📄 cppcodegenerator.java
字号:
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;
}
// generate exit test if greedy set to false
// and an alt is ambiguous with exit branch
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 ( "+cnt+">=1 && "+predictExit+") goto "+label+";");
}
CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
genBlockFinish(
howToFinish,
"if ( "+cnt+">=1 ) { goto "+label+"; } else {" + throwNoViable + "}"
);
println(cnt+"++;");
tabs--;
println("}");
println(label+":;");
println("}");
// Restore previous AST generation
currentASTResult = saveCurrentASTResult;
}
/** Generate the parser C++ file */
public void gen(ParserGrammar g) throws IOException {
// if debugging, set up a new vector to keep track of sempred
// strings for this grammar
if (g.debuggingOutput)
semPreds = new Vector();
setGrammar(g);
if (!(grammar instanceof ParserGrammar)) {
tool.panic("Internal error generating parser");
}
genBody(g);
genInclude(g);
}
/** Generate code for the given grammar element.
* @param blk The rule-reference to generate
*/
public void gen(RuleRefElement rr) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("genRR("+rr+")");
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
if (rs == null || !rs.isDefined())
{
// Is this redundant???
tool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine());
return;
}
if (!(rs instanceof RuleSymbol))
{
// Is this redundant???
tool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine());
return;
}
genErrorTryForElement(rr);
// AST value for labeled rule refs in tree walker.
// This is not AST construction; it is just the input tree node value.
if ( grammar instanceof TreeWalkerGrammar &&
rr.getLabel() != null &&
syntacticPredLevel == 0 )
{
println(rr.getLabel() + " = (_t == ASTNULL) ? "+labeledElementASTInit+" : "+lt1Value+";");
}
// if in lexer and ! on rule ref or alt or rule, save buffer index to kill later
if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
println("_saveIndex = text.length();");
}
// Process return value assignment if any
printTabs();
if (rr.idAssign != null)
{
// Warn if the rule has no return type
if (rs.block.returnAction == null)
{
tool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine());
}
_print(rr.idAssign + "=");
} else {
// Warn about return value if any, but not inside syntactic predicate
if ( !(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
{
tool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine());
}
}
// Call the rule
GenRuleInvocation(rr);
// if in lexer and ! on element or alt or rule, save buffer index to kill later
if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
println("text.erase(_saveIndex);");
}
// if not in a syntactic predicate
if (syntacticPredLevel == 0) {
boolean doNoGuessTest = (
grammar.hasSyntacticPredicate &&
(
grammar.buildAST && rr.getLabel() != null ||
(genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
)
);
if (doNoGuessTest) {
println("if (inputState->guessing==0) {");
tabs++;
}
if (grammar.buildAST && rr.getLabel() != null) {
// always gen variable for rule return on labeled rules
// FIXME: maybe broken....
println(rr.getLabel() + "_AST = "+labeledElementASTType+"(returnAST);");
}
if (genAST) {
switch (rr.getAutoGenType()) {
case GrammarElement.AUTO_GEN_NONE:
// println("theASTFactory.addASTChild(currentAST, returnAST);");
println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(returnAST));");
break;
case GrammarElement.AUTO_GEN_CARET:
tool.error("Internal: encountered ^ after rule reference");
break;
default:
break;
}
}
// if a lexer and labeled, Token label defined at rule level, just set it here
if ( grammar instanceof LexerGrammar && rr.getLabel() != null ) {
println(rr.getLabel()+"=_returnToken;");
}
if (doNoGuessTest) {
tabs--;
println("}");
}
}
genErrorCatchForElement(rr);
}
/** Generate code for the given grammar element.
* @param blk The string-literal reference to generate
*/
public void gen(StringLiteralElement atom) {
if ( DEBUG_CODE_GENERATOR ) System.out.println("genString("+atom+")");
// Variable declarations for labeled elements
if (atom.getLabel()!=null && syntacticPredLevel == 0) {
println(atom.getLabel() + " = " + lt1Value + ";");
}
// AST
genElementAST(atom);
// is there a bang on the literal?
boolean oldsaveText = saveText;
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(labeledElementType+" __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 ? "+namespaceAntlr+"nullAST :"+labeledElementASTType+"(_t);");
println(t.root.getLabel() + " = (_t == ASTNULL) ? "+labeledElementASTInit+" : _t;");
}
// Generate AST variables
genElementAST(t.root);
if (grammar.buildAST) {
// Save the AST construction state
println(namespaceAntlr+"ASTPair __currentAST" + t.ID + " = currentAST;");
// Make the next item added a child of the TreeElement root
println("currentAST.root = currentAST.child;");
println("currentAST.child = "+labeledElementASTInit+";");
}
// 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 C++ files */
public void gen(TreeWalkerGrammar g) throws IOException {
setGrammar(g);
if (!(grammar instanceof TreeWalkerGrammar)) {
tool.panic("Internal error generating tree-walker");
}
genBody(g);
genInclude(g);
}
/** 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 == "+labeledElementASTInit+" ) throw "+namespaceAntlr+"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.erase(_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("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;
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+") goto "+label+";");
}
CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
genBlockFinish(howToFinish, "goto " + label + ";");
tabs--;
println("}");
println(label+":;");
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -