27 March 2000 Release 2.22 Notes for New Users of PCCTS Version 1.33MR22
17
The new AST (a single node) contains Stmt_With_Label in the token field - given a traditional version of
AST::AST(
ANTLR
TokenType,char *).
rule! : name:id COLON e:expr <<#0=#(#name,#e);>> ; /* a2 */
Creates an AST list with "name" at its root and "e" as its first (and only) child.
The following example (a3) is equivalent to a1, but more confusing, because the two steps above have been
combined into a single action:
rule! : name:ID COLON e:expr
/* a3 */
<<#0=#(#[Stmt_With_Label,$name->getText()],#e);>>;
#84.
The make-a-root operator for ASTs ("^") can be applied only to terminals (#token, #tokclass, #tokdef)
A child rule might return a tree rather than a single AST. Were this to happen it could not be made into a root as it
is
already
a root and the corresponding fields of the structure are in use. To make an AST returned by a called rule
a root use the expression: #(root-rule, sibling1, sibling2, sibling3).
addOp : "\+" | "\-";
#tokclass AddOp { "\+" "\-"}
/* OK */
add ! : expr ("\+"^ expr) ;
/* Wrong */
addExpr ! : expr (addOp^ expr) ;
/* OK */
addExpr ! : expr (AddOp^ expr);
#85.
An already constructed AST tree cannot be the root of a new tree
An AST tree (unless it's a trivial tree with no children) already has made use of the "down" field in its structure.
Thus one should be suspicious of any constructs like the following:
rule! : anotherRule:rule2........ <<#0=#(#
anotherRule
,...);>> ;
#86.
Don't assign to #0 unless automatic construction of ASTs is disabled using the "!" operator on a rule
a! : xx:x yy:y zz:z <<#0=#(#xx,#yy,#zz);>> ; // ok
a : xx:x yy:y zz:z <<#0=#(#xx,#yy,#zz);>> ; // NOT ok
The reason for the restriction is that assignment to #0 will cause any ASTs pointed to by #0 to be lost when the
pointer is overwritten.
#87.
The statement in Item #86 is stronger than necessary
You can assign to #0 even when using automated AST construction if the old tree pointed to by #0 is part of the new
tree constructed by
#(...)
. For example:
#token Comma ","
#token Stmt_List
stmt_list: stmt (Comma stmt)* <<#0=#(#[Stmt_List],#0);>> ;
The automatically constructed tree pointed to by #0 is just put at the end of the new list, so nothing is lost. If you
reassign to #0 in the middle of the rule, automatic tree construction will result in the addition of remaining elements
at the end of the new tree. This is not recommended by TJP.
Special care must be used when combining the make-a-root operator (e.g. rule: expr Op^ expr) with this
transgression (assignment to #0 when automatic tree construction is selected).
#88.
A rule that constructs an AST returns an AST even when its caller uses the "!" operator
#89.
(C++ mode) Without
ANTLR
RefCountToken, a token which isn't used in an AST will result in lost memory
For a rule like the following:
rule : FOR^ lValue EQ! expr TO! expr BY! expr ;
the tokens "EQ", "TO", and "BY" are not incorporated into any AST. In C mode the memory they occupied (they
are called
attributes
in C mode) would be recovered on rule exit. In C++ mode their memory will be lost unless the
ANTLR
Token class is derived from
ANTLR
RefCountToken. Another approach is to use the NoLeakToken class from
Example #4.
#90.
When passing
#(...)
or
#[...]
to a subroutine it must be cast from "ASTBase *" to "AST *"
Most of the
PCCTS
internal routines are declared using ASTBase rather than AST because they don't depend on
behavior added by the user to class AST. Usually
PCCTS
hides this by generating explicit casts, but in the case of