📄 javacodegenerator.java
字号:
saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
// matching
genMatch(atom);
saveText = oldsaveText;
// tack on tree cursor motion if doing a tree walker
if (grammar instanceof TreeWalkerGrammar) {
println("_t = _t.getNextSibling();");
}
}
/** Generate code for the given grammar element.
* @param blk The token-range reference to generate
*/
public void gen(TokenRangeElement r) {
genErrorTryForElement(r);
if ( r.getLabel()!=null && syntacticPredLevel == 0) {
println(r.getLabel() + " = " + lt1Value + ";");
}
// AST
genElementAST(r);
// match
println("matchRange("+r.beginText+","+r.endText+");");
genErrorCatchForElement(r);
}
/** Generate code for the given grammar element.
* @param blk The token-reference to generate
*/
public void gen(TokenRefElement atom) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("genTokenRef("+atom+")");
if ( grammar instanceof LexerGrammar ) {
tool.panic("Token reference found in lexer");
}
genErrorTryForElement(atom);
// Assign Token value to token label variable
if ( atom.getLabel()!=null && syntacticPredLevel == 0) {
println(atom.getLabel() + " = " + lt1Value + ";");
}
// AST
genElementAST(atom);
// matching
genMatch(atom);
genErrorCatchForElement(atom);
// tack on tree cursor motion if doing a tree walker
if (grammar instanceof TreeWalkerGrammar) {
println("_t = _t.getNextSibling();");
}
}
public void gen(TreeElement t) {
// save AST cursor
println("AST __t" + t.ID + " = _t;");
// If there is a label on the root, then assign that to the variable
if (t.root.getLabel() != null) {
println(t.root.getLabel() + " = _t==ASTNULL ? null :("+labeledElementASTType +")_t;");
}
// Generate AST variables
genElementAST(t.root);
if (grammar.buildAST) {
// Save the AST construction state
println("ASTPair __currentAST" + t.ID + " = currentAST.copy();");
// Make the next item added a child of the TreeElement root
println("currentAST.root = currentAST.child;");
println("currentAST.child = null;");
}
// match root
genMatch(t.root);
// move to list of children
println("_t = _t.getFirstChild();");
// walk list of children, generating code for each
for (int i=0; i<t.getAlternatives().size(); i++) {
Alternative a = t.getAlternativeAt(i);
AlternativeElement e = a.head;
while ( e != null ) {
e.generate();
e = e.next;
}
}
if (grammar.buildAST) {
// restore the AST construction state to that just after the
// tree root was added
println("currentAST = __currentAST" + t.ID + ";");
}
// restore AST cursor
println("_t = __t" + t.ID + ";");
// move cursor to sibling of tree just parsed
println("_t = _t.getNextSibling();");
}
/** Generate the tree-parser Java file */
public void gen(TreeWalkerGrammar g) throws IOException {
// SAS: debugging stuff removed for now...
setGrammar(g);
if (!(grammar instanceof TreeWalkerGrammar)) {
tool.panic("Internal error generating tree-walker");
}
// Open the output stream for the parser and set the currentOutput
// SAS: move file open to method so subclass can override it
// (mainly for VAJ interface)
setupOutput(grammar.getClassName());
genAST = grammar.buildAST;
tabs = 0;
// Generate the header common to all output files.
genHeader();
// Do not use printAction because we assume tabs==0
println(behavior.getHeaderAction(""));
// Generate header for the parser
println("import antlr_oaa." + grammar.getSuperClass() + ";");
println("import antlr_oaa.Token;");
println("import antlr_oaa.collections.AST;");
println("import antlr_oaa.RecognitionException;");
println("import antlr_oaa.ANTLRException;");
println("import antlr_oaa.NoViableAltException;");
println("import antlr_oaa.MismatchedTokenException;");
println("import antlr_oaa.SemanticException;");
println("import antlr_oaa.collections.impl.BitSet;");
println("import antlr_oaa.ASTPair;");
println("import antlr_oaa.collections.impl.ASTArray;");
// Output the user-defined parser premamble
println(grammar.preambleAction.getText());
// Generate parser class definition
String sup=null;
if ( grammar.superClass!=null ) {
sup = grammar.superClass;
}
else {
sup = "antlr_oaa." + grammar.getSuperClass();
}
println("");
// print javadoc comment if any
if ( grammar.comment!=null ) {
_println(grammar.comment);
}
println("public class " + grammar.getClassName() + " extends "+sup);
println(" implements " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
if ( tsuffix != null ) {
String suffix = Tool.stripFrontBack(tsuffix.getText(),"\"","\"");
if ( suffix != null ) {
print(", "+suffix); // must be an interface name for Java
}
}
println(" {");
// Generate user-defined parser class members
print(
processActionForTreeSpecifiers(grammar.classMemberAction.getText(), 0, currentRule, null)
);
// Generate default parser class constructor
println("public " + grammar.getClassName() + "() {");
tabs++;
println("tokenNames = _tokenNames;");
tabs--;
println("}");
println("");
// Generate code for each rule in the grammar
Enumeration ids = grammar.rules.elements();
int ruleNum=0;
String ruleNameInits = "";
while ( ids.hasMoreElements() ) {
GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
if ( sym instanceof RuleSymbol) {
RuleSymbol rs = (RuleSymbol)sym;
genRule(rs, rs.references.size()==0, ruleNum++);
}
exitIfError();
}
// Generate the token names
genTokenStrings();
// Generate the bitsets used throughout the grammar
genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType());
// Close class definition
println("}");
println("");
// Close the parser output stream
currentOutput.close();
currentOutput = null;
}
/** Generate code for the given grammar element.
* @param wc The wildcard element to generate
*/
public void gen(WildcardElement wc) {
// Variable assignment for labeled elements
if (wc.getLabel()!=null && syntacticPredLevel == 0) {
println(wc.getLabel() + " = " + lt1Value + ";");
}
// AST
genElementAST(wc);
// Match anything but EOF
if (grammar instanceof TreeWalkerGrammar) {
println("if ( _t==null ) throw new MismatchedTokenException();");
}
else if (grammar instanceof LexerGrammar) {
if ( grammar instanceof LexerGrammar &&
(!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
println("_saveIndex=text.length();");
}
println("matchNot(EOF_CHAR);");
if ( grammar instanceof LexerGrammar &&
(!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
println("text.setLength(_saveIndex);"); // kill text atom put in buffer
}
}
else {
println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
}
// tack on tree cursor motion if doing a tree walker
if (grammar instanceof TreeWalkerGrammar) {
println("_t = _t.getNextSibling();");
}
}
/** Generate code for the given grammar element.
* @param blk The (...)* block to generate
*/
public void gen(ZeroOrMoreBlock blk) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("gen*("+blk+")");
println("{");
genBlockPreamble(blk);
String label;
if ( blk.getLabel() != null ) {
label = blk.getLabel();
}
else {
label = "_loop" + blk.ID;
}
println(label+":");
println("do {");
tabs++;
// Tell AST generation to build subrule result
String saveCurrentASTResult = currentASTResult;
if (blk.getLabel() != null) {
currentASTResult = blk.getLabel();
}
boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
// generate exit test if greedy set to false
// and an alt is ambiguous with exit branch
// or when lookahead derived purely from end-of-file
// Lookahead analysis stops when end-of-file is hit,
// returning set {epsilon}. Since {epsilon} is not
// ambig with any real tokens, no error is reported
// by deterministic() routines and we have to check
// for the case where the lookahead depth didn't get
// set to NONDETERMINISTIC (this only happens when the
// FOLLOW contains real atoms + epsilon).
boolean generateNonGreedyExitPath = false;
int nonGreedyExitDepth = grammar.maxk;
if ( !blk.greedy &&
blk.exitLookaheadDepth<=grammar.maxk &&
blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
{
generateNonGreedyExitPath = true;
nonGreedyExitDepth = blk.exitLookaheadDepth;
}
else if ( !blk.greedy &&
blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
{
generateNonGreedyExitPath = true;
}
if ( generateNonGreedyExitPath ) {
if ( DEBUG_CODE_GENERATOR ) {
System.out.println("nongreedy (...)* loop; exit depth is "+
blk.exitLookaheadDepth);
}
String predictExit =
getLookaheadTestExpression(blk.exitCache,
nonGreedyExitDepth);
println("// nongreedy exit test");
println("if ("+predictExit+") break "+label+";");
}
JavaBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
genBlockFinish(howToFinish, "break " + label + ";");
tabs--;
println("} while (true);");
println("}");
// Restore previous AST generation
currentASTResult = saveCurrentASTResult;
}
/** Generate an alternative.
* @param alt The alternative to generate
* @param blk The block to which the alternative belongs
*/
protected void genAlt(Alternative alt, AlternativeBlock blk) {
// Save the AST generation state, and set it to that of the alt
boolean savegenAST = genAST;
genAST = genAST && alt.getAutoGen();
boolean oldsaveTest = saveText;
saveText = saveText && alt.getAutoGen();
// Reset the variable name map for the alternative
Hashtable saveMap = treeVariableMap;
treeVariableMap = new Hashtable();
// Generate try block around the alt for error handling
if (alt.exceptionSpec != null) {
println("try { // for error handling");
tabs++;
}
AlternativeElement elem = alt.head;
while ( !(elem instanceof BlockEndElement) ) {
elem.generate(); // alt can begin with anything. Ask target to gen.
elem = elem.next;
}
if ( genAST) {
if (blk instanceof RuleBlock) {
// Set the AST return value for the rule
RuleBlock rblk = (RuleBlock)blk;
println(rblk.getRuleName() + "_AST = ("+labeledElementASTType+")currentAST.root;");
}
else if (blk.getLabel() != null) {
// ### future: also set AST value for labeled subrules.
// println(blk.getLabel() + "_AST = ("+labeledElementASTType+")currentAST.root;");
}
}
if (alt.exceptionSpec != null) {
// close try block
tabs--;
println("}");
genErrorHandler(alt.exceptionSpec);
}
genAST = savegenAST;
saveText = oldsaveTest;
treeVariableMap = saveMap;
}
/** Generate all the bitsets to be used in the parser or lexer
* Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
* and the BitSet object declarations like "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
* Note that most languages do not support object initialization inside a
* class definition, so other code-generators may have to separate the
* bitset declarations from the initializations (e.g., put the initializations
* in the generated constructor instead).
* @param bitsetList The list of bitsets to generate.
* @param maxVocabulary Ensure that each generated bitset can contain at least this value.
*/
protected void genBitsets(
Vector bitsetList,
int maxVocabulary
) {
println("");
for (int i = 0; i < bitsetList.size(); i++)
{
BitSet p = (BitSet)bitsetList.elementAt(i);
// Ensure that generated BitSet is large enough for vocabulary
p.growToInclude(maxVocabulary);
// initialization data
println(
"private static final long " + getBitsetName(i) + "_data_" + "[] = { " +
p.toStringOfWords() +
" };"
);
// BitSet object
println(
"public static final BitSet " + getBitsetName(i) + " = new BitSet(" +
getBitsetName(i) + "_data_" +
");"
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -