Smalltalk PetitParser解析规则如何发出错误信号?

Smalltalk PetitParser解析规则如何发出错误信号?,smalltalk,pharo,petitparser,Smalltalk,Pharo,Petitparser,我想要一个只识别0到32767之间的数字的解析规则。我试过这样的方法: integerConstant ^ (#digit asParser min: 1 max: 5) flatten ==> [ :string | | value | value := string asNumber. (value between: 0 and: 32767) ifTrue: [ value ]

我想要一个只识别0到32767之间的数字的解析规则。我试过这样的方法:

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

但我不知道该写些什么???。我考虑过返回PPFailure,但这需要知道流的位置。

正如您所怀疑的,您可以使操作返回PPFailure。虽然一般来说,这不是一种好的风格(混合了句法和语义分析),但有时还是有帮助的。在PetitPasser的测试中,有几个例子。您可以在
PPXmlGrammar>#element
PPSmalltalkGrammar>>#number
中看到良好的用法

PPFailure的位置只是PetitPasser提供给其用户的东西(工具)。它不是用于解析本身的东西,因此如果您感到懒惰,可以将其设置为0。或者,您可以使用以下示例获取输入中的当前位置:

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 ] ]

好的,疯狂的解决方案,但有效:-)。您是有意编写“self positionInput”还是将“positionInput”作为实例变量?对于不在循环中使用的规则,您不需要实例变量。如果解析器
positionInInput
足够常见,则可以将其移动到某个地方的工厂方法中,甚至移动到它自己的PPParser子类中。