use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class ATNOptimizer method optimizeSets.
private static void optimizeSets(Grammar g, ATN atn) {
if (g.isParser()) {
// parser codegen doesn't currently support SetTransition
return;
}
int removedStates = 0;
List<DecisionState> decisions = atn.decisionToState;
for (DecisionState decision : decisions) {
if (decision.ruleIndex >= 0) {
Rule rule = g.getRule(decision.ruleIndex);
if (Character.isLowerCase(rule.name.charAt(0))) {
// parser codegen doesn't currently support SetTransition
continue;
}
}
IntervalSet setTransitions = new IntervalSet();
for (int i = 0; i < decision.getNumberOfTransitions(); i++) {
Transition epsTransition = decision.transition(i);
if (!(epsTransition instanceof EpsilonTransition)) {
continue;
}
if (epsTransition.target.getNumberOfTransitions() != 1) {
continue;
}
Transition transition = epsTransition.target.transition(0);
if (!(transition.target instanceof BlockEndState)) {
continue;
}
if (transition instanceof NotSetTransition) {
// TODO: not yet implemented
continue;
}
if (transition instanceof AtomTransition || transition instanceof RangeTransition || transition instanceof SetTransition) {
setTransitions.add(i);
}
}
// due to min alt resolution policies, can only collapse sequential alts
for (int i = setTransitions.getIntervals().size() - 1; i >= 0; i--) {
Interval interval = setTransitions.getIntervals().get(i);
if (interval.length() <= 1) {
continue;
}
ATNState blockEndState = decision.transition(interval.a).target.transition(0).target;
IntervalSet matchSet = new IntervalSet();
for (int j = interval.a; j <= interval.b; j++) {
Transition matchTransition = decision.transition(j).target.transition(0);
if (matchTransition instanceof NotSetTransition) {
throw new UnsupportedOperationException("Not yet implemented.");
}
IntervalSet set = matchTransition.label();
List<Interval> intervals = set.getIntervals();
int n = intervals.size();
for (int k = 0; k < n; k++) {
Interval setInterval = intervals.get(k);
int a = setInterval.a;
int b = setInterval.b;
if (a != -1 && b != -1) {
for (int v = a; v <= b; v++) {
if (matchSet.contains(v)) {
// TODO: Token is missing (i.e. position in source will not be displayed).
g.tool.errMgr.grammarError(ErrorType.CHARACTERS_COLLISION_IN_SET, g.fileName, null, CharSupport.getANTLRCharLiteralForChar(v), CharSupport.getIntervalSetEscapedString(matchSet));
break;
}
}
}
}
matchSet.addAll(set);
}
Transition newTransition;
if (matchSet.getIntervals().size() == 1) {
if (matchSet.size() == 1) {
newTransition = CodePointTransitions.createWithCodePoint(blockEndState, matchSet.getMinElement());
} else {
Interval matchInterval = matchSet.getIntervals().get(0);
newTransition = CodePointTransitions.createWithCodePointRange(blockEndState, matchInterval.a, matchInterval.b);
}
} else {
newTransition = new SetTransition(blockEndState, matchSet);
}
decision.transition(interval.a).target.setTransition(0, newTransition);
for (int j = interval.a + 1; j <= interval.b; j++) {
Transition removed = decision.removeTransition(interval.a + 1);
atn.removeState(removed.target);
removedStates++;
}
}
}
// System.out.println("ATN optimizer removed " + removedStates + " states by collapsing sets.");
}
use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class TestTokenPositionOptions method testLeftRecursionWithSet.
@Test
public void testLeftRecursionWithSet() throws Exception {
Grammar g = new Grammar("grammar T;\n" + "s : e ';' ;\n" + "e : e op=('*'|'/') 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 49))) (e (ELEMENT_OPTIONS (= tokenIndex 51) (= p 2)))) (ALT (ID (ELEMENT_OPTIONS (= tokenIndex 55))))) (* (BLOCK (ALT ({precpred(_ctx, 5)}? (ELEMENT_OPTIONS (= p 5))) (= op (SET ('*' (ELEMENT_OPTIONS (= tokenIndex 24))) ('/' (ELEMENT_OPTIONS (= tokenIndex 26))))) (e (ELEMENT_OPTIONS (= tokenIndex 29) (= p 6)))) (ALT ({precpred(_ctx, 4)}? (ELEMENT_OPTIONS (= p 4))) ('+' (ELEMENT_OPTIONS (= tokenIndex 35))) (e (ELEMENT_OPTIONS (= tokenIndex 37) (= p 5)))) (ALT ({precpred(_ctx, 3)}? (ELEMENT_OPTIONS (= p 3))) ('.' (ELEMENT_OPTIONS (= tokenIndex 43))) (ID (ELEMENT_OPTIONS (= tokenIndex 45)))))))))))";
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" + "[@49,73:75=''-'',<62>,6:4]\n" + "[@51,77:77='e',<57>,6:8]\n" + "[@55,83:84='ID',<66>,7:4]\n" + "[@24,33:35=''*'',<62>,3:10]\n" + "[@26,37:39=''/'',<62>,3:14]\n" + "[@29,42:42='e',<57>,3:19]\n" + "[@35,50:52=''+'',<62>,4:6]\n" + "[@37,54:54='e',<57>,4:10]\n" + "[@43,62:64=''.'',<62>,5:6]\n" + "[@45,66:67='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.runtime.misc.IntervalSet in project antlr4 by antlr.
the class TestIntervalSet method testNotSetFragmentedVocabulary.
@Test
public void testNotSetFragmentedVocabulary() throws Exception {
IntervalSet vocabulary = IntervalSet.of(1, 255);
vocabulary.add(1000, 2000);
vocabulary.add(9999);
IntervalSet s = IntervalSet.of(50, 60);
s.add(3);
s.add(250, 300);
// this is outside range of vocab and should be ignored
s.add(10000);
String expecting = "{1..2, 4..49, 61..249, 1000..2000, 9999}";
String result = (s.complement(vocabulary)).toString();
assertEquals(expecting, result);
}
use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class TestIntervalSet method testMergeWhereAdditionMergesThreeExistingIntervals.
/**
* This case is responsible for antlr/antlr4#153.
* https://github.com/antlr/antlr4/issues/153
*/
@Test
public void testMergeWhereAdditionMergesThreeExistingIntervals() throws Exception {
IntervalSet s = new IntervalSet();
s.add(0);
s.add(3);
s.add(5);
s.add(0, 7);
String expecting = "{0..7}";
String result = s.toString();
assertEquals(expecting, result);
}
use of org.antlr.v4.runtime.misc.IntervalSet in project antlr4 by antlr.
the class TestIntervalSet method testMembership.
@Test
public void testMembership() throws Exception {
IntervalSet s = IntervalSet.of(15, 15);
s.add(50, 60);
assertTrue(!s.contains(0));
assertTrue(!s.contains(20));
assertTrue(!s.contains(100));
assertTrue(s.contains(15));
assertTrue(s.contains(55));
assertTrue(s.contains(50));
assertTrue(s.contains(60));
}
Aggregations