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

📄 sathercodegenerator.java

📁 SRI international 发布的OAA框架软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			"| " +
			charList + 
			" |;"
			);
		println( "const " + bitsetName + " : INT_SET := int_set( " +
			 bitsetData + " );" );
			    
	    }
	}
    }
    /** Generate the finish of a block, using a combination of the info
	 * returned from genCommonBlock() and the action to perform when
	 * no alts were taken
	 * @param howToFinish The return of genCommonBlock()
	 * @param noViableAction What to generate when no alt is taken
	 */
    private void genBlockFinish(JavaBlockFinishingInfo howToFinish, String noViableAction)
    {
	if (howToFinish.needAnErrorClause &&
	    (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {

	    if ( howToFinish.generatedAnIf ) {
		tabs++;
		println("else");
	    }
	    else {
  				// println("{");
	    }
	    tabs++;
	    println(noViableAction);
	    tabs--;
	    if ( howToFinish.generatedAnIf ) {
		println("end; -- if");
		tabs--;
	    }

	    if ( howToFinish.generatedSwitch )
		println("end; -- case");

	}

	if ( !howToFinish.needAnErrorClause && howToFinish.generatedSwitch )
	    println("end; -- case");

	if ( howToFinish.postscript!=null ) {
	    println(howToFinish.postscript);
	}
    }
    /** Generate the header for a block, which may be a RuleBlock or a
	 * plain AlternativeBLock.  This generates any variable declarations,
	 * init-actions, and syntactic-predicate-testing variables.
	 * @blk The block for which the preamble is to be generated.
	 */
    protected void genBlockPreamble(AlternativeBlock blk) {
	// define labels for rule blocks.
	if ( blk instanceof RuleBlock ) {
	    RuleBlock rblk = (RuleBlock)blk;
	    if ( rblk.labeledElements!=null ) {
		for (int i=0; i<rblk.labeledElements.size(); i++) {

		    AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
		    //System.out.println("looking at labeled element: "+a);
		    // Variables for labeled rule refs and subrules are different than
		    // variables for grammar atoms.  This test is a little tricky because
		    // we want to get all rule refs and ebnf, but not rule blocks or
		    // syntactic predicates
		    if (
			a instanceof RuleRefElement ||
			a instanceof AlternativeBlock &&
			!(a instanceof RuleBlock) &&
			!(a instanceof SynPredBlock)
			) {

			if (
			    !(a instanceof RuleRefElement) && 
			    ((AlternativeBlock)a).not &&
			    analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
			    ) {
			    // Special case for inverted subrules that will be inlined.
			    // Treat these like token or char literal references
			    println( a.getLabel() + " : " + labeledElementType + " := " + labeledElementInit + ";");
			    if (grammar.buildAST) {
				println( a.getLabel() + "_ast : " + labeledElementASTType+ ";" );
			    }
			}
			else {
			    if (grammar.buildAST) {
				// Always gen AST variables for labeled elements, even if the
				// element itself is marked with !
				println( a.getLabel() + "_ast : " + labeledElementASTType+ ";" );
			    }
			    if ( grammar instanceof LexerGrammar ) {
				println( a.getLabel() + " : $ANTLR_TOKEN; " );
			    }	
			    if (grammar instanceof TreeWalkerGrammar) {
				// always generate rule-ref variables for tree walker
				println(  a.getLabel() + " : " + labeledElementType + " := " + labeledElementInit + ";");
			    }
			}
		    }
		    else {
			// It is a token or literal reference.  Generate the
			// correct variable type for this grammar
			println( a.getLabel() + " : " + labeledElementType + " := " + labeledElementInit + ";");
			// In addition, generate *_AST variables if building ASTs
			if (grammar.buildAST) {
			    println( a.getLabel() + "_ast : " + labeledElementASTType + ";");
			}
		    }
		}
	    }
	}

	// dump out init action
	if ( blk.initAction!=null ) {
	    printAction(
			processActionForTreeSpecifiers(blk.initAction, 0, currentRule, null)
			);
	}
    }
    /** Generate a series of case statements that implement a BitSet test.
	 * @param p The Bitset for which cases are to be generated
	 */
    protected void genCases(BitSet p) {
	if ( DEBUG_CODE_GENERATOR ) System.out.println("genCases("+p+")");
	int[] elems;

	elems = p.toArray();
	// Wrap cases four-per-line for lexer, one-per-line for parser
	int wrap = (grammar instanceof LexerGrammar) ? 4 : 1;
	int j=1;
	boolean startOfLine = true;
	for (int i = 0; i < elems.length; i++) {
	    if (j==1) {
		print("");
	    } else {
		_print("  ");
	    }
	    if ( i == 0 )
		_print("when " + getValueString(elems[i]) );
	    else
		_print(", " + getValueString(elems[i]) );

	    if (j==wrap) {
		_println(""); 
		startOfLine = true;
		j=1;
	    }
	    else {
		j++;
		startOfLine = false;
	    }
	}
	if (!startOfLine) {
	    _println("");
	}
    }
    /**Generate common code for a block of alternatives; return a postscript
	 * that needs to be generated at the end of the block.  Other routines
	 * may append else-clauses and such for error checking before the postfix
	 * is generated.
	 * If the grammar is a lexer, then generate alternatives in an order where 
	 * alternatives requiring deeper lookahead are generated first, and 
	 * EOF in the lookahead set reduces the depth of the lookahead.
	 * @param blk The block to generate
	 * @param noTestForSingle If true, then it does not generate a test for a single alternative.
	 */
    public JavaBlockFinishingInfo genCommonBlock(
						 AlternativeBlock blk, 
						 boolean noTestForSingle)
    {
	int nIF=0;
	boolean createdLL1Switch = false;
	int closingBracesOfIFSequence = 0;
	JavaBlockFinishingInfo finishingInfo = new JavaBlockFinishingInfo();
	if ( DEBUG_CODE_GENERATOR ) System.out.println("genCommonBlk("+blk+")");

	// Save the AST generation state, and set it to that of the block
	boolean savegenAST = genAST;
	genAST = genAST && blk.getAutoGen();
		
	boolean oldsaveTest = saveText;
	saveText = saveText && blk.getAutoGen();

	// Is this block inverted?  If so, generate special-case code
	if (
	    blk.not &&
	    analyzer.subruleCanBeInverted(blk, grammar instanceof LexerGrammar)
	    ) {
	    Lookahead p = analyzer.look(1, blk);
	    // Variable assignment for labeled elements
	    if (blk.getLabel() != null && syntacticPredLevel == 0) {
		println(blk.getLabel() + " := " + lt1Value + ";");
	    }

	    // AST

	    genElementAST(blk);

	    String astArgs="";
	    if (grammar instanceof TreeWalkerGrammar) {
		astArgs="sa_t,";
	    }

	    // match the bitset for the alternative
	    println("match( sa" + astArgs + getBitsetName(markBitsetForGen(p.fset)) + ");");

	    // tack on tree cursor motion if doing a tree walker
	    if (grammar instanceof TreeWalkerGrammar) {
		println("sa_t := sa_t.next_sibling;");
	    }
	    return finishingInfo;
	}

	// Special handling for single alt
	if (blk.getAlternatives().size() == 1) {
	    Alternative alt = blk.getAlternativeAt(0);
	    // 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 ( void(sa_t) ) then");
		tabs++;
		println("sa_t := AST::ASTNULL;");
		tabs--;
		println("end; -- if");
	    }
	    println("case ( " + 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 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("then");
		    tabs++;
		    genAlt(alt, blk);
		    //					println("break;");
		    tabs--;
		    //					println("}");
		}
	    }
	    println("else -- 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);
		}

		boolean defaultBlock = true;

		// Was it a big unicode range that forced
		// unsuitability for a case expression?
		if ( alt.cache[1].fset.degree()>caseSizeThreshold ) {
		    if ( nIF==0 ) {
			println("if " + e + " then");
		    }
		    else {
			println("elsif " + e + " then");
		    }
		}
		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 ");
			defaultBlock = false;  // else is for an if statement, not a case statement.
		    }			
		    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

⌨️ 快捷键说明

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