Java Reference
In-Depth Information
The tokens PACKAGE , SEMI , IMPORT , and EOF are returned by the scanner.
To parse a compilation unit using the recursive descent technique, one would write a
method, call it compilationUnit() , which does the following:
1. If the next (the first, in this case) incoming token were PACKAGE , would scan it (ad-
vancing to the next token), invoke a separate method called qualifiedIdentifier()
for parsing a qualified identifier, and then we must scan a SEMI (and announce a
syntax error if the next token were not a SEMI ).
2. While the next incoming token is an IMPORT , scan it and invoke qualifiedIdentifier
() for parsing the qualified identifier, and then we must again scan a SEMI . We save
the (imported) qualified identifiers in a list.
3. While the next incoming token is not an EOF , invoke a method called typeDeclaration
() for parsing the type declaration (in j-- this is only a class declaration), and we must
scan a SEMI . We save all of the ASTs for the type declararations in a list.
4. We must scan the EOF .
Here is the Java code for compilationUnit() , taken directly from Parser .
publicJCompilationUnitcompilationUnit(){
intline=scanner.token().line();
TypeNamepackageName=null;//Default
if(have(PACKAGE)){
packageName=qualifiedIdentifier();
mustBe(SEMI);
}
ArrayList<TypeName>imports=newArrayList<TypeName>();
while(have(IMPORT)){
imports.add(qualifiedIdentifier());
mustBe(SEMI);
}
ArrayList<JAST>typeDeclarations=newArrayList<JAST>();
while(!see(EOF)){
JASTtypeDeclaration=typeDeclaration();
if(typeDeclaration!=null){
typeDeclarations.add(typeDeclaration);
}
}
mustBe(EOF);
returnnewJCompilationUnit(scanner.fileName(),line,
packageName,imports,typeDeclarations);
}
In Parser , see() is a Boolean method that looks to see whether or not its argument
matches the next incoming token. Method have() is the same, but has the side-effect of
scanning past the incoming token when it does match its argument. Method mustBe()
requires that its argument match the next incoming token, and raises an error if it does not.
Of course, the method typeDeclaration() recursively invokes additional methods for
parsing the HelloWorld class declaration; hence the technique's name: recursive descent.
Each of these parsing methods produces an AST constructed from some particular type of
node. For example, at the end of compilationUnit() , a JCompilationUnit node is created
for encapsulating any package name (none here), the single import (having its own AST),
and a single class declaration (an AST rooted at a JClassDeclaration node).
Parsing in general, and recursive descent in particular, are discussed more fully in
Chapter 3.
 
Search WWH ::




Custom Search