Parsing
Parsing
An EBNF grammar that parses infix notation will usually look like this:
expression ::= equality-expression
equality-expression ::= additive-expression ( ( '==' | '!=' ) additive-expression ) *
additive-expression ::= multiplicative-expression ( ( '+' | '-' ) multiplicative-expression ) *
multiplicative-expression ::= primary ( ( '*' | '/' ) primary ) *
primary ::= '(' expression ')' | NUMBER | VARIABLE | '-' primary
With many levels of precedence, implementing this grammar with a predictive recursive-descent parser
can become inefficient. Parsing a number, for example, can require five function calls (one for each
non-terminal in the grammar, until we reach primary).
An operator-precedence parser can do the same more efficiently. The idea is that we can left associate
the arithmetic operations as long as we find operators with the same precedence, but we have to save a
temporary result to evaluate higher precedence operators. The algorithm that is presented here does not
need an explicit stack: instead, it uses recursive calls to implement the stack.
The algorithm is not a pure operator-precedence parser like the Dijkstra shunting yard algorithm. It
assumes that the primary nonterminal is parsed in a separate subroutine, like in a recursive descent
parser.
Pseudo-code
The pseudo-code for the algorithm is as follows. The parser starts at function parse_expression.
Precedence levels are greater or equal to 0.
parse_expression ()
return parse_expression_1 (parse_primary (), 0)