|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectcom.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 namesof
rule non-terminalsto an
ArrayList of productions, as Strings. |
private java.util.Map |
red2Ast
Map of Reductionto 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 ASTNodefor 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 childMapand 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
namesof
rule non-terminalsto 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
Reductionto 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 childMapand 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
ASTNodefor each
non-terminal. They will be named by the name of the non-terminal with a
suffix AST_SUFFIXand 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
<ext_statement> ::=
SUB tkName <formal_list_opt> tkEol <statement_list> END SUB tkEol
| DECLARE FUNCTION tkName LIB tkString <formal_list_opt> <as_opt> tkEol
|
a ext_statement_AST class will be generated, containing the
following:
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:
ReflectiveVisitorwill 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 ReflectiveVisitoris
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 ReflectiveVisitorto be
generated.
goldengine.java.ParserException - if an error occurs
java.io.IOExceptionpublic 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.ParserExceptionpublic ASTNode getStart()
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||