Hi,
On Jan 29, 2019, at 7:04 PM, Konrad Hinsen <konrad.hinsen@fastmail.net> wrote:
Tudor Girba <tudor@tudorgirba.com> 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."