Go to the first, previous, next, last section, table of contents.
Inherited attributes are attributes that are passed to a rule, as opposed to synthesized attributes, which are returned from a rule.
As an example, we rewrite example 5 to handle the operator priorities within a single rule: the priority of the expression surrounding the subexpression being handled is passed as an attribute. For this purpose, we define some constants to give names to the various priorities.
%class ex6 %instance { redeclare Lexer lex; const PRIO_EXPR = 0; const PRIO_ADDSUB = 1; const PRIO_MULDIV = 2; const PRIO_UNARY = 3; } %token NUMBER
The expr
rule is modified to accept a the priority of the
expression that it is to parse. When, for example, an subexpression
must be parsed at priority PRIO_ADDSUB
, a multiplication must be
parsed before the subexpression is completed. If, however, another
addition is encountered, the subexpression is finished (since parsing
the addition before returning would imply right-associativity, which is
not the desired semantics).
The expr
rule becomes:
expr (> int priority, < int value) { int right; } : atom (value) [ { if (priority >= PRIO_ADDSUB) return; } '+' expr (PRIO_ADDSUB, right) { value += right; } | { if (priority >= PRIO_ADDSUB) return; } '-' expr (PRIO_ADDSUB, right) { value -= right; } | { if (priority >= PRIO_MULDIV) return; } '*' expr (PRIO_MULDIV, right) { value *= right; } | { if (priority >= PRIO_MULDIV) return; } '/' expr (PRIO_MULDIV, right) { value /= right; } ]* ;
A top-level invocation of the expr
rule becomes
expr (PRIO_EXPR, result)
A closer look at the branches in the expr
reveals a very common
structure:
{ if (priority >= PRIO_ADDSUB) return; } '+' expr (PRIO_ADDSUB, right)
A particular branch will be selected when the current token matches (in
this case, it would be a `+'). However, when the priority of the
next operator is not higher than that of the expression already being
parsed (passed as an attribute in priority
), the return
is
executed and the operator token still remains to be taken from the
input, for the invoking rule to digest it and correctly accept an
expression.
Go to the first, previous, next, last section, table of contents.