-
Notifications
You must be signed in to change notification settings - Fork 1
Parser Stack
If you want to create some sort of Abstract Syntax Tree (AST) or you want the parser to return a calculated result (i.e an interpreter), the best option is to do this via the parser stack.
The stack can be accessed in any rule using the rule context object.
There are various operations available on the stack, like push, pop, peek, poke, swap, dup etc. (For more details on available operations see Rules#action-rules).
The type of objects on the stack is determined by the generic type parameter of AbstractGrammar<T>
(in the example below T
is Int
).
If a rule fails, the state of the parser is reset to the state before the rule was executed.
open class IntegerAdderGrammar : AbstractGrammar<Int>() {
override fun start(): Rule<Int> = expression() + eoi()
open fun expression(): Rule<Int> = integer() + zeroOrMore(add() + integer() + push { pop(it) + pop(it) })
open fun add(): Rule<Int> = char('+') + whitespaces()
open fun integer(): Rule<Int> =
optional(char('-')) + oneOrMore(digit()) + push { it.previousMatch.toString().toInt() } + whitespaces()
open fun whitespaces(): Rule<Int> = zeroOrMore(whitespace())
}
In the example above the integer
rule pushes the parsed Int
value on the stack. The expression
rule pops two Int
s for each partial addition from the stack and pushes the result back to the stack, leaving one Int
on the stack after all additions are processed. At the end of the parser run, there will be one Int
value on the stack.
In examples/calculator there is a more extensive example of how to use the parser stack in an interpreter-like manner.
In examples/json you can find an example that puts a tree structure (i.e. a tree representation of a Json) onto the stack.