added more DFA unit tests

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6807]
This commit is contained in:
parrt 2010-04-10 16:19:10 -08:00
parent dcadda638e
commit 47a3f66fea
9 changed files with 220 additions and 29 deletions

View File

@ -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>
>>

View File

@ -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,

View File

@ -166,6 +166,7 @@ public class ErrorManager {
}
public static void resetErrorState() {
state.set(new ErrorState());
}
public static void info(Object... args) {

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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 =

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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"
};