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

📄 cppcodegenerator.java

📁 SRI international 发布的OAA框架软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			// Generate a warning if there is a synPred for single alt.
			if (alt.synPred != null)
			{
				tool.warning(
					"Syntactic predicate superfluous for single alternative",
					grammar.getFilename(),
					blk.getAlternativeAt(0).synPred.getLine()
				);
			}
			if (noTestForSingle) {
				if (alt.semPred != null) {
					// Generate validating predicate
					genSemPred(alt.semPred, blk.line);
				}
				genAlt(alt, blk);
				return finishingInfo;
			}
		}

		// count number of simple LL(1) cases; only do switch for
		// many LL(1) cases (no preds, no end of token refs)
		// We don't care about exit paths for (...)*, (...)+
		// because we don't explicitly have a test for them
		// as an alt in the loop.
		//
		// Also, we now count how many unicode lookahead sets
		// there are--they must be moved to DEFAULT or ELSE
		// clause.

		int nLL1 = 0;
		for (int i=0; i<blk.getAlternatives().size(); i++) {
			Alternative a = blk.getAlternativeAt(i);
			if ( suitableForCaseExpression(a) ) {
				nLL1++;
			}
		}

		// do LL(1) cases
		if ( nLL1 >= makeSwitchThreshold) {
			// Determine the name of the item to be compared
			String testExpr = lookaheadString(1);
			createdLL1Switch = true;
			// when parsing trees, convert null to valid tree node with NULL lookahead
			if ( grammar instanceof TreeWalkerGrammar ) {
				println("if (_t == "+labeledElementASTInit+" )");
				tabs++;
				println("_t = ASTNULL;");
				tabs--;
			}
			println("switch ( "+testExpr+") {");
			for (int i=0; i<blk.alternatives.size(); i++) {
				Alternative alt = blk.getAlternativeAt(i);
				// ignore any non-LL(1) alts, predicated alts or end-of-token alts
				// or end-of-token alts for case expressions
				if ( !suitableForCaseExpression(alt) ) {
					continue;
				}
				Lookahead p = alt.cache[1];
				if (p.fset.degree() == 0 && !p.containsEpsilon()) {
					tool.warning("Alternate omitted due to empty prediction set",
						grammar.getFilename(),
						alt.head.getLine());
				}
				else {
					genCases(p.fset);
					println("{");
					tabs++;
					genAlt(alt, blk);
					println("break;");
					tabs--;
					println("}");
				}
			}
			println("default:");
			tabs++;
		}

		// do non-LL(1) and nondeterministic cases
		// This is tricky in the lexer, because of cases like:
		//     STAR : '*' ;
		//     ASSIGN_STAR : "*=";
		// Since nextToken is generated without a loop, then the STAR will
		// have end-of-token as it's lookahead set for LA(2).  So, we must generate the
		// alternatives containing trailing end-of-token in their lookahead sets *after*
		// the alternatives without end-of-token.  This implements the usual
		// lexer convention that longer matches come before shorter ones, e.g.
		// "*=" matches ASSIGN_STAR not STAR
		//
		// For non-lexer grammars, this does not sort the alternates by depth
		// Note that alts whose lookahead is purely end-of-token at k=1 end up
		// as default or else clauses.
		int startDepth = (grammar instanceof LexerGrammar) ? grammar.maxk : 0;
		for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
			if ( DEBUG_CODE_GENERATOR ) System.out.println("checking depth "+altDepth);
			for (int i=0; i<blk.alternatives.size(); i++) {
				Alternative alt = blk.getAlternativeAt(i);
				if ( DEBUG_CODE_GENERATOR ) System.out.println("genAlt: "+i);
				// if we made a switch above, ignore what we already took care
				// of.  Specifically, LL(1) alts with no preds
				// that do not have end-of-token in their prediction set
				if ( createdLL1Switch &&
					 suitableForCaseExpression(alt) ) {
					if ( DEBUG_CODE_GENERATOR )
						System.out.println("ignoring alt because it was in the switch");
					continue;
				}
				String e;

				boolean unpredicted = false;

				if (grammar instanceof LexerGrammar) {
					// Calculate the "effective depth" of the alt, which is the max
					// depth at which cache[depth]!=end-of-token
					int effectiveDepth = alt.lookaheadDepth;
					if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC) {
						// use maximum lookahead
						effectiveDepth = grammar.maxk;
					}
					while ( effectiveDepth >= 1 &&
							 alt.cache[effectiveDepth].containsEpsilon() )
					{
						effectiveDepth--;
					}
					// Ignore alts whose effective depth is other than the ones we
					// are generating for this iteration.
					if (effectiveDepth != altDepth) {
						if ( DEBUG_CODE_GENERATOR )
							System.out.println("ignoring alt because effectiveDepth!=altDepth;"+effectiveDepth+"!="+altDepth);
						continue;
					}
					unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
					e = getLookaheadTestExpression(alt, effectiveDepth);
				} else {
					unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
					e = getLookaheadTestExpression(alt, grammar.maxk);
				}

				// Was it a big unicode range that forced unsuitability
				// for a case expression?
				if ( alt.cache[1].fset.degree() > caseSizeThreshold )
				{
					if ( nIF==0 )
					{
						// generate this only for the first if the elseif's
						// are covered by this one
						if ( grammar instanceof TreeWalkerGrammar ) {
							println("if (_t == "+labeledElementASTInit+" )");
							tabs++;
							println("_t = ASTNULL;");
							tabs--;
						}
						println("if " + e + " {");
					}
					else
						println("else if " + e + " {");
				}
				else if (unpredicted &&
							alt.semPred==null &&
							alt.synPred==null)
				{
					// The alt has empty prediction set and no
					// predicate to help out.  if we have not
					// generated a previous if, just put {...} around
					// the end-of-token clause
					if ( nIF==0 ) {
						println("{");
					}
					else {
						println("else {");
					}
					finishingInfo.needAnErrorClause = false;
				}
				else
				{
					// check for sem and syn preds
					// Add any semantic predicate expression to the lookahead test
					if ( alt.semPred != null ) {
						// if debugging, wrap the evaluation of the predicate in a method
						//
						// translate $ and # references
						ActionTransInfo tInfo = new ActionTransInfo();
						String actionStr = processActionForTreeSpecifiers(alt.semPred,
																		  blk.line,
																		  currentRule,
																		  tInfo);
						// ignore translation info...we don't need to do anything with it.

						// call that will inform SemanticPredicateListeners of the result
						if (((grammar instanceof ParserGrammar) || (grammar instanceof LexerGrammar)) && grammar.debuggingOutput)
							e = "("+e+"&& fireSemanticPredicateEvaluated(antlr_oaa.debug.SemanticPredicateEvent.PREDICTING,"+ //FIXME
									addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
						else
							e = "("+e+"&&("+actionStr +"))";
					}

					// Generate any syntactic predicates
					if ( nIF>0 ) {
						if ( alt.synPred != null ) {
							println("else {");
							tabs++;
							genSynPred( alt.synPred, e );
							closingBracesOfIFSequence++;
						}
						else {
							println("else if " + e + " {");
						}
					}
					else {
						if ( alt.synPred != null ) {
							genSynPred( alt.synPred, e );
						}
						else {
							// when parsing trees, convert null to valid tree node
							// with NULL lookahead.
							if ( grammar instanceof TreeWalkerGrammar ) {
								println("if (_t == "+labeledElementASTInit+" )");
								tabs++;
								println("_t = ASTNULL;");
								tabs--;
							}
							println("if " + e + " {");
						}
					}

				}

				nIF++;
				tabs++;
				genAlt(alt, blk);
				tabs--;
				println("}");
			}
		}
		String ps = "";
		for (int i=1; i<=closingBracesOfIFSequence; i++) {
			tabs--; // does JavaCodeGenerator need this?
			ps+="}";
		}

		// Restore the AST generation state
		genAST = savegenAST;

		// restore save text state
		saveText=oldsaveTest;

		// Return the finishing info.
		if ( createdLL1Switch ) {
			tabs--;
			finishingInfo.postscript = ps+"}";
			finishingInfo.generatedSwitch = true;
			finishingInfo.generatedAnIf = nIF>0;
			//return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement

		}
		else {
			finishingInfo.postscript = ps;
			finishingInfo.generatedSwitch = false;
			finishingInfo.generatedAnIf = nIF>0;
			//return new CppBlockFinishingInfo(ps, false,nIF>0);
		}
		return finishingInfo;
	}

	private static boolean suitableForCaseExpression(Alternative a) {
		return a.lookaheadDepth == 1 &&
			a.semPred == null &&
			!a.cache[1].containsEpsilon() &&
			a.cache[1].fset.degree()<=caseSizeThreshold;
	}

	/** Generate code to link an element reference into the AST */
	private void genElementAST(AlternativeElement el) {
		// handle case where you're not building trees, but are in tree walker.
		// Just need to get labels set up.
		if ( grammar instanceof TreeWalkerGrammar && !grammar.buildAST ) {
			String elementRef;
			String astName;

			// Generate names and declarations of the AST variable(s)
			if (el.getLabel() == null) {
				elementRef = lt1Value;
				// Generate AST variables for unlabeled stuff
				astName = "tmp" + astVarNumber + "_AST";
				astVarNumber++;
				// Map the generated AST variable in the alternate
				mapTreeVariable(el, astName);
				// Generate an "input" AST variable also
				println(labeledElementASTType+" "+astName+"_in = "+elementRef+";");
			}
			return;
		}

		if (grammar.buildAST && syntacticPredLevel == 0) {
			boolean doNoGuessTest = (
				grammar.hasSyntacticPredicate &&
				(
					el.getLabel() != null ||
					el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG
				)
			);

			String elementRef;
			String astName;

			// Generate names and declarations of the AST variable(s)
			if (el.getLabel() != null) {
				elementRef = el.getLabel();
				astName = el.getLabel() + "_AST";
			} else {
				elementRef = lt1Value;
				// Generate AST variables for unlabeled stuff
				astName = "tmp" + astVarNumber + "_AST";
				astVarNumber++;
				// Generate the declaration
				if ( el instanceof GrammarAtom ) {
					GrammarAtom ga = (GrammarAtom)el;
					if ( ga.getASTNodeType()!=null ) {
						println("Ref"+ga.getASTNodeType()+" " + astName + ";");
					}
					else {
						println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
					}
				}
				else {
					println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
				}

				// Map the generated AST variable in the alternate
				mapTreeVariable(el, astName);
				if (grammar instanceof TreeWalkerGrammar) {
					// Generate an "input" AST variable also
					println(labeledElementASTType+" " + astName + "_in = "+labeledElementASTInit+";");
				}
			}

			// Enclose actions with !guessing
			if (doNoGuessTest) {
				println("if (inputState->guessing==0) {");
				tabs++;
			}

			if (el.getLabel() != null) {
				if ( el instanceof GrammarAtom ) {
					println(astName + " = "+
							getASTCreateString((GrammarAtom)el,elementRef) + ";");
				}
				else {
					println(astName + " = "+
							getASTCreateString(elementRef) + ";");
				}
			} else {
				elementRef = lt1Value;
				if ( el instanceof GrammarAtom ) {
					println(astName + " = "+
							getASTCreateString((GrammarAtom)el,elementRef) + ";");
				}
				else {
					println(astName + " = "+
							getASTCreateString(elementRef) + ";");
				}
				// Map the generated AST variable in the alternate
				if (grammar instanceof TreeWalkerGrammar) {
					// set "input" AST variable also
					println(astName + "_in = " + elementRef + ";");
				}
			}

			if (genAST) {
				switch (el.getAutoGenType()) {
				case GrammarElement.AUTO_GEN_NONE:
					println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
					break;
				case GrammarElement.AUTO_GEN_CARET:
//					println("astFactory.makeASTRoot(currentAST, " + astName + ");");
					println("astFactory.makeASTRoot(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
					break;
				default:
					break;
				}
			}
			if (doNoGuessTest) {
				tabs--;
				println("}");
			}
		}
	}
	/** Close the try block and generate catch phrases
	 * if the element has a labeled handler in the rule
	 */
	private void genErrorCatchForElement(AlternativeElement el) {
		if (el.getLabel() == null) return;
		String r = el.enclosingRuleName;
		if ( grammar instanceof LexerGrammar ) {
			r = CodeGenerator.lexerRuleName(el.enclosingRuleName);
		}
		RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
		if (rs == null) {
			tool.panic("Enclosing rule not found!");
		}
		ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
		if (ex != null) {
			tabs--;
			println("}");
			genErrorHandler(ex);

⌨️ 快捷键说明

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