📄 javacodegenerator.java
字号:
package antlr_oaa;
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.jGuru.com
* Software rights: http://www.antlr.org/RIGHTS.html
*
* $Id: JavaCodeGenerator.java,v 1.1 2002/11/08 17:37:57 agno Exp $
*/
import java.util.Enumeration;
import java.util.Hashtable;
import antlr_oaa.collections.impl.BitSet;
import antlr_oaa.collections.impl.Vector;
import java.io.PrintWriter; //SAS: changed for proper text file io
import java.io.IOException;
import java.io.FileWriter;
/**Generate MyParser.java, MyLexer.java and MyParserTokenTypes.java */
public class JavaCodeGenerator extends CodeGenerator {
// non-zero if inside syntactic predicate generation
protected int syntacticPredLevel = 0;
// Are we generating ASTs (for parsers and tree parsers) right now?
protected boolean genAST = false;
// Are we saving the text consumed (for lexers) right now?
protected boolean saveText = false;
// Grammar parameters set up to handle different grammar classes.
// These are used to get instanceof tests out of code generation
String labeledElementType;
String labeledElementASTType;
String labeledElementInit;
String commonExtraArgs;
String commonExtraParams;
String commonLocalVars;
String lt1Value;
String exceptionThrown;
String throwNoViable;
/** Tracks the rule being generated. Used for mapTreeId */
RuleBlock currentRule;
/** Tracks the rule or labeled subrule being generated. Used for
AST generation. */
String currentASTResult;
/** Mapping between the ids used in the current alt, and the
* names of variables used to represent their AST values.
*/
Hashtable treeVariableMap = new Hashtable();
/* Count of unnamed generated variables */
int astVarNumber = 1;
/** Special value used to mark duplicate in treeVariableMap */
protected static final String NONUNIQUE = new String();
public static final int caseSizeThreshold = 127; // ascii is max
private Vector semPreds;
/** Create a Java code-generator using the given Grammar.
* The caller must still call setTool, setBehavior, and setAnalyzer
* before generating code.
*/
public JavaCodeGenerator() {
super();
charFormatter = new JavaCharFormatter();
}
/** Adds a semantic predicate string to the sem pred vector
These strings will be used to build an array of sem pred names
when building a debugging parser. This method should only be
called when the debug option is specified
*/
protected int addSemPred(String predicate) {
semPreds.appendElement(predicate);
return semPreds.size()-1;
}
public void exitIfError() {
if (tool.hasError) {
System.out.println("Exiting due to errors.");
System.exit(1);
}
}
/**Generate the parser, lexer, treeparser, and token types in Java */
public void gen() {
// Do the code generation
try {
// Loop over all grammars
Enumeration grammarIter = behavior.grammars.elements();
while (grammarIter.hasMoreElements()) {
Grammar g = (Grammar)grammarIter.nextElement();
// Connect all the components to each other
g.setGrammarAnalyzer(analyzer);
g.setCodeGenerator(this);
analyzer.setGrammar(g);
// To get right overloading behavior across hetrogeneous grammars
setupGrammarParameters(g);
g.generate();
// print out the grammar with lookahead sets (and FOLLOWs)
// System.out.print(g.toString());
exitIfError();
}
// Loop over all token managers (some of which are lexers)
Enumeration tmIter = behavior.tokenManagers.elements();
while (tmIter.hasMoreElements()) {
TokenManager tm = (TokenManager)tmIter.nextElement();
if (!tm.isReadOnly()) {
// Write the token manager tokens as Java
// this must appear before genTokenInterchange so that
// labels are set on string literals
genTokenTypes(tm);
// Write the token manager tokens as plain text
genTokenInterchange(tm);
}
exitIfError();
}
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
/** Generate code for the given grammar element.
* @param blk The {...} action to generate
*/
public void gen(ActionElement action) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("genAction("+action+")");
if ( action.isSemPred ) {
genSemPred(action.actionText, action.line);
}
else {
if ( grammar.hasSyntacticPredicate ) {
println("if ( inputState.guessing==0 ) {");
tabs++;
}
ActionTransInfo tInfo = new ActionTransInfo();
String actionStr = processActionForTreeSpecifiers(action.actionText, action.getLine(), currentRule, tInfo);
if ( tInfo.refRuleRoot!=null ) {
// Somebody referenced "#rule", make sure translated var is valid
// assignment to #rule is left as a ref also, meaning that assignments
// with no other refs like "#rule = foo();" still forces this code to be
// generated (unnecessarily).
println(tInfo.refRuleRoot + " = ("+labeledElementASTType+")currentAST.root;");
}
// dump the translated action
printAction(actionStr);
if ( tInfo.assignToRoot ) {
// Somebody did a "#rule=", reset internal currentAST.root
println("currentAST.root = "+tInfo.refRuleRoot+";");
// reset the child pointer too to be last sibling in sibling list
println("currentAST.child = "+tInfo.refRuleRoot+"!=null &&"+tInfo.refRuleRoot+".getFirstChild()!=null ?");
tabs++;
println(tInfo.refRuleRoot+".getFirstChild() : "+tInfo.refRuleRoot+";");
tabs--;
println("currentAST.advanceChildToEnd();");
}
if ( grammar.hasSyntacticPredicate ) {
tabs--;
println("}");
}
}
}
/** Generate code for the given grammar element.
* @param blk The "x|y|z|..." block to generate
*/
public void gen(AlternativeBlock blk) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("gen("+blk+")");
println("{");
genBlockPreamble(blk);
// Tell AST generation to build subrule result
String saveCurrentASTResult = currentASTResult;
if (blk.getLabel() != null) {
currentASTResult = blk.getLabel();
}
boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
JavaBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
genBlockFinish(howToFinish, throwNoViable);
println("}");
// Restore previous AST generation
currentASTResult = saveCurrentASTResult;
}
/** Generate code for the given grammar element.
* @param blk The block-end element to generate. Block-end
* elements are synthesized by the grammar parser to represent
* the end of a block.
*/
public void gen(BlockEndElement end) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("genRuleEnd("+end+")");
}
/** Generate code for the given grammar element.
* @param blk The character literal reference to generate
*/
public void gen(CharLiteralElement atom) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("genChar("+atom+")");
if ( atom.getLabel()!=null ) {
println(atom.getLabel() + " = " + lt1Value + ";");
}
boolean oldsaveText = saveText;
saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
genMatch(atom);
saveText = oldsaveText;
}
/** Generate code for the given grammar element.
* @param blk The character-range reference to generate
*/
public void gen(CharRangeElement r) {
if ( r.getLabel()!=null && syntacticPredLevel == 0) {
println(r.getLabel() + " = " + lt1Value + ";");
}
println("matchRange("+r.beginText+","+r.endText+");");
}
/** Generate the lexer Java file */
public void gen(LexerGrammar g) throws IOException {
// If debugging, create a new sempred vector for this grammar
if (g.debuggingOutput)
semPreds = new Vector();
setGrammar(g);
if (!(grammar instanceof LexerGrammar)) {
tool.panic("Internal error generating lexer");
}
// SAS: moved output creation to method so a subclass can change
// how the output is generated (for VAJ interface)
setupOutput(grammar.getClassName());
genAST = false; // no way to gen trees.
saveText = true; // save consumed characters.
tabs=0;
// Generate header common to all Java output files
genHeader();
// Do not use printAction because we assume tabs==0
println(behavior.getHeaderAction(""));
// Generate header specific to lexer Java file
// println("import java.io.FileInputStream;");
println("import java.io.InputStream;");
println("import antlr_oaa.TokenStreamException;");
println("import antlr_oaa.TokenStreamIOException;");
println("import antlr_oaa.TokenStreamRecognitionException;");
println("import antlr_oaa.CharStreamException;");
println("import antlr_oaa.CharStreamIOException;");
println("import antlr_oaa.ANTLRException;");
println("import java.io.Reader;");
println("import java.util.Hashtable;");
println("import antlr_oaa." + grammar.getSuperClass() + ";");
println("import antlr_oaa.InputBuffer;");
println("import antlr_oaa.ByteBuffer;");
println("import antlr_oaa.CharBuffer;");
println("import antlr_oaa.Token;");
println("import antlr_oaa.CommonToken;");
println("import antlr_oaa.RecognitionException;");
println("import antlr_oaa.NoViableAltForCharException;");
println("import antlr_oaa.MismatchedCharException;");
println("import antlr_oaa.TokenStream;");
println("import antlr_oaa.ANTLRHashString;");
println("import antlr_oaa.LexerSharedInputState;");
println("import antlr_oaa.collections.impl.BitSet;");
println("import antlr_oaa.SemanticException;");
// Generate user-defined lexer file preamble
println(grammar.preambleAction.getText());
// Generate lexer class definition
String sup=null;
if ( grammar.superClass!=null ) {
sup = grammar.superClass;
}
else {
sup = "antlr_oaa." + grammar.getSuperClass();
}
// print javadoc comment if any
if ( grammar.comment!=null ) {
_println(grammar.comment);
}
print("public class " + grammar.getClassName() + " extends "+sup);
println(" implements " + grammar.tokenManager.getName() + TokenTypesFileSuffix+", TokenStream");
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 lexer class members
print(
processActionForTreeSpecifiers(grammar.classMemberAction.getText(), 0, currentRule, null)
);
//
// Generate the constructor from InputStream, which in turn
// calls the ByteBuffer constructor
//
println("public " + grammar.getClassName() + "(InputStream in) {");
tabs++;
println("this(new ByteBuffer(in));");
tabs--;
println("}");
//
// Generate the constructor from Reader, which in turn
// calls the CharBuffer constructor
//
println("public " + grammar.getClassName() + "(Reader in) {");
tabs++;
println("this(new CharBuffer(in));");
tabs--;
println("}");
println("public " + grammar.getClassName() + "(InputBuffer ib) {");
tabs++;
// if debugging, wrap the input buffer in a debugger
if (grammar.debuggingOutput)
println("this(new LexerSharedInputState(new antlr_oaa.debug.DebuggingInputBuffer(ib)));");
else
println("this(new LexerSharedInputState(ib));");
tabs--;
println("}");
//
// Generate the constructor from InputBuffer (char or byte)
//
println("public " + grammar.getClassName() + "(LexerSharedInputState state) {");
tabs++;
println("super(state);");
// if debugging, set up array variables and call user-overridable
// debugging setup method
if ( grammar.debuggingOutput ) {
println(" ruleNames = _ruleNames;");
println(" semPredNames = _semPredNames;");
println(" setupDebugging();");
}
// Generate the initialization of a hashtable
// containing the string literals used in the lexer
// The literals variable itself is in CharScanner
println("literals = new Hashtable();");
Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
while ( keys.hasMoreElements() ) {
String key = (String)keys.nextElement();
if ( key.charAt(0) != '"' ) {
continue;
}
TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
if ( sym instanceof StringLiteralSymbol ) {
StringLiteralSymbol s = (StringLiteralSymbol)sym;
println("literals.put(new ANTLRHashString(" + s.getId() + ", this), new Integer(" + s.getTokenType() + "));");
}
}
tabs--;
Enumeration ids;
// Generate the setting of various generated options.
println("caseSensitiveLiterals = " + g.caseSensitiveLiterals + ";");
println("setCaseSensitive("+g.caseSensitive+");");
println("}");
// generate the rule name array for debugging
if (grammar.debuggingOutput) {
println("private static final String _ruleNames[] = {");
ids = grammar.rules.elements();
int ruleNum=0;
while ( ids.hasMoreElements() ) {
GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
if ( sym instanceof RuleSymbol)
println(" \""+((RuleSymbol)sym).getId()+"\",");
}
println("};");
}
// Generate nextToken() rule.
// nextToken() is a synthetic lexer rule that is the implicit OR of all
// user-defined lexer rules.
genNextToken();
// Generate code for each rule in the lexer
ids = grammar.rules.elements();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -