added more DFA unit tests
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6807]
This commit is contained in:
parent
dcadda638e
commit
47a3f66fea
|
@ -242,7 +242,7 @@ CONFLICTING_OPTION_IN_TREE_FILTER(arg,arg2) ::=
|
|||
|
||||
AMBIGUITY(arg) ::= <<
|
||||
Decision can match input such as "<arg.input>" using multiple alternatives:
|
||||
<arg.conflictingPaths.keys:{alt | alt <alt> via tokens <arg.conflictingPaths.(alt); separator=",">}>
|
||||
<arg.conflictingPaths.keys:{alt | alt <alt> via token <arg.conflictingPaths.(alt):{t | <t.text> at line <t.line>:<t.charPositionInLine>}; separator=",">}; separator=" and ">
|
||||
<if(arg.hasPredicateBlockedByAction)><\n>At least one possibly relevant semantic predicate was hidden by action(s).<endif>
|
||||
>>
|
||||
|
||||
|
|
|
@ -43,6 +43,18 @@ public class Utils {
|
|||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String join(Object[] a, String separator) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (int i=0; i<a.length; i++) {
|
||||
Object o = a[i];
|
||||
buf.append(o.toString());
|
||||
if ( (i+1)<a.length ) {
|
||||
buf.append(separator);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/** Given a source string, src,
|
||||
a string to replace, replacee,
|
||||
and a string to replace with, replacer,
|
||||
|
|
|
@ -166,6 +166,7 @@ public class ErrorManager {
|
|||
}
|
||||
|
||||
public static void resetErrorState() {
|
||||
state.set(new ErrorState());
|
||||
}
|
||||
|
||||
public static void info(Object... args) {
|
||||
|
|
|
@ -82,7 +82,8 @@ public abstract class BaseTest {
|
|||
public void setUp() throws Exception {
|
||||
lastTestFailed = false; // hope for the best, but set to true in asserts that fail
|
||||
// new output dir for each test
|
||||
tmpdir = new File(System.getProperty("java.io.tmpdir"), "antlr-"+getClass().getName()+"-"+System.currentTimeMillis()).getAbsolutePath();
|
||||
tmpdir = new File(System.getProperty("java.io.tmpdir"),
|
||||
"antlr-"+getClass().getName()+"-"+System.currentTimeMillis()).getAbsolutePath();
|
||||
ErrorManager.resetErrorState();
|
||||
}
|
||||
|
||||
|
@ -150,13 +151,31 @@ public abstract class BaseTest {
|
|||
return null;
|
||||
}
|
||||
DecisionState blk = (DecisionState)s.transition(0).target;
|
||||
checkRuleDFA(g, blk, expecting);
|
||||
return equeue.all;
|
||||
}
|
||||
|
||||
List<Message> checkRuleDFA(String gtext, int decision, String expecting)
|
||||
throws Exception
|
||||
{
|
||||
ErrorQueue equeue = new ErrorQueue();
|
||||
ErrorManager.setErrorListener(equeue);
|
||||
|
||||
Grammar g = new Grammar(gtext);
|
||||
NFA nfa = createNFA(g);
|
||||
System.out.println("# decs="+nfa.decisionToNFAState.size());
|
||||
DecisionState blk = nfa.decisionToNFAState.get(decision);
|
||||
checkRuleDFA(g, blk, expecting);
|
||||
return equeue.all;
|
||||
}
|
||||
|
||||
void checkRuleDFA(Grammar g, DecisionState blk, String expecting)
|
||||
throws Exception
|
||||
{
|
||||
DFA dfa = createDFA(g, blk);
|
||||
String result = null;
|
||||
if ( dfa!=null ) result = dfa.toString();
|
||||
assertEquals(expecting, result);
|
||||
|
||||
return equeue.all;
|
||||
}
|
||||
|
||||
List<Message> checkLexerDFA(String gtext, String expecting)
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package org.antlr.v4.test;
|
||||
|
||||
import org.antlr.v4.tool.AmbiguityMessage;
|
||||
import org.antlr.v4.tool.Message;
|
||||
import org.antlr.v4.tool.UnreachableAltsMessage;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class TestDFAConstruction extends BaseTest {
|
||||
|
@ -105,16 +109,145 @@ public class TestDFAConstruction extends BaseTest {
|
|||
System.out.println(msgs);
|
||||
}
|
||||
|
||||
@Test public void testMultiAltsWithRecursion() throws Exception {
|
||||
String g =
|
||||
"parser grammar T;\n" +
|
||||
"s : b X\n" +
|
||||
" | b Y\n" +
|
||||
" ;\n" +
|
||||
"b : L b R\n" +
|
||||
" | A b B\n" +
|
||||
" | I\n" +
|
||||
" ;";
|
||||
String expecting =
|
||||
"s0-A->s1\n" +
|
||||
"s0-I->s3\n" +
|
||||
"s0-L->s2\n" +
|
||||
"s1-A->s1\n" +
|
||||
"s1-I->s3\n" +
|
||||
"s1-L->s2\n" +
|
||||
"s2-A->s1\n" +
|
||||
"s2-I->s3\n" +
|
||||
"s2-L->s2\n" +
|
||||
"s3-B->s4\n" +
|
||||
"s3-R->s5\n" +
|
||||
"s3-X->:s7=>1\n" +
|
||||
"s3-Y->:s6=>2\n" +
|
||||
"s4-B->s4\n" +
|
||||
"s4-R->s5\n" +
|
||||
"s4-X->:s7=>1\n" +
|
||||
"s4-Y->:s6=>2\n" +
|
||||
"s5-B->s4\n" +
|
||||
"s5-R->s5\n" +
|
||||
"s5-X->:s7=>1\n" +
|
||||
"s5-Y->:s6=>2\n";
|
||||
checkRuleDFA(g, "s", expecting);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test public void _template() throws Exception {
|
||||
@Test public void recursionInMultipleWithoutNonRecursiveAlt() throws Exception {
|
||||
String g =
|
||||
"parser grammar t;\n"+
|
||||
"a : A a X | A a Y;";
|
||||
String expecting =
|
||||
"s0-A->:s1=>1\n";
|
||||
List<Message> msgs = checkRuleDFA(g, "a", expecting);
|
||||
System.out.println(msgs);
|
||||
ambig(msgs, new int[] {1,2}, "A");
|
||||
unreachable(msgs, new int[] {2});
|
||||
assertEquals(msgs.size(), 2);
|
||||
}
|
||||
|
||||
@Test public void emptyAndNonEmptyContextStack() throws Exception {
|
||||
String g =
|
||||
"parser grammar S4;\n" +
|
||||
"a : A+ ;\n" +
|
||||
"x : a a ;";
|
||||
String expecting =
|
||||
"s0-A->:s1=>1\n" +
|
||||
"s0-EOF->:s2=>1\n";
|
||||
List<Message> msgs = checkRuleDFA(g, 0, expecting);
|
||||
System.out.println(msgs);
|
||||
ambig(msgs, new int[] {1,2}, "A");
|
||||
unreachable(msgs, new int[] {2});
|
||||
assertEquals(msgs.size(), 2);
|
||||
}
|
||||
|
||||
|
||||
@Test public void simpleNullableRule() throws Exception {
|
||||
String g =
|
||||
"parser grammar S2;\n" +
|
||||
"a : b X \n" +
|
||||
" | b Y\n" +
|
||||
" ; \n" +
|
||||
"b : F \n" +
|
||||
" | \n" +
|
||||
" ;";
|
||||
String expecting =
|
||||
"s0-F->s1\n" +
|
||||
"s0-X->:s3=>1\n" +
|
||||
"s0-Y->:s2=>2\n" +
|
||||
"s1-X->:s3=>1\n" +
|
||||
"s1-Y->:s2=>2\n";
|
||||
List<Message> msgs = checkRuleDFA(g, "a", expecting);
|
||||
System.out.println(msgs);
|
||||
assertEquals(msgs.size(), 0);
|
||||
}
|
||||
|
||||
public void _template() throws Exception {
|
||||
String g =
|
||||
"";
|
||||
String expecting =
|
||||
"";
|
||||
checkRuleDFA(g, "a", expecting);
|
||||
List<Message> msgs = checkRuleDFA(g, "a", expecting);
|
||||
System.out.println(msgs);
|
||||
//ambig(msgs, new int[] {1,2}, "A");
|
||||
//unreachable(msgs, new int[] {2});
|
||||
assertEquals(msgs.size(), 2);
|
||||
}
|
||||
|
||||
void ambig(List<Message> msgs, int[] expectedAmbigAlts, String expectedAmbigInput)
|
||||
throws Exception
|
||||
{
|
||||
ambig(msgs, 0, expectedAmbigAlts, expectedAmbigInput);
|
||||
}
|
||||
|
||||
void ambig(List<Message> msgs, int i, int[] expectedAmbigAlts, String expectedAmbigInput)
|
||||
throws Exception
|
||||
{
|
||||
List<Message> amsgs = getMessagesOfType(msgs, AmbiguityMessage.class);
|
||||
AmbiguityMessage a = (AmbiguityMessage)amsgs.get(i);
|
||||
if ( a==null ) assertNull(expectedAmbigAlts);
|
||||
else {
|
||||
assertEquals(a.conflictingAlts.toString(), Arrays.toString(expectedAmbigAlts));
|
||||
}
|
||||
assertEquals(expectedAmbigInput, a.input);
|
||||
}
|
||||
|
||||
void unreachable(List<Message> msgs, int[] expectedUnreachableAlts)
|
||||
throws Exception
|
||||
{
|
||||
unreachable(msgs, 0, expectedUnreachableAlts);
|
||||
}
|
||||
|
||||
void unreachable(List<Message> msgs, int i, int[] expectedUnreachableAlts)
|
||||
throws Exception
|
||||
{
|
||||
List<Message> amsgs = getMessagesOfType(msgs, UnreachableAltsMessage.class);
|
||||
UnreachableAltsMessage u = (UnreachableAltsMessage)amsgs.get(i);
|
||||
if ( u==null ) assertNull(expectedUnreachableAlts);
|
||||
else {
|
||||
assertEquals(u.conflictingAlts.toString(), Arrays.toString(expectedUnreachableAlts));
|
||||
}
|
||||
}
|
||||
|
||||
List<Message> getMessagesOfType(List<Message> msgs, Class c) {
|
||||
List<Message> filtered = new ArrayList<Message>();
|
||||
for (Message m : msgs) {
|
||||
if ( m.getClass() == c ) filtered.add(m);
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,12 +26,12 @@ public class TestLexerDFAConstruction extends BaseTest {
|
|||
String expecting =
|
||||
":s1=> INT-{'0'..'9'}->:s1=> INT\n" +
|
||||
":s2=> ID-{'a'..'z'}->:s2=> ID\n" +
|
||||
":s3=> ID-'f'->:s4=> ID IF\n" +
|
||||
":s3=> ID-'f'->:s4=> IF ID\n" +
|
||||
":s3=> ID-{'a'..'e', 'g'..'z'}->:s2=> ID\n" +
|
||||
":s4=> ID IF-{'a'..'z'}->:s2=> ID\n" +
|
||||
":s4=> IF ID-{'a'..'z'}->:s2=> ID\n" +
|
||||
"s0-'i'->:s3=> ID\n" +
|
||||
"s0-{'0'..'9'}->:s1=> INT\n" +
|
||||
"s0-{'a'..'h', 'j'..'z'}->:s2=> ID";
|
||||
"s0-{'a'..'h', 'j'..'z'}->:s2=> ID\n";
|
||||
checkLexerDFA(g, expecting);
|
||||
}
|
||||
|
||||
|
@ -68,24 +68,7 @@ public class TestLexerDFAConstruction extends BaseTest {
|
|||
checkLexerDFA(g, expecting);
|
||||
}
|
||||
|
||||
@Test public void _t3emplate() throws Exception {
|
||||
String g =
|
||||
"";
|
||||
String expecting =
|
||||
"";
|
||||
checkLexerDFA(g, expecting);
|
||||
}
|
||||
|
||||
@Test public void _templ33ate() throws Exception {
|
||||
String g =
|
||||
"";
|
||||
String expecting =
|
||||
"";
|
||||
checkLexerDFA(g, expecting);
|
||||
}
|
||||
|
||||
|
||||
@Test public void _template() throws Exception {
|
||||
public void _template() throws Exception {
|
||||
String g =
|
||||
"";
|
||||
String expecting =
|
||||
|
|
|
@ -20,6 +20,19 @@ public class TestLinearApproximateLookahead extends BaseTest {
|
|||
checkRule(g, "a", expecting);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLL1Chain() throws Exception {
|
||||
String g =
|
||||
"parser grammar P;\n"+
|
||||
"a : b | B ;\n" +
|
||||
"b : c | C ;\n" +
|
||||
"c : D ;";
|
||||
String expecting =
|
||||
"s0-B->:s2=>2\n" +
|
||||
"s0-{D, C}->:s1=>1\n";
|
||||
checkRule(g, "a", expecting);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLL2Block() throws Exception {
|
||||
String g =
|
||||
|
@ -33,6 +46,33 @@ public class TestLinearApproximateLookahead extends BaseTest {
|
|||
checkRule(g, "a", expecting);
|
||||
}
|
||||
|
||||
@Test public void testLL1NullableRuleRef() throws Exception {
|
||||
String g =
|
||||
"parser grammar P;\n"+
|
||||
"a : b B | X b C ;\n" +
|
||||
"b : A | ;";
|
||||
String expecting =
|
||||
"s0-X->:s2=>2\n" +
|
||||
"s0-{A, B}->:s1=>1\n";
|
||||
checkRule(g, "a", expecting);
|
||||
}
|
||||
|
||||
@Test public void testLL2FOLLOW() throws Exception {
|
||||
String g =
|
||||
"parser grammar P;\n"+
|
||||
"a : X b Q | Y b Z ;\n" +
|
||||
"b : A B | A | ;\n" +
|
||||
"c : b C ;";
|
||||
String expecting =
|
||||
"s0-A->s1\n" +
|
||||
"s0-A->s3\n" +
|
||||
"s0-{Q, C, Z}->s5\n" +
|
||||
"s1-B->:s2=>1\n" +
|
||||
"s3-{Q, C, Z}->:s4=>2\n" +
|
||||
"s5-EOF->:s6=>3\n";
|
||||
checkRule(g, "b", expecting);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonDetLL1Block() throws Exception {
|
||||
String g =
|
||||
|
@ -57,6 +97,10 @@ public class TestLinearApproximateLookahead extends BaseTest {
|
|||
Grammar g = new Grammar(gtext);
|
||||
NFA nfa = createNFA(g);
|
||||
NFAState s = nfa.ruleToStartState.get(g.getRule(ruleName));
|
||||
if ( s==null ) {
|
||||
System.err.println("no start state for rule "+ruleName);
|
||||
return;
|
||||
}
|
||||
DecisionState blk = (DecisionState)s.transition(0).target;
|
||||
LinearApproximator lin = new LinearApproximator(g, blk.decision);
|
||||
DFA dfa = lin.createDFA(blk);
|
||||
|
|
|
@ -878,6 +878,7 @@ public class TestNFAConstruction extends BaseTest {
|
|||
String result = serializer.toString();
|
||||
|
||||
//System.out.print(result);
|
||||
System.out.println("test NFA checkRule: thread name: "+Thread.currentThread().getName());
|
||||
assertEquals(expecting, result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@ public class TestSymbolIssues extends BaseTest {
|
|||
"error(72): A.g:3:19: cannot alias X; token name already defined\n" +
|
||||
"error(72): A.g:3:26: cannot alias Y; token name already assigned to 'y'\n" +
|
||||
"error(72): A.g:3:36: cannot alias Z; token name already defined\n" +
|
||||
"error(46): A.g:13:32: rule a has no defined parameters\n" +
|
||||
"error(46): A.g:13:37: rule b has no defined parameters\n" +
|
||||
"error(23): A.g:13:43: reference to undefined rule: q"
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue