Clone wiki

stx:goodies/petitparser / Limitations

Limitations

PetitCompiler contains several limitations, i.e., it cannot (efficiently) compile any working parser. This due to the fact that PetitParser allows any arbitrary code.

Limitations on action blocks

By action blocks we mean blocks that are executed when child parser consumes input. They're created by #==> and map: messages, i.e.,

#letter asParser / (#letterOrDigit asParser) ==> [:chars | String withAll: chars ]

or

#letter asParser / (#digit asParser) map: [:letter :digit | String with: letter with: digit ]

Generally speaking, action blocks are required to be purely functional. In practice this means they may not access any state nor they may do a super-send. This requirement is transitive, i.e., all self-sent methods must be purely functional.

Strictly speaking, from within an action block defined in class C, you may not:

  • read or assign any instance variable of class C
  • read or assign any class variable of class C
  • do a super-send
  • do a self-send to non-existing method

If actions blocks are not functional, an error (instance of PPCCompilationError) is raised with a message like code not functional: ... where ... gives more detail on what's wrong.

Accessing properties from within action blocks

Strictly speaking, accessing PPParser's properties leads to accessing and instance variable and therefore is forbidden. However, is storing some sort of state during parsing is absolutely unavoidable, PetitCompiler provides an option to get around this limitation.

If the parser is compiled with option #allowProperties set to true, the parser compiler allows accessing properties via properties API (see class PPParser protocol accessing-properties). However, the values of all properties MUST be lazy initialized - never use #propertyAt:, always use #propertyAt:isAbsent:.

For example. following is allowed

semiSeen
   ^self propertyAt: #semiSeen isAbsent:[ false ]

semiSeen: aBoolean
   ^self propertyAt: #semiSeen put: aBoolean

semi
   ^$; asParser ==> [:semi | self semiSeen: true. semi ]

given that parser is compiled with #allowProperties like:

SomeParser compileWithOptions: #( allowProperties: true )

If properties are not lazy-initialized, the behaviour is undefined.

Updated