PetitParser question

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

PetitParser question

khinsen
Dear parsing experts,

I have been working on a medium-size parser using the PetitParser
framework, which so far has been a very productive environment.  But now
I have a problem to which I could not find the solution in "Deep into
Pharo", nor by searching around in the code.

One of my production rules requires several parsed items to be equal.
It should accept expressions such as

    1 + 3 + 2 + 6
    2 * 9 * 3 * 6
    0 - 8 - 5 - 3

but not expressions that mix different operators (because my grammar has
no precedence rules and thus requires parentheses for disambiguation).

In various other parsing frameworks, I do this by parsing up to the
first operator, retrieving it, and permitting only that same string in
the following. But I haven't found a way to do this in PetitParser, nor
any other obvious solution.

The only solution I see right now is to have one production rule per
operator, but that makes for a huge grammar. Is there another way?

Thanks in advance,
  Konrad

Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

tomo
Dear Konrad,

This post might help you. In case of PetitParser2, it's PP2Failure instead
of PPFailure.
https://stackoverflow.com/questions/15371334/how-can-a-petitparser-parse-rule-signal-an-error

Best Regards,
---
tomo



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

khinsen
Dear Tomo,

> This post might help you. In case of PetitParser2, it's PP2Failure instead
> of PPFailure.
> https://stackoverflow.com/questions/15371334/how-can-a-petitparser-parse-rule-signal-an-error

That's indeed a possible solution: parse for arbitrary operators, and
then add a test for equality that can make everything fail in the end. I
will try it out!

Thanks,
   Konrad.


Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

Tudor Girba-2
Hi Konrad,

A somewhat similar issue is present in an XML grammar: the closing element must match the opening element. In PPXmlGrammar, you have a condition that matches it and throws a failure otherwise:

element
        "[39]   element   ::=   EmptyElemTag | STag content ETag"
       
        ^ $< asParser , qualified , attributes , whitespace optional , ('/>' asParser / ($> asParser , content , [ :stream | stream position ] asParser , '</' asParser , qualified , whitespace optional , $> asParser)) ==> [ :nodes |
                nodes fifth = '/>'
                        ifTrue: [ Array with: nodes second with: nodes third with: #() ]
                        ifFalse: [
                                nodes second = nodes fifth fifth
                                        ifTrue: [ Array with: nodes second with: nodes third with: nodes fifth second ]
                                        ifFalse: [ PPFailure message: 'Expected </' , nodes second qualifiedName , '>' context: nil at: nodes fifth third ] ] ]

Cheers,
Doru


> On Jan 27, 2019, at 4:38 PM, Konrad Hinsen <[hidden email]> wrote:
>
> Dear Tomo,
>
>> This post might help you. In case of PetitParser2, it's PP2Failure instead
>> of PPFailure.
>> https://stackoverflow.com/questions/15371334/how-can-a-petitparser-parse-rule-signal-an-error
>
> That's indeed a possible solution: parse for arbitrary operators, and then add a test for equality that can make everything fail in the end. I will try it out!
>
> Thanks,
>  Konrad.
>
>

--
www.feenk.com

"Not knowing how to do something is not an argument for how it cannot be done."


Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

khinsen
Hi Doru,

Thanks for pointing out the use case in XML, which gave me an
opportunity to play around with this with almost no
effort. Unfortunately there seems to be a bug in how PPXmlParser
constructs the PPFailure message
(freshly reported:
https://github.com/moosetechnology/PetitParser/issues/38).

More generally, there seems to be a bug in how PetitParser handles
PPFailure return values. The actually reported error is always different
from what is passed to PPFailure. I love software ;-)

Konrad.

Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

Tudor Girba-2
Hi,


> On Jan 29, 2019, at 6:31 PM, Konrad Hinsen <[hidden email]> wrote:
>
> Hi Doru,
>
> Thanks for pointing out the use case in XML, which gave me an
> opportunity to play around with this with almost no
> effort. Unfortunately there seems to be a bug in how PPXmlParser
> constructs the PPFailure message
> (freshly reported:
> https://github.com/moosetechnology/PetitParser/issues/38).

Yes, I saw it. I mostly pointed you to the example. We originally built PPXmlParser as an example, and not so much as a production parser.

But, does it solve your problem?

> More generally, there seems to be a bug in how PetitParser handles
> PPFailure return values. The actually reported error is always different
> from what is passed to PPFailure. I love software ;-)

What do you mean?

Cheers,
Doru

> Konrad.

--
www.feenk.com

"If you interrupt the barber while he is cutting your hair,
you will end up with a messy haircut."


Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

khinsen
Tudor Girba <[hidden email]> writes:

> But, does it solve your problem?

Not yet. Not sure it will.

>> More generally, there seems to be a bug in how PetitParser handles
>> PPFailure return values. The actually reported error is always different
>> from what is passed to PPFailure. I love software ;-)
>
> What do you mean?

If I return

    PPFailure message: 'whatever' at: 0

from my parser, then it does fail but it reports a different error.

After some more experiments, it looks like this is perhaps not a bug,
but a feature that makes returning failures not so useful after all. I
suspect that PetitParser simply backtracks after my failure and tries a
different rule that then fails as well.

A simple example:

   | p |
   p := #digit asParser plus flatten
    ==> [ :value | value asSet size = 1 ifTrue: [ value ] ifFalse: [ PPFailure message: 'not equal' at: 0 ]].
   p parse: '22233'

The reported failure is "digit expected at 5".

On the other hand, if there is no path for backtracking, the reported
failure is the expected one:

   | p |
   p := (#digit asParser, #digit asParser) flatten
    ==> [ :value | value first = value second ifTrue: [ value ] ifFalse: [ PPFailure message: 'not equal' at: 0 ]].
   p parse: '23'

Konrad.

Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

Tudor Girba-2
Hi,


> On Jan 29, 2019, at 7:04 PM, Konrad Hinsen <[hidden email]> wrote:
>
> Tudor Girba <[hidden email]> writes:
>
>> But, does it solve your problem?
>
> Not yet. Not sure it will.

Would this not work:

p := (#digit asPParser separatedBy: ($+ asPParser / $- asPParser) trim) ==> [:tokens |
        | result |
        result := tokens.
        2 to: tokens size - 1 by: 2 do: [ :index |
                (tokens at: index) = (tokens at: 2)
                        ifFalse: [result := PP2Failure message: 'expected ', (tokens at: 2) asString, ' but got ', (tokens at: index) asString ]].
        result ].


p end parse: '1+3+2 - 6' "a PP2Failure: 'expected + but got -‘"
p end parse: '1+3+2 + 6'  "#($1 $+ $3 $+ $2 $+ $6)”

?

Please note that I used PetitParser2 for this one because it also addresses the failure message issue you raised below. However, the logic would work in PP1 as well.


Cheers,
Doru



>>> More generally, there seems to be a bug in how PetitParser handles
>>> PPFailure return values. The actually reported error is always different
>>> from what is passed to PPFailure. I love software ;-)
>>
>> What do you mean?
>
> If I return
>
>    PPFailure message: 'whatever' at: 0
>
> from my parser, then it does fail but it reports a different error.
>
> After some more experiments, it looks like this is perhaps not a bug,
> but a feature that makes returning failures not so useful after all. I
> suspect that PetitParser simply backtracks after my failure and tries a
> different rule that then fails as well.
>
> A simple example:
>
>   | p |
>   p := #digit asParser plus flatten
>   ==> [ :value | value asSet size = 1 ifTrue: [ value ] ifFalse: [ PPFailure message: 'not equal' at: 0 ]].
>   p parse: '22233'
>
> The reported failure is "digit expected at 5".
>
> On the other hand, if there is no path for backtracking, the reported
> failure is the expected one:
>
>   | p |
>   p := (#digit asParser, #digit asParser) flatten
>   ==> [ :value | value first = value second ifTrue: [ value ] ifFalse: [ PPFailure message: 'not equal' at: 0 ]].
>   p parse: '23'
>
> Konrad.

--
www.feenk.com

"Quality cannot be an afterthought."


Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

khinsen
Tudor Girba <[hidden email]> writes:

> Would this not work:

It works. And as much as I hate to admit it, my version of yesterday was
very similar except ... that it lacked a set of parentheses :-(

> Please note that I used PetitParser2 for this one because it also
> addresses the failure message issue you raised below. However, the
> logic would work in PP1 as well.

It does, but I ended up switching to PP2 as well to get the right error
messages.

Thanks a lot,
  Konrad.

Reply | Threaded
Open this post in threaded view
|

Re: PetitParser question

Tudor Girba-2
Great. I am happy you found a solution :)

Cheers,
Doru


> On Jan 30, 2019, at 3:37 PM, Konrad Hinsen <[hidden email]> wrote:
>
> Tudor Girba <[hidden email]> writes:
>
>> Would this not work:
>
> It works. And as much as I hate to admit it, my version of yesterday was
> very similar except ... that it lacked a set of parentheses :-(
>
>> Please note that I used PetitParser2 for this one because it also
>> addresses the failure message issue you raised below. However, the
>> logic would work in PP1 as well.
>
> It does, but I ended up switching to PP2 as well to get the right error
> messages.
>
> Thanks a lot,
>  Konrad.

--
www.feenk.com

"We cannot reach the flow of things unless we let go."