Damien Cassou
Damien Cassou

Reputation: 2589

How can a PetitParser parse rule signal an error?

I want a parse rule that only recognizes numbers between 0 and 32767. I tried something like:

integerConstant
  ^ (#digit asParser min: 1 max: 5) flatten
      ==> [ :string | | value |
            value := string asNumber.
            (value between: 0 and: 32767)
              ifTrue: [ value ]
              ifFalse: [ **???** ]]

But I have no idea what to write for the ???. I thought about return a PPFailure, but this requires knowing the stream position.

Upvotes: 4

Views: 196

Answers (1)

Lukas Renggli
Lukas Renggli

Reputation: 8947

As you suspect, you can make the action return a PPFailure. While in general this is not good style (mixes syntactic and semantic analysis) it is sometimes helpful. In the tests of PetitParser there are a few examples. Good uses you see at PPXmlGrammar>>#element and PPSmalltalkGrammar>>#number.

The position of a PPFailure is just something PetitParser provides to its users (tools). It is not something used for the parsing itself, thus you can set it to 0 if you feel lazy. Alternatively you can fetch the current position in the input using the following example:

positionInInput
    "A parser that does not consume anything, that always succeeds and that 
     returns the current position in the input."

    ^ [ :stream | stream position ] asParser

integerConstant
    ^ (self positionInInput , (#digit asParser min: 1 max: 5) flatten) map: [ :pos :string |
        | value |
        value := string asNumber.
        (value between: 0 and: 32767)
           ifTrue: [ value ]
           ifFalse: [ PPFailure message: value , ' out of range' at: pos ] ]

Upvotes: 8

Related Questions