27 March 2000 Release 2.22 Notes for New Users of PCCTS Version 1.33MR22
18
subroutine arguments the hiding fails and the user needs to code the cast manually. See also Item #163.
#91. Some examples of
#(...)
notation using the
PCCTS
list notation
See page 45 of the 1.00 manual for a description of the
PCCTS
list notation.
a: A ;
b: B ;
c: C ;
#token T_abc
r : a b c <<;>> ;/* AST list (0 A B C) without root */
r!: a b c <<#0=#(0,#1,#2,#3);>> ;/* AST list (0 A B C) without root */
r : a! b! c! <<#0=#(0,#1,#2,#3);>> ;/* AST list (0 A B C) without root */
r : a^ b c ;/* AST tree (A B C) with root A */
r!: a b c <<#0=#(#1,#2,#3);>> ;/* AST tree (A B C) with root A */
r!: a b c <<#0=#(#[T_abc],#1,#2,#3);>>
;/* AST tree (T_abc_node A B C) */
/* with root T_abc_node */
r : a b c <<#0=#(#[T_abc],#0);>> ; /* the same as above */
r : a! b! c! <<#0=#(#[T_abc],#1,#2,#3);>> ; /* the same as above */
#92. A rule which derives epsilon can short circuit its caller's explicitly constructed AST
When a rule derives epsilon it will return an AST value of 0. As the routine which constructs the AST tree
(ASTBase::tmake) has a variable length argument list which is terminated by 0, this can cause problem with
#(...)
lists that have more than two elements:
rule ! : DO body:loop_body END_DO <<#0=#(#[DO],#body,#[END_DO];>> ;
loop_body : { statement_list } ; /* can return 0 on DO END_DO */
Although this particular example could be handled by automatic tree construction, the problem is a real one when
constructing a tree by adding more than one sibling at a time. This problem does not exist for automatically
constructed AST trees because those trees are constructed one element at a time. Contributed by T. Doan
(tdoan@bnr.ca).
#93. How to use automatic AST tree construction when a token code depends on the alternative chosen
Suppose one wants to make the following transformation:
rule : lv:lhs ; => #(#[T_simple],#lv)
rule : lv:lhs rv:rhs ; => #(#[T_complex],#lv,#rv)
Both lhs and rhs considered separately may be suitable for automatic construction of ASTs, but the change in token
type from "T_simple" to "T_complex" appears to require manual tree construction. Use the following idiom:
rule : lhs (
| rhs <<#0=#(#[T_complex],#0);>>
() <<#0=#(#[T_simple],#0);>>
) ;
Another solution:
rule : <<ANTLRTokenType t=T_simple;>>
l:lhs { r:rhs <<t=T_complex;>> } <<#0=#(#[t],#0);>> ;
#94. For doubly linked ASTs derive from class ASTDoublyLinkedBase and call tree­>double_link(0,0)
The ASTDoublyLinkedBase class adds "up" and "left" fields to the AST definition, but it does not cause them to be
filled in during AST construction. After the tree is built call tree->double_link(0,0) to traverses the tree and fill in
the up and left fields.
#95. When ASTs are constructed manually the programmer is responsible for deleting them on rule failure
It is worth a little bit of extra trouble to let
PCCTS
construct the AST for a rule automatically in order to obviate the
need for writing a fail action for a rule. A safer implementation might be to maintain a doubly linked list of all
ASTs from which an AST is removed when it is destroyed. See class NoLeakAST from Example #5.