use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class TestTokenPositionOptions method testLeftRecursionRewrite.
@Test
public void testLeftRecursionRewrite() throws Exception {
Grammar g = new Grammar("grammar T;\n" + "s : e ';' ;\n" + "e : e '*' e\n" + " | e '+' e\n" + " | e '.' ID\n" + " | '-' e\n" + " | ID\n" + " ;\n" + "ID : [a-z]+ ;\n");
String expectedTree = "(COMBINED_GRAMMAR T (RULES (RULE s (BLOCK (ALT e ';'))) (RULE e (BLOCK (ALT (BLOCK (ALT {} ('-' (ELEMENT_OPTIONS (= tokenIndex 43))) (e (ELEMENT_OPTIONS (= tokenIndex 45) (= p 2)))) (ALT (ID (ELEMENT_OPTIONS (= tokenIndex 49))))) (* (BLOCK (ALT ({precpred(_ctx, 5)}? (ELEMENT_OPTIONS (= p 5))) ('*' (ELEMENT_OPTIONS (= tokenIndex 21))) (e (ELEMENT_OPTIONS (= tokenIndex 23) (= p 6)))) (ALT ({precpred(_ctx, 4)}? (ELEMENT_OPTIONS (= p 4))) ('+' (ELEMENT_OPTIONS (= tokenIndex 29))) (e (ELEMENT_OPTIONS (= tokenIndex 31) (= p 5)))) (ALT ({precpred(_ctx, 3)}? (ELEMENT_OPTIONS (= p 3))) ('.' (ELEMENT_OPTIONS (= tokenIndex 37))) (ID (ELEMENT_OPTIONS (= tokenIndex 39)))))))))))";
assertEquals(expectedTree, g.ast.toStringTree());
String expectedElementTokens = "[@5,11:11='s',<57>,2:0]\n" + "[@9,15:15='e',<57>,2:4]\n" + "[@11,17:19='';'',<62>,2:6]\n" + "[@15,23:23='e',<57>,3:0]\n" + "[@43,64:66=''-'',<62>,6:4]\n" + "[@45,68:68='e',<57>,6:8]\n" + "[@49,74:75='ID',<66>,7:4]\n" + "[@21,29:31=''*'',<62>,3:6]\n" + "[@23,33:33='e',<57>,3:10]\n" + "[@29,41:43=''+'',<62>,4:6]\n" + "[@31,45:45='e',<57>,4:10]\n" + "[@37,53:55=''.'',<62>,5:6]\n" + "[@39,57:58='ID',<66>,5:10]";
IntervalSet types = new IntervalSet(ANTLRParser.TOKEN_REF, ANTLRParser.STRING_LITERAL, ANTLRParser.RULE_REF);
List<GrammarAST> nodes = g.ast.getNodesWithTypePreorderDFS(types);
List<Token> tokens = new ArrayList<Token>();
for (GrammarAST node : nodes) {
tokens.add(node.getToken());
}
assertEquals(expectedElementTokens, Utils.join(tokens.toArray(), "\n"));
}
use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class TestTokenPositionOptions method testLeftRecursionWithLabels.
@Test
public void testLeftRecursionWithLabels() throws Exception {
Grammar g = new Grammar("grammar T;\n" + "s : e ';' ;\n" + "e : e '*' x=e\n" + " | e '+' e\n" + " | e '.' y=ID\n" + " | '-' e\n" + " | ID\n" + " ;\n" + "ID : [a-z]+ ;\n");
String expectedTree = "(COMBINED_GRAMMAR T (RULES (RULE s (BLOCK (ALT e ';'))) (RULE e (BLOCK (ALT (BLOCK (ALT {} ('-' (ELEMENT_OPTIONS (= tokenIndex 47))) (e (ELEMENT_OPTIONS (= tokenIndex 49) (= p 2)))) (ALT (ID (ELEMENT_OPTIONS (= tokenIndex 53))))) (* (BLOCK (ALT ({precpred(_ctx, 5)}? (ELEMENT_OPTIONS (= p 5))) ('*' (ELEMENT_OPTIONS (= tokenIndex 21))) (= x (e (ELEMENT_OPTIONS (= tokenIndex 25) (= p 6))))) (ALT ({precpred(_ctx, 4)}? (ELEMENT_OPTIONS (= p 4))) ('+' (ELEMENT_OPTIONS (= tokenIndex 31))) (e (ELEMENT_OPTIONS (= tokenIndex 33) (= p 5)))) (ALT ({precpred(_ctx, 3)}? (ELEMENT_OPTIONS (= p 3))) ('.' (ELEMENT_OPTIONS (= tokenIndex 39))) (= y (ID (ELEMENT_OPTIONS (= tokenIndex 43))))))))))))";
assertEquals(expectedTree, g.ast.toStringTree());
String expectedElementTokens = "[@5,11:11='s',<57>,2:0]\n" + "[@9,15:15='e',<57>,2:4]\n" + "[@11,17:19='';'',<62>,2:6]\n" + "[@15,23:23='e',<57>,3:0]\n" + "[@47,68:70=''-'',<62>,6:4]\n" + "[@49,72:72='e',<57>,6:8]\n" + "[@53,78:79='ID',<66>,7:4]\n" + "[@21,29:31=''*'',<62>,3:6]\n" + "[@25,35:35='e',<57>,3:12]\n" + "[@31,43:45=''+'',<62>,4:6]\n" + "[@33,47:47='e',<57>,4:10]\n" + "[@39,55:57=''.'',<62>,5:6]\n" + "[@43,61:62='ID',<66>,5:12]";
IntervalSet types = new IntervalSet(ANTLRParser.TOKEN_REF, ANTLRParser.STRING_LITERAL, ANTLRParser.RULE_REF);
List<GrammarAST> nodes = g.ast.getNodesWithTypePreorderDFS(types);
List<Token> tokens = new ArrayList<Token>();
for (GrammarAST node : nodes) {
tokens.add(node.getToken());
}
assertEquals(expectedElementTokens, Utils.join(tokens.toArray(), "\n"));
}
use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class LeftRecursiveRuleAnalyzer method stripLeftRecursion.
// TODO: this strips the tree properly, but since text()
// uses the start of stop token index and gets text from that
// ineffectively ignores this routine.
public GrammarAST stripLeftRecursion(GrammarAST altAST) {
GrammarAST lrlabel = null;
GrammarAST first = (GrammarAST) altAST.getChild(0);
int leftRecurRuleIndex = 0;
if (first.getType() == ELEMENT_OPTIONS) {
first = (GrammarAST) altAST.getChild(1);
leftRecurRuleIndex = 1;
}
// if label=rule
Tree rref = first.getChild(1);
if ((first.getType() == RULE_REF && first.getText().equals(ruleName)) || (rref != null && rref.getType() == RULE_REF && rref.getText().equals(ruleName))) {
if (first.getType() == ASSIGN || first.getType() == PLUS_ASSIGN)
lrlabel = (GrammarAST) first.getChild(0);
// remove rule ref (first child unless options present)
altAST.deleteChild(leftRecurRuleIndex);
// reset index so it prints properly (sets token range of
// ALT to start to right of left recur rule we deleted)
GrammarAST newFirstChild = (GrammarAST) altAST.getChild(leftRecurRuleIndex);
altAST.setTokenStartIndex(newFirstChild.getTokenStartIndex());
}
return lrlabel;
}
use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class LeftRecursiveRuleAnalyzer method suffixAlt.
@Override
public void suffixAlt(AltAST originalAltTree, int alt) {
AltAST altTree = (AltAST) originalAltTree.dupTree();
String altLabel = altTree.altLabel != null ? altTree.altLabel.getText() : null;
String label = null;
boolean isListLabel = false;
GrammarAST lrlabel = stripLeftRecursion(altTree);
if (lrlabel != null) {
label = lrlabel.getText();
isListLabel = lrlabel.getParent().getType() == PLUS_ASSIGN;
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST, String>(lrlabel, altLabel));
}
stripAltLabel(altTree);
String altText = text(altTree);
altText = altText.trim();
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel, isListLabel, originalAltTree);
suffixAlts.put(alt, a);
// System.out.println("suffixAlt " + alt + ": " + altText + ", rewrite=" + rewriteText);
}
use of org.antlr.v4.tool.ast.GrammarAST in project antlr4 by antlr.
the class LeftRecursiveRuleAnalyzer method hasImmediateRecursiveRuleRefs.
/**
* Match (RULE RULE_REF (BLOCK (ALT .*) (ALT RULE_REF[self] .*) (ALT .*)))
* Match (RULE RULE_REF (BLOCK (ALT .*) (ALT (ASSIGN ID RULE_REF[self]) .*) (ALT .*)))
*/
public static boolean hasImmediateRecursiveRuleRefs(GrammarAST t, String ruleName) {
if (t == null)
return false;
GrammarAST blk = (GrammarAST) t.getFirstChildWithType(BLOCK);
if (blk == null)
return false;
int n = blk.getChildren().size();
for (int i = 0; i < n; i++) {
GrammarAST alt = (GrammarAST) blk.getChildren().get(i);
Tree first = alt.getChild(0);
if (first == null)
continue;
if (first.getType() == ELEMENT_OPTIONS) {
first = alt.getChild(1);
if (first == null) {
continue;
}
}
if (first.getType() == RULE_REF && first.getText().equals(ruleName))
return true;
Tree rref = first.getChild(1);
if (rref != null && rref.getType() == RULE_REF && rref.getText().equals(ruleName))
return true;
}
return false;
}
Aggregations