|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object com.ph.pr.parser.ASTBuilder
public class ASTBuilder
A singleton class providing capabilities for creating a class hierarchy for an AST for a supplied grammar, and creating the tree of AST objects, each one corresponding to a non-terminal, upon parsing. This is based on GOLD Parsing System and its Java engine .
parse(ClassLoader, String, String)
,
generateClasses(String, String, String, String)
Field Summary | |
---|---|
static java.lang.String |
AST_SUFFIX
|
private java.util.Map |
ast2Comments
|
private boolean |
caseInsensitive
|
private java.util.Map |
childMap
|
private ASTNode |
curAst
Current AST node (eventually this is returned by parse(ClassLoader, String, String) ). |
private java.lang.String |
curComment
|
static java.lang.String |
GOLD_NON_TERMINAL_END
|
static java.lang.String |
GOLD_NON_TERMINAL_START
|
static java.lang.String |
GOLD_PROD_SYMB
|
private java.lang.String |
grammar
|
private boolean |
grammarLoaded
|
private java.lang.String |
input
|
private static ASTBuilder |
instance
The singleton instance |
private java.io.PrintWriter |
out
|
private goldengine.java.GOLDParser |
parser
|
private java.util.Map |
prodMap
Map of names of
rule non-terminals to an
ArrayList of productions, as Strings. |
private java.util.Map |
red2Ast
Map of Reduction to corresponding ASTNode . |
private java.util.Map |
terminalMap
|
Fields inherited from interface goldengine.java.GPMessageConstants |
---|
gpMsgAccept, gpMsgCommentError, gpMsgCommentLineRead, gpMsgInternalError, gpMsgLexicalError, gpMsgNotLoadedError, gpMsgReduction, gpMsgSyntaxError, gpMsgTokenRead |
Constructor Summary | |
---|---|
private |
ASTBuilder()
|
Method Summary | |
---|---|
void |
generateClasses(java.lang.String root,
java.lang.String pkg,
java.lang.String visitorPkg,
java.lang.String visitorName)
Generate the classes implementing ASTNode for each
non-terminal. |
java.util.Collection |
getAllAsts()
|
java.util.Map |
getAst2Comments()
|
ASTNode |
getStart()
|
java.util.Map |
getTerminalMap()
|
private boolean |
isNonTerminal(java.lang.String s)
|
static void |
main(java.lang.String[] argv)
|
private java.lang.String |
nonTerminalName(java.lang.String s)
|
ASTNode |
parse(java.lang.ClassLoader loader,
java.lang.String pkg,
java.lang.String input)
Parse the input. |
static java.lang.String |
pkg2Dir(java.lang.String pkg)
|
private void |
processReduction(java.lang.ClassLoader myLoader,
java.lang.String pkg,
goldengine.java.Reduction reduction)
|
private void |
readRules()
Read the GOLD's .cgt file (provided in #setGrammar(String) ) and
initialize childMap and prodMap . |
void |
setGrammar(java.lang.String g,
boolean force)
Loads the grammar. |
static ASTBuilder |
singleton()
|
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final java.lang.String AST_SUFFIX
private static ASTBuilder instance
public static final java.lang.String GOLD_NON_TERMINAL_START
public static final java.lang.String GOLD_NON_TERMINAL_END
public static final java.lang.String GOLD_PROD_SYMB
private java.lang.String curComment
private final java.util.Map childMap
private final java.util.Map prodMap
names
of
rule non-terminals
to an
ArrayList of productions, as Strings.
private java.io.PrintWriter out
private java.lang.String grammar
private java.lang.String input
private final goldengine.java.GOLDParser parser
private boolean grammarLoaded
private java.util.Map red2Ast
Reduction
to corresponding ASTNode
.
private java.util.Map ast2Comments
private ASTNode curAst
parse(ClassLoader, String, String)
).
private java.util.Map terminalMap
private boolean caseInsensitive
Constructor Detail |
---|
private ASTBuilder()
Method Detail |
---|
public static ASTBuilder singleton()
private java.lang.String nonTerminalName(java.lang.String s)
private boolean isNonTerminal(java.lang.String s)
private void readRules()
#setGrammar(String)
) and
initialize childMap
and prodMap
.
public void setGrammar(java.lang.String g, boolean force) throws goldengine.java.ParserException
g
- path to GOLD compiled grammar (.cgt file).force
- if true, the grammar is reloaded, otherwise, if
the grammar points to the same one loaded previously, it is
ignored.
goldengine.java.ParserException
- whenever {GOLDParser#loadCompiledGrammar} does.GOLDParser.loadCompiledGrammar(String)
public void generateClasses(java.lang.String root, java.lang.String pkg, java.lang.String visitorPkg, java.lang.String visitorName) throws goldengine.java.ParserException, java.io.IOException
ASTNode
for each
non-terminal. They will be named by the name of the non-terminal with a
suffix AST_SUFFIX
and structure as explained below. The
parse(ClassLoader, String, String)
method will instantiate and
populate appropriate objects from this hierarchy during parsing, using
setters as described here. Thus, for the following production
a ext_statement_AST class will be generated, containing the following:<ext_statement> ::= SUB tkName <formal_list_opt> tkEol <statement_list> END SUB tkEol | DECLARE FUNCTION tkName LIB tkString <formal_list_opt> <as_opt> tkEol |
ASTNode.getProduction()
, which will be set by
parse(ClassLoader, String, String)
to one of the
PROD_n constants, as above.
suffix
-- since there will be a class generated for
that non-terminal, in turn, and accessors (getters and setters).
Depending on the actual reduction, not all such fields, obviously, will
be set. In our example, thus, one of the fields will be
private formal_list_opt_AST inst_formal_list_opt (and its
accessors will be set_formal_list_opt_AST(ASTNode) and
get_formal_list_opt_AST(). Another such field will be
inst_as_opt_AST. It's easy to see that if an instance of
ext_statement_AST is created as a result of first reduction (
SUB tkName..., or, in other words, when
getProduction() returns a String that's equal to
PROD_1) the inst_as_opt_AST will not be set; while
inst_formal_list_opt will be set in cases of both
PROD_1 and PROD_2. Notice that:
- The _inst prefix not part of the accessor name.
- The setter takes ASTNode, rather than that particular type (and downcasts inside). This is to make my life easier.
List
terminals field (with a
getTerminals() accessor) that will return the values of all
terminals in the current reduction, in order. Thus, in or example, in
case of PROD_2, this field will contain 6 elements:
ReflectiveVisitor
will be
generated. It will provide a visit method for every
ASTNode subclass that was generated. Using our example above,
one such method will be:
public void visit(ext_statement_AST node) { // ext_statement ::= SUB tkName <formal_list_opt> tkEol // <statement_list> END SUB tkEol if (node.getProduction().equals(ext_statement_AST.PROD_1)) { String curStr = ""; // TERMINAL: [SUB] curStr += (String) node.getTerminals().get(0); // TERMINAL: [tkName] curStr += (String) node.getTerminals().get(1); node.get_formal_list_opt_AST().accept(this); // TODO curStr = this.code; this.code = ""; // TERMINAL: [tkEol] curStr += (String) node.getTerminals().get(2); node.get_statement_list_AST().accept(this); // TODO curStr = this.code; this.code = ""; // TERMINAL: [END] curStr += (String) node.getTerminals().get(3); // TERMINAL: [SUB] curStr += (String) node.getTerminals().get(4); // TERMINAL: [tkEol] curStr += (String) node.getTerminals().get(5); return; } // ext_statement ::= DECLARE FUNCTION tkName LIB tkString // <formal_list_opt> <as_opt> tkEol if (node.getProduction().equals(ext_statement_AST.PROD_2)) { String curStr = ""; // TERMINAL: [DECLARE] curStr += (String) node.getTerminals().get(0); // TERMINAL: [FUNCTION] curStr += (String) node.getTerminals().get(1); // TERMINAL: [tkName] curStr += (String) node.getTerminals().get(2); // TERMINAL: [LIB] curStr += (String) node.getTerminals().get(3); // TERMINAL: [tkString] curStr += (String) node.getTerminals().get(4); node.get_formal_list_opt_AST().accept(this); // TODO curStr = this.code; this.code = ""; node.get_as_opt_AST().accept(this); // TODO curStr = this.code; this.code = ""; // TERMINAL: [tkEol] curStr += (String) node.getTerminals().get(5); return; } // ext_statement ::= if (node.getProduction().equals(ext_statement_AST.PROD_3)) { String curStr = ""; return; } }This visitor can then be modified. TODO
root
- path where the
pkg
containing generated classes is
to be createdpkg
- package into which to place generated classes; if it exists,
its contents will be deleted prior to the generation.visitorPkg
- package into which a subclass of ReflectiveVisitor
is
generated -- different from
pkg
in that it's
something to be modified/customized by a developer, rather
than to be used as generated.visitorName
- a name of the subclass of ReflectiveVisitor
to be
generated.
goldengine.java.ParserException
- if an error occurs
java.io.IOException
public static final java.lang.String pkg2Dir(java.lang.String pkg)
public java.util.Collection getAllAsts()
public ASTNode parse(java.lang.ClassLoader loader, java.lang.String pkg, java.lang.String input) throws goldengine.java.ParserException
loader
- ClassLoader to use to load classes implementing
ASTNode that were generated by
#generateClasses(String, String)
(useful if not
running in an IDE, etc.); if null, then
Thread.getContextClassLoader()
of the
Thread.currentThread()
is used.pkg
- package where the classes implementing ASTNode that
were generated by #generateClasses(String, String)
reside.input
- input to parse.
goldengine.java.ParserException
- if there were any errors in parsingpublic java.util.Map getAst2Comments()
public static void main(java.lang.String[] argv)
argv
- In the following order:
public java.util.Map getTerminalMap()
private void processReduction(java.lang.ClassLoader myLoader, java.lang.String pkg, goldengine.java.Reduction reduction) throws goldengine.java.ParserException
goldengine.java.ParserException
public ASTNode getStart()
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |