Escolar Documentos
Profissional Documentos
Cultura Documentos
CMSC CS431
UMBC
So far a parser traces the derivation of a sequence of tokens The rest of the compiler needs a structural representation of the program Abstract syntax trees
Like parse trees but ignore some details Abbreviated as AST
UMBC
UMBC
UMBC
Source Program
Program input
Tokens
UMBC
e e + e 5 15 e * e 20
*
20
6
UMBC
If-then-else S1 ELSE S2
S1
S2
UMBC
Constructing AST
Grammar:
E ::= E + T | E T | T T ::= (E) | id | num
Bottom-up: synthesized attribute if we know the AST of each child, how to compute the AST of the parent?
8
UMBC
T ::= num
T.nptr=mkleaf_num(num.val)
9
UMBC
E1 +
T1 ( E2 T2 15
T4
E3 ) T3 b
UMBC
Implementing AST in C
Grammar: E ::= E + T | E T | T T ::= (E) | id | num
Define AST node construction routines ASTnode* mkleaf_id(symbol_table_entry* e); ASTnode* mkleaf_num(int n); ASTnode* mknode_plus(struct ASTnode* opd1, struct ASTNode* opd2); ASTnode* mknode_minus(struct ASTnode* opd1, struct ASTNode* opd2);
11
UMBC
Define AST node construction routines ASTexpression* mkleaf_id(symbol_table_entry* e); ASTexpression* mkleaf_num(int n); ASTexpression* mknode_plus(struct ASTnode* opd1, struct ASTNode* opd2); ASTexpression* mknode_minus(struct ASTnode* opd1, struct ASTNode* opd2);
12
class ASTexpression { public ASTNodeTag kind(); }; class ASTidentifier inherit ASTexpression { private symbol_table_entry* id_entry; } class ASTvalue inherit ASTexpression { private int num_value; } class ASTplus inherit ASTexpression { private ASTnode* opds[2]; } Class ASTminus inherit ASTexpression { private ASTnode* opds[2]; ... }
UMBC
More ASTs
Abstract syntax: S::= if-else E S S | while E S | E | E::= var | num | true | false | E bop E | uop E bop ::= < | <= | > | >= | && | = | + | * | . uop ::= - | * | & |
class ASTstmt {} class ASTifElse inherit ASTstmt { private ASTexpr* cond; private ASTstmt* tbranch; private ASTstmt* fbranch; } class ASTwhile inherit ASTstmt { private ASTexpr* cond; private ASTstmt* body;} class ASTexpr inherit ASTstmt {} class ASTvar inherit ASTexpr {}
13
UMBC
AST Covered
We built AST by hand in the 1st Project Lets start to see about an automated approach. Lets see what the Galles text (see slide 1542) comes to say about AST Later we will look at some code
14
UMBC
UMBC
Equations
E.val = E1.val + E2.val E1.val = int5.val = 5 E2.val = E3.val E3.val = E4.val + E5.val E4.val = int2.val = 2 E5.val = int3.val = 3
16
UMBC
Example:
E3.val = E4.val + E5.val Must compute E4.val and E5.val before E3.val We say that E3.val depends on E4.val and E5.val
17
UMBC
Dependency Graph
E + E2 ( E3 + 2
E1
+
5 E4 int2
Each node labeled E has one slot for the val attribute Note the dependencies
int5
+
E5 int3 3
18
UMBC
Evaluating Attributes
An attribute must be computed after all its successors in the dependency graph have been computed
In previous example attributes can be computed bottom-up
19
UMBC
Synthesized attributes
Calculated from attributes of descendents in the parse tree E.val is a synthesized attribute Can always be calculated in a bottom-up order
UMBC
Recursive-descent interpreter Consider this grammar S -> E $ E -> T E E-> +T E E -> - T E T -> F T T -> * F T T -> / F T F -> id F -> num F -> ( E )
E-> T ->
UMBC
Recursive-descent interpreter
int T() { switch (tok.kind) { case ID: case NUM: case LPAREN return Tprime( F() ); default:print(expected ID, NUM, or left-paren); skipto(T_follow); return 0; }} int Tprime(int a) {switch (tok.kind) { case TIMES: eat(TIMES); return Tprime(a*F()); case DIVIDE: eat(DIVIDE); return Tprime(a/F()); case PLUS: case MINUS: case RPAREN: case EOF: return a; default: /* error handling */ }}
22
UMBC
JavaCC version
Grammar S -> E $ E -> T ( + T | - T)* T -> F ( * F | - F)* F -> id | num | ( E ) Note: E > T E E -> + T E | - T E | e
23
UMBC
JavaCC version
void Start() : { int i; } { i=Exp() <EOF> {System.out.println(i); } } int Exp() : { int a, i; } { a=Term() ( + i=Term() { a=a+i; } | - i=Term() { a=a+i; } )* { return a; } } Int Factor() : { Token t; int i; } { t = <IDENTIFIER > {return lookup(t.image); } | t=<INTEGER_LITERAL> {return Integer.parseInt(t.image);} | ( i=Exp() ) {return i; } }
24
UMBC
We can now illustrate how semantic actions are implemented for LR parsing Keep attributes on the stack
UMBC
UMBC
| int * int + int int3 | * int + int int3 * | int + int int3 * int5 | + int int3 * T5 | + int T15 | + int T15 + | int T15 + int8 | T15 + T8 | T15 + E8 | E23 |
UMBC
Inherited Attributes
Another kind of attribute Calculated from attributes of parent and/or siblings in the parse tree
28
UMBC
A Line Calculator
Each line contains an expression E int | E + E Each line is terminated with the = sign LE= | +E= In second form the value of previous line is used as starting value A program is a sequence of lines P e|PL
29
UMBC
We need the value of the previous line We use an inherited attribute L.prev
30
UMBC
Example
31
UMBC
P + E4 int2 2
L
E3 +
+ prev inherited
+ E5 int3
=
All can be computed in depth-first order
32
UMBC
Semantic actions can be used to build ASTs And many other things as well
Also used for type checking, code generation,
33
UMBC
Constructing An AST
mkplus(
T1
T2
T1
T2
34
UMBC
UMBC
Consider the string int5 + ( int2 + int3 ) A bottom-up evaluation of the ast attribute:
E.ast = mkplus(mkleaf(5), mkplus(mkleaf(2), mkleaf(3)) PLUS PLUS
3
36
UMBC
Review
We can specify language syntax using CFG A parser will answer whether s L(G) and will build a parse tree which we convert to an AST and pass on to the rest of the compiler
37
UMBC
UMBC
public abstract class Exp { public abstract int eval(): } public class PlusExp extends Exp { private Exp e1, e2; public PlusExp(Exp a1, Exp a2) { e1=a1; d2=a2; } public int eval() { return e1.eval()+e2.eval(): } } public class Identifier extends Exp { private String f0; public Indenfifier(String n0) { f0 = n0; } public int eval() { return lookup(f0); } } public class IntegerLiteral extends Exp { private String f0; public IntegerLiteral(String n0) { f0 = n0; } public int eval() { return Integer.parseInt(f0); } }
39
UMBC
Exp Start() : { Exp e; } { e=Exp() { return e; }} Exp Exp() : { Exp e1, e2; } { e1=Term() ( + e2=Term() { e1=new PlusExp(e1,e2); } | - e2=Term() { e1=new MinusExp(e1,e2); } )* { return a; } } Exp Factor() : { Token t; Exp e; } { t = <IDENTIFIER > {return new Identifier(t.image); } | t=<INTEGER_LITERAL> {return new IntegerLiteral(t.image);} | ( e=Exp() ) {return e; } }
40
UMBC
Positions
AST must keep the pos fields, which indicate the position within the original source file. Lexer must pass the information to the parser. Ast node constructors must be augmented to init the pos fields.
41
UMBC
Unfortunately, .
42
UMBC
Visitors
Visitor pattern
Visitor implements an interpretation. Visitor object contains a visit method for each syntax-tree class. Syntax-tree classes contain accept methods. Visitor calls accept(what is your class?). Then accept calls the visit of the visitor.
43
UMBC
public abstract class Exp { public abstract int accept(Visitor v): } public class PlusExp extends Exp { private Exp e1, e2; public PlusExp(Exp a1, Exp a2) { e1=a1; d2=a2; } public int accept(Visitor v) { return v.visit(this) ; } } public class Identifier extends Exp { private String f0; public Indenfifier(String n0) { f0 = n0; } public int accept(Visitor v) { return v.visit(this) ; } } public class IntegerLiteral extends Exp { private String f0; public IntegerLiteral(String n0) { f0 = n0; } public int accept(Visitor v) { return v.visit(this) ; } }
44
UMBC
An interpreter visitor
public interface Visitor { public int visit(PlusExp n); public int visit(Identifier n); public int visit(IntegerLiteral n); } public class Interpreter implements Visitor { public int visit(PlusExp n) { return n.e1.accept(this) + n.e2.accept(this); } public int visit(Identifier n) { return looup(n.f0); } public int visit(IntegerLiteral n) { return Integer.parseInt(n.f0); }
45
UMBC
Package syntaxtree;
Program(MainClass m, ClassDecList c1) MainClass(Identifier i1, Identifier i2, Statement s) ---------------------------abstract class ClassDecl ClassDeclSimple(Identifier i, VarDeclList vl, methodDeclList m1) ClassDeclExtends(Identifier i, Identifier j, VarDecList vl, MethodDeclList ml) ----------------------------VarDecl(Type t, Identifier i) MethodDecl(Type t, Identifier I, FormalList fl, VariableDeclList vl, StatementList sl, Exp e) Formal(Type t, Identifier i)
46
UMBC
abstract class type IntArrayType() BooleanType() IntegerType() IndentifierType(String s) --------------------------abstract class Statement Block(StatementList sl) If(Exp e, Statement s1, Statement s2) While(Exp e, Statement s) Print(Exp e) Assign(Identifier i, Exp e) ArrayAssign(Identifier i, Exp e1, Exp e2) ------------------------------------------47
UMBC
abstract class Exp And(Exp e1, Exp e2) LessThan(Exp e1, Exp e2) Plus(Exp e1, Exp e2) Minus(Exp e1, Exp e2) Times(Exp e1, Exp e2) Not(Exp e) ArrayLookup(Exp e1, Exp e2) ArrayLength(Exp e) Call(Exp e, Identifier i, ExpList el) IntergerLiteral(int i) True() False() IdentifierExp(String s) This() NewArray(Exp e) NewObject(Identifier i) ------------------------------------------------Identifier(Sting s) --list classes------------------------ClassDecList() ExpList() FormalList() MethodDeclList() StatementLIst() VarDeclList()
48
UMBC
package syntaxtree; import visitor.Visitor; import visitor.TypeVisitor; public class Program { public MainClass m; public ClassDeclList cl;
UMBC
ClassDecl.java
package syntaxtree; import visitor.Visitor; import visitor.TypeVisitor; public abstract class ClassDecl { public abstract void accept(Visitor v); public abstract Type accept(TypeVisitor v); }
50
UMBC
ClassDeclExtends.java
package syntaxtree; import visitor.Visitor; import visitor.TypeVisitor; public class ClassDeclExtends extends ClassDecl { public Identifier i; public Identifier j; public VarDeclList vl; public MethodDeclList ml; public ClassDeclExtends(Identifier ai, Identifier aj, VarDeclList avl, MethodDeclList aml) { i=ai; j=aj; vl=avl; ml=aml; } public void accept(Visitor v) { v.visit(this); } public Type accept(TypeVisitor v) { return v.visit(this); } } 51
UMBC
StatementList.java
package syntaxtree; import java.util.Vector; public class StatementList { private Vector list; public StatementList() { list = new Vector(); } public void addElement(Statement n) { list.addElement(n); } public Statement elementAt(int i) { return (Statement)list.elementAt(i); } public int size() { return list.size(); } }
52
UMBC
Package Visitor/visitor.java
package visitor; import syntaxtree.*; public interface Visitor { public void visit(Program n); public void visit(MainClass n); public void visit(ClassDeclSimple n); public void visit(ClassDeclExtends n); public void visit(VarDecl n); public void visit(MethodDecl n); public void visit(Formal n); public void visit(IntArrayType n); public void visit(BooleanType n); public void visit(IntegerType n); public void visit(IdentifierType n); public void visit(Block n); public void visit(If n); public void visit(While n); public void visit(Print n); public void visit(Assign n); public void visit(ArrayAssign n); public void visit(And n); public void visit(LessThan n); public void visit(Plus n); public void visit(Minus n); public void visit(Times n); public void visit(ArrayLookup n); public void visit(ArrayLength n); public void visit(Call n); public void visit(IntegerLiteral n); public void visit(True n); public void visit(False n); public void visit(IdentifierExp n); public void visit(This n); public void visit(NewArray n); public void visit(NewObject n); public void visit(Not n); public void visit(Identifier n); } 53
UMBC
X = y.m(1,4+5)
Statement -> AssignmentStatement AssignmentStatement -> Identfier1 = Expression Identifier1 -> <IDENTIFIER> Expression -> Expression1 . Identifier2 ( ( ExpList)? ) Expression1 -> IdentifierExp IdentifierExp -> <IDENTIFIER> Identifier2 -> <IDENTIFIER> ExpList -> Expression2 ( , Expression3 )* Expression2 -> <INTEGER_LITERAL> Expression3 -> PlusExp -> Expression + Expression -> <INTEGER_LITERAL> , <INTEGER_LITERAL>
54
UMBC
AST
Statement s -> Assign (Identifier,Exp)
Identifier(x)
Call(Exp,Identifier,ExpList)
init
IdentifierExp(y)
Identifier(m)
ExpList e1
add
IntegerLiteral(1)
Plus(Exp,Exp)
add
IntegerLiteral(4)
(IntegerLiteral(5)
55
UMBC
MiniJava : Grammar(I)
56
UMBC
MiniJava : Grammar(II)
MainClass(Identifier, VarDeclList)
MainClass -> class id { public static void main ( String [] id ) { Statement } } ClassDecl -> class id { VarDecl * MethodDecl * } -> class id extends id { VarDecl* MethodDecl * } VarDecl
ClassDeclSimple(), ClassDecExtends()
-> Type id ;
VarDecl(Type, Identifier)
UMBC
MiniJava : Grammar(III)
->
FormalRest ->
, Type id
Type
58
UMBC
MiniJava : Grammar(IV)
Statement -> { Statement * } -> if ( Exp ) Statement else Statement -> while ( Exp ) Statement -> System.out.println ( Exp ) ; -> id = Exp ; -> id [ Exp ] = Exp ;
ExpList
ExpRest
UMBC
MiniJava : Grammar(V)
-> -> -> -> -> -> -> -> -> -> -> -> ->
Exp
id
this new int [ Exp ] new id ( ) ! Exp ( Exp )
60
UMBC
61
UMBC
References
Andrew W. Appel, Modern Compiler Implementation in Java (2nd Edition), Cambridge University Press, 2002 http://compiler.kaist.ac.kr/courses/cs420/cla sstps/Chapter05.pps Modern Compiler Design, Scott Galles, Scott Jones http://www.cs.utsa.edu/~qingyi/cs4713/hando uts/AbstractSyntaxTree.ppt
62
UMBC
Lecture Outline
64
UMBC
Introduction
The Java Tree Builder (JTB) is a tool used to automatically generate syntax trees with the Java Compiler Compiler (JavaCC) parser generator. Its based on the Visitor design pattern please see the section entitled Why Visitors?
65
UMBC
Why Visitors?
The Visitor pattern is one among many design patterns aimed at making object-oriented systems more flexible The issue addressed by the Visitor pattern is the manipulation of composite objects. Without visitors, such manipulation runs into several problems as illustrated by considering an implementation of integer lists, written in Java
66
UMBC
interface List {} class Nil implements List {} class Cons implements List {
int head; List tail; }
What happens when we write a program which computes the sum of all components of a given List object?
67
UMBC
List l; // The List-object we are working on. int sum = 0; // Contains the sum after the loop. boolean proceed = true; What are the while (proceed) { if (l instanceof Nil) problems here? proceed = false; else if (l instanceof Cons) { sum = sum + ((Cons) l).head; // Type cast! l = ((Cons) l).tail; // Type cast! } }
68
UMBC
Type Casts?
We want static (compile time) type checking
Flexible?
Probably not well illustrated with this example
69
UMBC
interface List { int sum(); } class Nil implements List { public int sum() { return 0; } } class Cons implements List { int head; List tail; public int sum() { return head + tail.sum(); } }
70
UMBC
Tradeoffs
Can compute the sum of all components of a given List-object l by writing l.sum(). Advantage: type casts and instanceof operations have disappeared, and that the code can be written in a systematic way. Disadvantage: Every time we want to perform a new operation on List-objects, say, compute the product of all integer parts, then new dedicated methods have to be written for all the classes, and the classes must be recompiled
71
UMBC
interface List {
void accept(Visitor v);
} class Nil implements List { public void accept(Visitor v) { v.visitNil(this); } } class Cons implements List { int head; List tail; public void accept(Visitor v) { v.visitCons(this); } }
72
UMBC
class SumVisitor implements Visitor { int sum = 0; public void visitNil(Nil x) {} public void visitCons(Cons x){ sum = sum + x.head; x.tail.accept(this); } }
73
UMBC
Summary
Each accept method takes a visitor as argument. The interface Visitor has a header for each of the basic classes. We can now compute and print the sum of all components of a given List-object l by writing
SumVisitor sv = new SumVisitor(); l.accept(sv); System.out.println(sv.sum);
74
UMBC
Summary Continued
The advantage is that one can write code that manipulates objects of existing classes without recompiling those classes. The price is that all objects must have an accept method. In summary, the Visitor pattern combines the advantages of the two other approaches
75
UMBC
Summary Table
Frequent recompilation?
Yes
No
Dedicated methods
The Visitor pattern
No
No
Yes
No
76
UMBC
To begin using JTB, simply run it using your grammar file as an argument
Run JTB without any argumentsfor list.
This will generate an augmented grammar file, as well as the needed classes
77
UMBC
Details
jtb.out.jj, the original grammar file, now with syntax tree building actions inserted The subdirectory/package syntaxtree which contains a java class for each production in the grammar The subdirectory/package visitor which contains Visitor.java, the default visitor interface, also ObjectVisitor.java, another default visitor interface that supports return value and argument.
ObjectDepthFirst.java is a defualt implemetation of ObjectVisitor.java.
DepthFirstVisitor.java, a default implementation which visits each node of the tree in depth-first order.
78
UMBC
General Instructions
To generate your parser, simply run JavaCC using jtb.out.jj as the grammar file. Let's take a look at all the files and directories JTB generates.
79
UMBC
Named jtb.out.jj This file is the same as the input grammar file except that it now contains code for building the syntax tree during parse. Typically, this file can be left alone after generation. The only thing that needs to be done to it is to run it through JavaCC to generate your parser
80
UMBC
This directory contains syntax tree node classes generated based on the productions in your JavaCC grammar. Each production will have its own class. If your grammar contains 42 productions, this directory will contain 42 classes (plus the special automatically generated nodes-these will be discussed later), with names corresponding to the left-hand side names of the productions. Like jtb.out.jj, after generation these files don't need to be edited. Generate them once, compile them once, and forget about them
81
UMBC
Example
Let's examine one of the classes generated from a production. Take, for example, the following production
void ImportDeclaration() : {} { "import" Name() [ "." "*" ] "; }
82
UMBC
// Generated by JTB 1.1.2 // package syntaxtree; /** * Grammar production: * f0 -> "import" All parts of a production * f1 -> Name() are represented in the tree, * f2 -> [ "." "*" ] including tokens. * f3 -> ";" */ public class ImportDeclaration implements Node {
public NodeToken f0; public Name f1; public NodeOptional f2; public NodeToken f3;
83
UMBC
Notice the package "syntaxtree". The purpose of separating the generated tree node classes into their own package is that it greatly simplifies file organization, particularly when the grammar contains a large number of productions. Its often not necessary to pay the syntax classes any more attention. All of the work is to done to the visitor classes. Note that this class implements an interface named Node.
84
UMBC
Nodelist
NodeListOptional NodeOptional NodeSequence
Represents ( A ) +
Represents ( A ) * Represents [ A ] or ( A )? Represents nexted sequence like [ "extends" Name() ]
NodeToken
UMBC
Node
The interface Node is implemented by all syntax tree nodes. Node looks like this:
public interface Node extends java.io.Serializable { public void accept(visitor.Visitor v); public Object accept(visitor.ObjectVisitor v, Object argu); }
86
UMBC
87
UMBC
The first is that Node extends java.io.Serializable, meaning that you can now serialize your trees (or subtrees) to an output stream and read them back in. Secondly, there is one accept() method that can take an extra argument and return a value.
88
UMBC
// Generated by JTB 1.1.2 // package syntaxtree; /** All parts of a production * Grammar production: * f0 -> "import" are represented in the tree, * f1 -> Name() including tokens. * f2 -> [ "." "*" ] * f3 -> ";" */ public class ImportDeclaration implements Node {
public NodeToken f0; public Name f1; public NodeOptional f2; public NodeToken f3;
89
UMBC
NodeListInterface
The interface NodeListInterface is implemented by NodeList, NodeListOptional, and NodeSequence. NodeListInterface looks like this:
public interface NodeListInterface extends Node { public void addNode(Node n); public Node elementAt(int i); public java.util.Enumeration elements(); public int size(); }
90
UMBC
Details
Interface not generally needed but can be useful when writing code which only deals with the Vector-like functionality of any of the three classes listed above.
addNode() is used by the tree-building code to add nodes to the list. elements() is similar to the method of the same name in Vector, returning an Enumeration of the elements in the list. elementAt() returns the node at the ith position in the list (starting at 0, naturally). size() returns the number of elements in the list
91
UMBC
NodeChoice
NodeChoice is the class which JTB uses to represent choice points in a grammar. An example of this would be ( "abstract" | "final" | "public" ) JTB would represent the production void ResultType() : {} { "void" | Type() }
as a class ResultType with a single child of type NodeChoice.
92
UMBC
Details
The type stored by this NodeChoice would not be determined until the file was actually parsed. The node stored by a NodeChoice would then be accessible through the choice field. Since the choice is of type Node, typecasts are sometimes necessary to access the fields of the node stored in a NodeChoice.
93
UMBC
Implementation
public class NodeChoice implements Node { public NodeChoice(Node node, int whichChoice); public void accept(visitor.Visitor v); public Object accept(visitor.ObjectVisitor v, Object argu); public Node choice; public int which; }
94
UMBC
Which One?
Another feature of NodeChoice is the field which for determining which of the choices was selected The which field is used to see which choice was used
If the first choice is selected, which equals 0 (following the old programming custom to start counting at 0). If the second choice is taken, which equals 1. The third choice would be 2, etc. Note that your code could potentially break if the order of the choices is changed in the grammar.
95
UMBC
NodeList
NodeList is the class used by JTB to represent lists. An example of a list would be ( "[" Expression() "]" )+ JTB would represent the javacc production :
void ArrayDimensions() : {} { ( "[" Expression() "]" )+ ( "[" "]" )* }
96
UMBC
Details
NodeLists use java.lang.Vectors to store the lists of nodes. Like NodeChoice, typecasts may occasionally be necessary to access fields of nodes contained in the list.
97
UMBC
Implementation
public class NodeList implements NodeListInterface { public NodeList(); public void addNode(Node n); public Enumeration elements(); public Node elementAt(int i); public int size(); public void accept(visitor.Visitor v); public Object accept(visitor.ObjectVisitor v, Object argu); public Vector nodes; }
98
UMBC
NodeToken
This class is used by JTB to store all tokens into the tree, including JavaCC "special tokens" (if the -tk command-line option is used). In addition, each NodeToken contains information about each token, including its starting and ending column and line numbers.
99
UMBC
Implementation
public class NodeToken implements Node { public NodeToken(String s); public NodeToken(String s, int kind, int beginLine, int beginColumn, int endLine, int endColumn); public String toString(); public void accept(visitor.Visitor v); public Object accept(visitor.ObjectVisitor v, Object argu); // -1 for these ints means no position info is available.
//
100
UMBC
Continued
public class NodeToken implements Node { // . public String tokenImage; public int beginLine, beginColumn, endLine, endColumn; // -1 if not available. // Equal to the JavaCC token "kind" integer. public int kind; // Special Token methods below public NodeToken getSpecialAt(int i); public int numSpecials(); public void addSpecial(NodeToken s); public void trimSpecials(); public String withSpecials(); public Vector specialTokens; }
101
UMBC
Token Details
The tokens are simply stored as strings. The field tokenImage can be accessed directly, and the toString() method returns the same string. Also available is the kind integer. JavaCC assigns each type of token a unique integer to identify it. This integer is now available in each JTB NodeToken. For more information on using the kind integer, see the JavaCC documentation.
102
UMBC
Next comes the member variables of the ImportDeclaration class. These are generated based on the RHS of the production. Their type depends on the various items in the RHS and their names begin with f0 and work their way up. Why are they public?
Visitors which must access these fields reside in a different package than the syntax tree nodes Package visibility cannot be used. Breaking encapsulation was a necessary evil in this case.
103
UMBC
public ImportDeclaration(NodeToken n0, Name n1, NodeOptional n2, NodeToken n3) { f0 = n0; f1 = n1; f2 = n2; f3 = n3; } public ImportDeclaration(Name n0, NodeOptional n1) { f0 = new NodeToken("import"); f1 = n0; f2 = n1; f3 = new NodeToken(";"); }
104
UMBC
Constructors
The next portion of the generated class is the standard constructor. It is called from the treebuilding actions in the annotated grammar so you will probably not need to use it. Following the first constructor is a convenience constructor with the constant tokens of the production already filled-in by the appropriate NodeToken. This constructor's purpose is to help in manual construction of syntax trees.
105
UMBC
public Object
accept(visitor.ObjectVisitor v, Object argu) {
return v.visit(this,argu);
} }
106
UMBC
void accept(visitor.Visitor v) works with Visitor Object accept(visitor.ObjectVisitor v, Object argu) works with ObjectVisitor
107
UMBC
Other Options?
108
UMBC
References
Java Tree Builder Documentation Why Visitors? Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.
109