⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cppcodegenerator.java

📁 SRI international 发布的OAA框架软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
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: CppCodeGenerator.java,v 1.1 2002/11/08 17:38:09 agno Exp $
 */

// C++ code generator by Pete Wells: pete@yamuna.demon.co.uk
// #line generation contributed by: Ric Klaren <klaren@cs.utwente.nl>

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.cpp, MyParser.hpp, MyLexer.cpp, MyLexer.hpp and MyParserTokenTypes.hpp */
public class CppCodeGenerator 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;

	// Generate #line's
	protected boolean genHashLines = true;
	// Used to keep track of lineno in output
	protected int outputLine;
	protected String outputFile;

	// Grammar parameters set up to handle different grammar classes.
	// These are used to get instanceof tests out of code generation
	boolean usingCustomAST = false;
	String labeledElementType;
	String labeledElementASTType; // mostly the same as labeledElementType except in parsers
	String labeledElementASTInit;
	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;

	private static String namespaceStd   = "ANTLR_USE_NAMESPACE(std)";
	private static String namespaceAntlr = "ANTLR_USE_NAMESPACE(antlr)";
	private static NameSpace nameSpace = null;

	private static final String preIncludeCpp  = "pre_include_cpp";
	private static final String preIncludeHpp  = "pre_include_hpp";
	private static final String postIncludeCpp = "post_include_cpp";
	private static final String postIncludeHpp = "post_include_hpp";

	/** Create a C++ code-generator using the given Grammar.
	 * The caller must still call setTool, setBehavior, and setAnalyzer
	 * before generating code.
	 */
	public CppCodeGenerator() {
		super();
		charFormatter = new CppCharFormatter();
	}
	/** 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);
		}
	}
	protected int countLines( String s )
	{
		int lines = 0;
		for( int i = 0; i < s.length(); i++ )
		{
			if( s.charAt(i) == '\n' )
				lines++;
		}
		return lines;
	}
	/** Output a String to the currentOutput stream.
	 * Ignored if string is null.
	 * @param s The string to output
	 */
	protected void _print(String s) {
		if (s != null) {
			outputLine += countLines(s);
			currentOutput.print(s);
		}
	}
	/** Print an action without leading tabs, attempting to
	 * preserve the current indentation level for multi-line actions
	 * Ignored if string is null.
	 * @param s The action string to output
	 */
	protected void _printAction(String s) {
		if (s != null) {
			outputLine += countLines(s)+1;
			super._printAction(s);
		}
	}
	/** Print an action stored in a token surrounded by #line stuff */
	public void printAction(Token t) {
		if (t != null) {
			genLineNo(t.getLine());
			printTabs();
			_printAction(t.getText());
			genLineNo2();
		}
	}
	/** Print a header action by #line stuff
	* @param name The name of the header part
	*/
	public void printHeaderAction(String name) {
		Token a = (antlr_oaa.Token)behavior.headerActions.get(name);
		if (a != null) {
			genLineNo(a.getLine());
			println(a.getText());
			genLineNo2();
		}
	}
	/** Output a String followed by newline, to the currentOutput stream.
	 * Ignored if string is null.
	 * @param s The string to output
	 */
	protected void _println(String s) {
		if (s != null) {
			outputLine += countLines(s)+1;
			currentOutput.println(s);
		}
	}
	/** Output tab indent followed by a String followed by newline,
	 * to the currentOutput stream.  Ignored if string is null.
	 * @param s The string to output
	 */
	protected void println(String s) {
		if (s != null) {
			printTabs();
			outputLine += countLines(s)+1;
			currentOutput.println(s);
		}
	}

	/** Generate a #line or // line depending on options */
	public void genLineNo(int line) {
	    if ( line == 0 ) {
		line++;
	    }
	    if( genHashLines )
		_println("#line "+line+" \""+Tool.fileMinusPath(tool.grammarFile)+"\"");
	    else
		println("// line "+line+" \""+Tool.fileMinusPath(tool.grammarFile)+"\"");
	}

	/** Generate a #line or // line depending on options */
	public void genLineNo(GrammarElement el)
	{
		if( el != null )
			genLineNo(el.getLine());
	}
	/** Generate a #line or // line depending on options */
	public void genLineNo(Token t)
	{
		if (t != null)
			genLineNo(t.getLine());
	}
	/** Generate a #line or // line depending on options */
	public void genLineNo2()
	{
		if( genHashLines )
		{
			_println("#line "+(outputLine+1)+" \""+outputFile+"\"");
		}
	}
	/**Generate the parser, lexer, treeparser, and token types in C++ */
	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();
				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 C++
					// 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
			genLineNo(action);
			printAction(actionStr);
			genLineNo2();

			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
				// now use if else in stead of x ? y : z to shut CC 4.2 up.
				println("if ( "+tInfo.refRuleRoot+"!="+labeledElementASTInit+" &&");
				tabs++;
				println(tInfo.refRuleRoot+"->getFirstChild() != "+labeledElementASTInit+" )");
				println("  currentAST.child = "+tInfo.refRuleRoot+"->getFirstChild();");
			  	tabs--;
				println("else");
				tabs++;
				println("currentAST.child = "+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);

		CppBlockFinishingInfo 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("+textOrChar(r.beginText)+","+textOrChar(r.endText)+");");
	}
	/** Generate the lexer C++ files */
	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");
		}

		genBody(g);
		genInclude(g);
	}
	/** Generate code for the given grammar element.
	 * @param blk The (...)+ block to generate
	 */
	public void gen(OneOrMoreBlock blk) {
		if ( DEBUG_CODE_GENERATOR ) System.out.println("gen+("+blk+")");
		String label;
		String cnt;
		println("{");
		genBlockPreamble(blk);
		if ( blk.getLabel() != null ) {
			cnt = "_cnt_"+blk.getLabel();
		}
		else {
			cnt = "_cnt" + blk.ID;
		}
		println("int "+cnt+"=0;");
		if ( blk.getLabel() != null ) {
			label = blk.getLabel();
		}
		else {
			label = "_loop" + blk.ID;
		}

		println("for (;;) {");
		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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -