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 |
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 |
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. |
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." |
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. |
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." |
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. |
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." |
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. |
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." |
Free forum by Nabble | Edit this page |