27 March 2000 Release 2.22 Notes for New Users of PCCTS Version 1.33MR22
19
Rules
#96.
To refer to a field of an
ANTLR
Token within a rule's action use
<<... mytoken($x)->field...>>
ANTLR
puts all "
ANTLR
Token *" variables in an
ANTLR
TokenPtr object in order to maintain reference counts for
tokens. When the reference counter goes to zero the token is deleted (assuming that the
ANTLR
Token definition is
derived from
ANTLR
RefCountToken). One result of this is that rule actions which need to refer to a real
ANTLR
Token field must first convert an
ANTLR
TokenPtr to an "
ANTLR
Token *" using the macro "mytoken":
number: n:Number <<if (mytoken($n)->value < 0) {...};>>
#97.
Rules don't return tokens values, thus this won't work:
rule: r1:rule1 <<...$r1...>>
In earlier versions of
PCCTS
(C mode) it was accepted practice to assign an attribute to a rule:
rule : rule1 <<$0=$1;>>
However, with the introduction of symbolic tags for labels (Item #79) this feature became deprecated for C mode
(Item #189) and is not even supported for C++ mode. To return a pointer to a token (
ANTLR
TokenPtr) from a rule
use inheritance (See Item #113):
statement
: <<ANTLRTokenPtr t;>> rule > [t] ;
rule > [ANTLRTokenPtr t]
: x:X <<$t=someAction($x);>>
It's still standard practice to pass back AST information using assignment to #0 and to refer to such return values
using labels on rules. It's also standard practice to refer to tokens associated with
terminals
:
rule : xx:X <<...$xx...>> // okay: "X" is a terminal (token)
rule : xx:x <<...$xx...>> // won't work: "x" is a rule rather
x : xx:X <<$x=$xx;>> // than a terminal (token)
#98.
A simple example of rewriting a grammar to remove left recursion
ANTLR
can't handle left-handed recursion. A rule such as:
expr : expr Op expr
| Number
| String
;
will have to be rewritten to something like this:
expr : Number (Op expr)*
| String (Op expr)*
;
#99.
A simple example of left-factoring to reduce the amount of
ANTLR
lookahead
Another sort of transformation required by
ANTLR
is left-factoring:
rule : STOP WHEN expr
| STOP ON expr
| STOP IN expr
;
These are easily distinguishable when
k
=2, but with a small amount of work it can be cast into a
k
=1 grammar:
rule : STOP ( WHEN expr
| ON expr
| IN expr
) ;
or:
rule : STOP rule_suffix
;
rule_suffix : WHEN expr
| ON expr
| IN expr
;
An extreme case of a grammar requiring a rewrite is in Example #11.