3

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.

Damien Cassou
  • 2,555
  • 1
  • 16
  • 21

1 Answers1

7

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 ] ]
Lukas Renggli
  • 8,754
  • 23
  • 46
  • Ok, crazy solution but works :-). Did you write "self positionInput" on purpose or did you meant "positionInput" as an instance variable? – Damien Cassou Mar 13 '13 at 16:16
  • You don't need instance variables for rules that are not used in cycles. If the parser `positionInInput` is common enough it could be moved into a factory method somewhere, or even in its own PPParser subclass. – Lukas Renggli Mar 16 '13 at 23:21