0001: /*
0002: [The "BSD licence"]
0003: Copyright (c) 2005-2006 Terence Parr
0004: All rights reserved.
0005:
0006: Redistribution and use in source and binary forms, with or without
0007: modification, are permitted provided that the following conditions
0008: are met:
0009: 1. Redistributions of source code must retain the above copyright
0010: notice, this list of conditions and the following disclaimer.
0011: 2. Redistributions in binary form must reproduce the above copyright
0012: notice, this list of conditions and the following disclaimer in the
0013: documentation and/or other materials provided with the distribution.
0014: 3. The name of the author may not be used to endorse or promote products
0015: derived from this software without specific prior written permission.
0016:
0017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0027: */
0028: package org.antlr.test;
0029:
0030: import org.antlr.analysis.DFA;
0031: import org.antlr.analysis.DecisionProbe;
0032: import org.antlr.misc.BitSet;
0033: import org.antlr.tool.*;
0034: import org.antlr.Tool;
0035: import org.antlr.codegen.CodeGenerator;
0036:
0037: import java.util.*;
0038:
0039: public class TestDFAConversion extends BaseTest {
0040:
0041: public void testA() throws Exception {
0042: Grammar g = new Grammar("parser grammar t;\n" + "a : A C | B;");
0043: String expecting = ".s0-A->:s1=>1\n" + ".s0-B->:s2=>2\n";
0044: checkDecision(g, 1, expecting, null, null, null, null, 0);
0045: }
0046:
0047: public void testAB_or_AC() throws Exception {
0048: Grammar g = new Grammar("parser grammar t;\n"
0049: + "a : A B | A C;");
0050: String expecting = ".s0-A->.s1\n" + ".s1-B->:s3=>1\n"
0051: + ".s1-C->:s2=>2\n";
0052: checkDecision(g, 1, expecting, null, null, null, null, 0);
0053: }
0054:
0055: public void testAB_or_AC_k2() throws Exception {
0056: Grammar g = new Grammar("parser grammar t;\n"
0057: + "options {k=2;}\n" + "a : A B | A C;");
0058: String expecting = ".s0-A->.s1\n" + ".s1-B->:s3=>1\n"
0059: + ".s1-C->:s2=>2\n";
0060: checkDecision(g, 1, expecting, null, null, null, null, 0);
0061: }
0062:
0063: public void testAB_or_AC_k1() throws Exception {
0064: Grammar g = new Grammar("parser grammar t;\n"
0065: + "options {k=1;}\n" + "a : A B | A C;");
0066: String expecting = ".s0-A->:s1=>1\n";
0067: int[] unreachableAlts = new int[] { 2 };
0068: int[] nonDetAlts = new int[] { 1, 2 };
0069: String ambigInput = "A";
0070: int[] danglingAlts = new int[] { 2 };
0071: int numWarnings = 2; // non-LL(1) abort and ambig upon A
0072: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0073: ambigInput, danglingAlts, numWarnings);
0074: }
0075:
0076: public void testselfRecurseNonDet() throws Exception {
0077: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0078: + "a : A a X | A a Y;");
0079: // nondeterministic from left edge; no stop state
0080: String expecting = ".s0-A->.s1\n" + ".s1-A->:s2=>1\n"; // gets this after failing to do LL(*)
0081: int[] unreachableAlts = new int[] { 1, 2 };
0082: int[] nonDetAlts = new int[] { 1, 2 };
0083: String ambigInput = null;
0084: int[] danglingAlts = new int[] { 1, 2 };
0085: int numWarnings = 2; // non-LL(*) abort and ambig upon A A
0086: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0087: ambigInput, danglingAlts, numWarnings);
0088: }
0089:
0090: public void testCannotSeePastRecursion() throws Exception {
0091: Grammar g = new Grammar("parser grammar t;\n" + "x : y X\n"
0092: + " | y Y\n" + " ;\n" + "y : L y R\n"
0093: + " | B\n" + " ;");
0094: String expecting = ".s0-B->.s4\n" + ".s0-L->.s1\n"
0095: + ".s1-B->.s3\n" + ".s1-L->:s2=>1\n";
0096: int[] unreachableAlts = new int[] { 1, 2 };
0097: int[] nonDetAlts = new int[] { 1, 2 };
0098: String ambigInput = null;
0099: int[] danglingAlts = null;
0100: int numWarnings = 2;
0101: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0102: ambigInput, danglingAlts, numWarnings);
0103: }
0104:
0105: public void testSynPredResolvesRecursion() throws Exception {
0106: Grammar g = new Grammar("parser grammar t;\n"
0107: + "x : (y X)=> y X\n" + " | y Y\n" + " ;\n"
0108: + "y : L y R\n" + " | B\n" + " ;");
0109: String expecting = ".s0-B->.s7\n" + ".s0-L->.s1\n"
0110: + ".s1-B->.s5\n" + ".s1-L->.s2\n"
0111: + ".s2-{synpred1}?->:s3=>1\n" + ".s2-{true}?->:s4=>2\n"
0112: + ".s5-R->.s6\n" + ".s6-X&&{synpred1}?->:s3=>1\n"
0113: + ".s6-Y->:s4=>2\n" + ".s7-X&&{synpred1}?->:s3=>1\n"
0114: + ".s7-Y->:s4=>2\n";
0115: int[] unreachableAlts = null;
0116: int[] nonDetAlts = null;
0117: String ambigInput = null;
0118: int[] danglingAlts = null;
0119: int numWarnings = 0;
0120: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0121: ambigInput, danglingAlts, numWarnings);
0122: }
0123:
0124: public void testSynPredResolvesRecursionInLexer() throws Exception {
0125: Grammar g = new Grammar("lexer grammar t;\n"
0126: + "A : (B ';')=> B ';'\n" + " | B '.'\n"
0127: + " ;\n" + "fragment\n" + "B : '(' B ')'\n"
0128: + " | 'x'\n" + " ;\n");
0129: String expecting = ".s0-'('->.s1\n" + ".s0-'x'->.s7\n"
0130: + ".s1-'('->.s2\n" + ".s1-'x'->.s5\n"
0131: + ".s2-{synpred1}?->:s3=>1\n" + ".s2-{true}?->:s4=>2\n"
0132: + ".s5-')'->.s6\n" + ".s6-'.'->:s4=>2\n"
0133: + ".s6-';'&&{synpred1}?->:s3=>1\n"
0134: + ".s7-'.'->:s4=>2\n"
0135: + ".s7-';'&&{synpred1}?->:s3=>1\n";
0136: int[] unreachableAlts = null;
0137: int[] nonDetAlts = null;
0138: String ambigInput = null;
0139: int[] danglingAlts = null;
0140: int numWarnings = 0;
0141: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0142: ambigInput, danglingAlts, numWarnings);
0143: }
0144:
0145: public void testAutoBacktrackResolvesRecursionInLexer()
0146: throws Exception {
0147: Grammar g = new Grammar("lexer grammar t;\n"
0148: + "options {backtrack=true;}\n" + "A : B ';'\n"
0149: + " | B '.'\n" + " ;\n" + "fragment\n"
0150: + "B : '(' B ')'\n" + " | 'x'\n" + " ;\n");
0151: String expecting = ".s0-'('->.s1\n" + ".s0-'x'->.s7\n"
0152: + ".s1-'('->.s2\n" + ".s1-'x'->.s5\n"
0153: + ".s2-{synpred1}?->:s3=>1\n" + ".s2-{true}?->:s4=>2\n"
0154: + ".s5-')'->.s6\n" + ".s6-'.'->:s4=>2\n"
0155: + ".s6-';'->:s3=>1\n" + ".s7-'.'->:s4=>2\n"
0156: + ".s7-';'->:s3=>1\n";
0157: int[] unreachableAlts = null;
0158: int[] nonDetAlts = null;
0159: String ambigInput = null;
0160: int[] danglingAlts = null;
0161: int numWarnings = 0;
0162: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0163: ambigInput, danglingAlts, numWarnings);
0164: }
0165:
0166: public void testAutoBacktrackResolvesRecursion() throws Exception {
0167: Grammar g = new Grammar("parser grammar t;\n"
0168: + "options {backtrack=true;}\n" + "x : y X\n"
0169: + " | y Y\n" + " ;\n" + "y : L y R\n"
0170: + " | B\n" + " ;");
0171: String expecting = ".s0-B->.s7\n" + ".s0-L->.s1\n"
0172: + ".s1-B->.s5\n" + ".s1-L->.s2\n"
0173: + ".s2-{synpred1}?->:s3=>1\n" + ".s2-{true}?->:s4=>2\n"
0174: + ".s5-R->.s6\n" + ".s6-X->:s3=>1\n"
0175: + ".s6-Y->:s4=>2\n" + ".s7-X->:s3=>1\n"
0176: + ".s7-Y->:s4=>2\n";
0177: int[] unreachableAlts = null;
0178: int[] nonDetAlts = null;
0179: String ambigInput = null;
0180: int[] danglingAlts = null;
0181: int numWarnings = 0;
0182: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0183: ambigInput, danglingAlts, numWarnings);
0184: }
0185:
0186: public void testselfRecurseNonDet2() throws Exception {
0187: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0188: + "a : P a P | P;");
0189: // nondeterministic from left edge
0190: String expecting = ".s0-P->.s1\n" + ".s1-EOF->:s2=>2\n"
0191: + ".s1-P->:s3=>1\n";
0192: int[] unreachableAlts = null;
0193: int[] nonDetAlts = new int[] { 1, 2 };
0194: String ambigInput = "P P";
0195: int[] danglingAlts = null;
0196: int numWarnings = 1;
0197: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0198: ambigInput, danglingAlts, numWarnings);
0199: }
0200:
0201: public void testIndirectRecursionLoop() throws Exception {
0202: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0203: + "a : b X ;\n" + "b : a B ;\n");
0204:
0205: DecisionProbe.verbose = true; // make sure we get all error info
0206: ErrorQueue equeue = new ErrorQueue();
0207: ErrorManager.setErrorListener(equeue);
0208:
0209: Set leftRecursive = g.getLeftRecursiveRules();
0210: Set expectedRules = new HashSet() {
0211: {
0212: add("a");
0213: add("b");
0214: }
0215: };
0216: assertEquals(expectedRules, leftRecursive);
0217:
0218: g.createLookaheadDFAs();
0219:
0220: Message msg = (Message) equeue.warnings.get(0);
0221: assertTrue("expecting left recursion cycles; found "
0222: + msg.getClass().getName(),
0223: msg instanceof LeftRecursionCyclesMessage);
0224: LeftRecursionCyclesMessage cyclesMsg = (LeftRecursionCyclesMessage) msg;
0225:
0226: // cycle of [a, b]
0227: Collection result = cyclesMsg.cycles;
0228: List expecting = new ArrayList();
0229: expecting.add(new HashSet() {
0230: {
0231: add("a");
0232: add("b");
0233: }
0234: });
0235: assertEquals(expecting, result);
0236: }
0237:
0238: public void testIndirectRecursionLoop2() throws Exception {
0239: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0240: + "a : i b X ;\n" + // should see through i
0241: "b : a B ;\n" + "i : ;\n");
0242:
0243: DecisionProbe.verbose = true; // make sure we get all error info
0244: ErrorQueue equeue = new ErrorQueue();
0245: ErrorManager.setErrorListener(equeue);
0246:
0247: Set leftRecursive = g.getLeftRecursiveRules();
0248: Set expectedRules = new HashSet() {
0249: {
0250: add("a");
0251: add("b");
0252: }
0253: };
0254: assertEquals(expectedRules, leftRecursive);
0255:
0256: g.createLookaheadDFAs();
0257:
0258: Message msg = (Message) equeue.warnings.get(0);
0259: assertTrue("expecting left recursion cycles; found "
0260: + msg.getClass().getName(),
0261: msg instanceof LeftRecursionCyclesMessage);
0262: LeftRecursionCyclesMessage cyclesMsg = (LeftRecursionCyclesMessage) msg;
0263:
0264: // cycle of [a, b]
0265: Collection result = cyclesMsg.cycles;
0266: List expecting = new ArrayList();
0267: expecting.add(new HashSet() {
0268: {
0269: add("a");
0270: add("b");
0271: }
0272: });
0273: assertEquals(expecting, result);
0274: }
0275:
0276: public void testIndirectRecursionLoop3() throws Exception {
0277: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0278: + "a : i b X ;\n" + // should see through i
0279: "b : a B ;\n" + "i : ;\n" + "d : e ;\n" + "e : d ;\n");
0280:
0281: DecisionProbe.verbose = true; // make sure we get all error info
0282: ErrorQueue equeue = new ErrorQueue();
0283: ErrorManager.setErrorListener(equeue);
0284:
0285: Set leftRecursive = g.getLeftRecursiveRules();
0286: Set expectedRules = new HashSet() {
0287: {
0288: add("a");
0289: add("b");
0290: add("e");
0291: add("d");
0292: }
0293: };
0294: assertEquals(expectedRules, leftRecursive);
0295:
0296: Message msg = (Message) equeue.warnings.get(0);
0297: assertTrue("expecting left recursion cycles; found "
0298: + msg.getClass().getName(),
0299: msg instanceof LeftRecursionCyclesMessage);
0300: LeftRecursionCyclesMessage cyclesMsg = (LeftRecursionCyclesMessage) msg;
0301:
0302: // cycle of [a, b]
0303: Collection result = cyclesMsg.cycles;
0304: List expecting = new ArrayList();
0305: expecting.add(new HashSet() {
0306: {
0307: add("a");
0308: add("b");
0309: }
0310: });
0311: expecting.add(new HashSet() {
0312: {
0313: add("d");
0314: add("e");
0315: }
0316: });
0317: assertEquals(expecting, result);
0318: }
0319:
0320: public void testifThenElse() throws Exception {
0321: Grammar g = new Grammar("parser grammar t;\n"
0322: + "s : IF s (E s)? | B;\n" + "slist: s SEMI ;");
0323: String expecting = ".s0-E->:s1=>1\n" + ".s0-SEMI->:s2=>2\n";
0324: int[] unreachableAlts = null;
0325: int[] nonDetAlts = new int[] { 1, 2 };
0326: String ambigInput = "E";
0327: int[] danglingAlts = null;
0328: int numWarnings = 1;
0329: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0330: ambigInput, danglingAlts, numWarnings);
0331: expecting = ".s0-B->:s2=>2\n" + ".s0-IF->:s1=>1\n";
0332: checkDecision(g, 2, expecting, null, null, null, null, 0);
0333: }
0334:
0335: public void testifThenElseChecksStackSuffixConflict()
0336: throws Exception {
0337: // if you don't check stack soon enough, this finds E B not just E
0338: // as ambig input
0339: Grammar g = new Grammar("parser grammar t;\n"
0340: + "slist: s SEMI ;\n" + "s : IF s el | B;\n"
0341: + "el: (E s)? ;\n");
0342: String expecting = ".s0-E->:s1=>1\n" + ".s0-SEMI->:s2=>2\n";
0343: int[] unreachableAlts = null;
0344: int[] nonDetAlts = new int[] { 1, 2 };
0345: String ambigInput = "E";
0346: int[] danglingAlts = null;
0347: int numWarnings = 1;
0348: checkDecision(g, 2, expecting, unreachableAlts, nonDetAlts,
0349: ambigInput, danglingAlts, numWarnings);
0350: expecting = ".s0-B->:s2=>2\n" + ".s0-IF->:s1=>1\n";
0351: checkDecision(g, 1, expecting, null, null, null, null, 0);
0352: }
0353:
0354: public void testInvokeRule() throws Exception {
0355: Grammar g = new Grammar("parser grammar t;\n" + "a : b A\n"
0356: + " | b B\n" + " | C\n" + " ;\n" + "b : X\n"
0357: + " ;\n");
0358: String expecting = ".s0-C->:s4=>3\n" + ".s0-X->.s1\n"
0359: + ".s1-A->:s3=>1\n" + ".s1-B->:s2=>2\n";
0360: checkDecision(g, 1, expecting, null, null, null, null, 0);
0361: }
0362:
0363: public void testDoubleInvokeRuleLeftEdge() throws Exception {
0364: Grammar g = new Grammar("parser grammar t;\n" + "a : b X\n"
0365: + " | b Y\n" + " ;\n" + "b : c B\n" + " | c\n"
0366: + " ;\n" + "c : C ;\n");
0367: String expecting = ".s0-C->.s1\n" + ".s1-B->.s4\n"
0368: + ".s1-X->:s2=>1\n" + ".s1-Y->:s3=>2\n"
0369: + ".s4-X->:s2=>1\n" + ".s4-Y->:s3=>2\n";
0370: checkDecision(g, 1, expecting, null, null, null, null, 0);
0371: expecting = ".s0-C->.s1\n" + ".s1-B->:s3=>1\n"
0372: + ".s1-X..Y->:s2=>2\n";
0373: checkDecision(g, 2, expecting, null, null, null, null, 0);
0374: }
0375:
0376: public void testimmediateTailRecursion() throws Exception {
0377: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0378: + "a : A a | A B;");
0379: String expecting = ".s0-A->.s1\n" + ".s1-A->:s3=>1\n"
0380: + ".s1-B->:s2=>2\n";
0381: checkDecision(g, 1, expecting, null, null, null, null, 0);
0382: }
0383:
0384: public void testAStar_immediateTailRecursion() throws Exception {
0385: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0386: + "a : A a | ;");
0387: String expecting = ".s0-A->:s1=>1\n" + ".s0-EOF->:s2=>2\n";
0388: int[] unreachableAlts = null; // without
0389: int[] nonDetAlts = null;
0390: String ambigInput = null;
0391: int[] danglingAlts = null;
0392: int numWarnings = 0;
0393: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0394: ambigInput, danglingAlts, numWarnings);
0395: }
0396:
0397: public void testNoStartRule() throws Exception {
0398: ErrorQueue equeue = new ErrorQueue();
0399: ErrorManager.setErrorListener(equeue);
0400: Grammar g = new Grammar("parser grammar t;\n" + "a : A a | X;"); // single rule 'a' refers to itself; no start rule
0401:
0402: Tool antlr = newTool();
0403: antlr.setOutputDirectory(null); // write to /dev/null
0404: CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
0405: g.setCodeGenerator(generator);
0406: generator.genRecognizer();
0407:
0408: Message msg = (Message) equeue.warnings.get(0);
0409: assertTrue("expecting no start rules; found "
0410: + msg.getClass().getName(),
0411: msg instanceof GrammarSemanticsMessage);
0412: }
0413:
0414: public void testAStar_immediateTailRecursion2() throws Exception {
0415: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0416: + "a : A a | A ;");
0417: String expecting = ".s0-A->.s1\n" + ".s1-A->:s3=>1\n"
0418: + ".s1-EOF->:s2=>2\n";
0419: int[] unreachableAlts = null;
0420: int[] nonDetAlts = null;
0421: String ambigInput = null;
0422: int[] danglingAlts = null;
0423: int numWarnings = 0;
0424: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0425: ambigInput, danglingAlts, numWarnings);
0426: }
0427:
0428: public void testimmediateLeftRecursion() throws Exception {
0429: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0430: + "a : a A | B;");
0431: Set leftRecursive = g.getLeftRecursiveRules();
0432: Set expectedRules = new HashSet() {
0433: {
0434: add("a");
0435: }
0436: };
0437: assertEquals(expectedRules, leftRecursive);
0438: }
0439:
0440: public void testIndirectLeftRecursion() throws Exception {
0441: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0442: + "a : b | A ;\n" + "b : c ;\n" + "c : a | C ;\n");
0443: Set leftRecursive = g.getLeftRecursiveRules();
0444: Set expectedRules = new HashSet() {
0445: {
0446: add("a");
0447: add("b");
0448: add("c");
0449: }
0450: };
0451: assertEquals(expectedRules, leftRecursive);
0452: }
0453:
0454: public void testLeftRecursionInMultipleCycles() throws Exception {
0455: Grammar g = new Grammar("parser grammar t;\n" + "s : a x ;\n"
0456: + "a : b | A ;\n" + "b : c ;\n" + "c : a | C ;\n"
0457: + "x : y | X ;\n" + "y : x ;\n");
0458: Set leftRecursive = g.getLeftRecursiveRules();
0459: Set expectedRules = new HashSet() {
0460: {
0461: add("a");
0462: add("b");
0463: add("c");
0464: add("x");
0465: add("y");
0466: }
0467: };
0468: assertEquals(expectedRules, leftRecursive);
0469: }
0470:
0471: public void testCycleInsideRuleDoesNotForceInfiniteRecursion()
0472: throws Exception {
0473: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0474: + "a : (A|)+ B;\n");
0475: // before I added a visitedStates thing, it was possible to loop
0476: // forever inside of a rule if there was an epsilon loop.
0477: Set leftRecursive = g.getLeftRecursiveRules();
0478: Set expectedRules = new HashSet();
0479: assertEquals(expectedRules, leftRecursive);
0480: }
0481:
0482: // L O O P S
0483:
0484: public void testAStar() throws Exception {
0485: Grammar g = new Grammar("parser grammar t;\n" + "a : ( A )* ;");
0486: String expecting = ".s0-A->:s2=>1\n" + ".s0-EOF->:s1=>2\n";
0487: checkDecision(g, 1, expecting, null, null, null, null, 0);
0488: }
0489:
0490: public void testAorBorCStar() throws Exception {
0491: Grammar g = new Grammar("parser grammar t;\n"
0492: + "a : ( A | B | C )* ;");
0493: String expecting = ".s0-A..C->:s2=>1\n" + ".s0-EOF->:s1=>2\n";
0494: checkDecision(g, 1, expecting, null, null, null, null, 0);
0495: }
0496:
0497: public void testAPlus() throws Exception {
0498: Grammar g = new Grammar("parser grammar t;\n" + "a : ( A )+ ;");
0499: String expecting = ".s0-A->:s2=>1\n" + ".s0-EOF->:s1=>2\n";
0500: checkDecision(g, 1, expecting, null, null, null, null, 0); // loopback decision
0501: }
0502:
0503: public void testAPlusNonGreedyWhenDeterministic() throws Exception {
0504: Grammar g = new Grammar("parser grammar t;\n"
0505: + "a : (options {greedy=false;}:A)+ ;\n");
0506: // should look the same as A+ since no ambiguity
0507: String expecting = ".s0-A->:s2=>1\n" + ".s0-EOF->:s1=>2\n";
0508: checkDecision(g, 1, expecting, null, null, null, null, 0);
0509: }
0510:
0511: public void testAorBorCPlus() throws Exception {
0512: Grammar g = new Grammar("parser grammar t;\n"
0513: + "a : ( A | B | C )+ ;");
0514: String expecting = ".s0-A..C->:s2=>1\n" + ".s0-EOF->:s1=>2\n";
0515: checkDecision(g, 1, expecting, null, null, null, null, 0);
0516: }
0517:
0518: public void testAOptional() throws Exception {
0519: Grammar g = new Grammar("parser grammar t;\n"
0520: + "a : ( A )? B ;");
0521: String expecting = ".s0-A->:s1=>1\n" + ".s0-B->:s2=>2\n";
0522: checkDecision(g, 1, expecting, null, null, null, null, 0); // loopback decision
0523: }
0524:
0525: public void testAorBorCOptional() throws Exception {
0526: Grammar g = new Grammar("parser grammar t;\n"
0527: + "a : ( A | B | C )? Z ;");
0528: String expecting = ".s0-A..C->:s1=>1\n" + ".s0-Z->:s2=>2\n";
0529: checkDecision(g, 1, expecting, null, null, null, null, 0); // loopback decision
0530: }
0531:
0532: // A R B I T R A R Y L O O K A H E A D
0533:
0534: public void testAStarBOrAStarC() throws Exception {
0535: Grammar g = new Grammar("parser grammar t;\n"
0536: + "a : (A)* B | (A)* C;");
0537: String expecting = ".s0-A->:s2=>1\n" + ".s0-B->:s1=>2\n";
0538: checkDecision(g, 1, expecting, null, null, null, null, 0); // loopback
0539: expecting = ".s0-A->:s2=>1\n" + ".s0-C->:s1=>2\n";
0540: checkDecision(g, 2, expecting, null, null, null, null, 0); // loopback
0541: expecting = ".s0-A->.s1\n" + ".s0-B->:s2=>1\n"
0542: + ".s0-C->:s3=>2\n" + ".s1-A->.s1\n"
0543: + ".s1-B->:s2=>1\n" + ".s1-C->:s3=>2\n";
0544: checkDecision(g, 3, expecting, null, null, null, null, 0); // rule block
0545: }
0546:
0547: public void testAStarBOrAPlusC() throws Exception {
0548: Grammar g = new Grammar("parser grammar t;\n"
0549: + "a : (A)* B | (A)+ C;");
0550: String expecting = ".s0-A->:s2=>1\n" + ".s0-B->:s1=>2\n";
0551: checkDecision(g, 1, expecting, null, null, null, null, 0); // loopback
0552: expecting = ".s0-A->:s2=>1\n" + ".s0-C->:s1=>2\n";
0553: checkDecision(g, 2, expecting, null, null, null, null, 0); // loopback
0554: expecting = ".s0-A->.s1\n" + ".s0-B->:s2=>1\n" + ".s1-A->.s1\n"
0555: + ".s1-B->:s2=>1\n" + ".s1-C->:s3=>2\n";
0556: checkDecision(g, 3, expecting, null, null, null, null, 0); // rule block
0557: }
0558:
0559: public void testAOrBPlusOrAPlus() throws Exception {
0560: Grammar g = new Grammar("parser grammar t;\n"
0561: + "a : (A|B)* X | (A)+ Y;");
0562: String expecting = ".s0-A..B->:s2=>1\n" + ".s0-X->:s1=>2\n";
0563: checkDecision(g, 1, expecting, null, null, null, null, 0); // loopback (A|B)*
0564: expecting = ".s0-A->:s2=>1\n" + ".s0-Y->:s1=>2\n";
0565: checkDecision(g, 2, expecting, null, null, null, null, 0); // loopback (A)+
0566: expecting = ".s0-A->.s1\n" + ".s0-B..X->:s2=>1\n"
0567: + ".s1-A->.s1\n" + ".s1-B..X->:s2=>1\n"
0568: + ".s1-Y->:s3=>2\n";
0569: checkDecision(g, 3, expecting, null, null, null, null, 0); // rule
0570: }
0571:
0572: public void testLoopbackAndExit() throws Exception {
0573: Grammar g = new Grammar("parser grammar t;\n" + "a : (A|B)+ B;");
0574: String expecting = ".s0-A->:s2=>1\n" + ".s0-B->.s1\n"
0575: + ".s1-A..B->:s2=>1\n" + ".s1-EOF->:s3=>2\n"; // sees A|B as a set
0576: checkDecision(g, 1, expecting, null, null, null, null, 0);
0577: }
0578:
0579: public void testOptionalAltAndBypass() throws Exception {
0580: Grammar g = new Grammar("parser grammar t;\n" + "a : (A|B)? B;");
0581: String expecting = ".s0-A->:s2=>1\n" + ".s0-B->.s1\n"
0582: + ".s1-B->:s2=>1\n" + ".s1-EOF->:s3=>2\n";
0583: checkDecision(g, 1, expecting, null, null, null, null, 0);
0584: }
0585:
0586: // R E S O L V E S Y N C O N F L I C T S
0587:
0588: public void testResolveLL1ByChoosingFirst() throws Exception {
0589: Grammar g = new Grammar("parser grammar t;\n"
0590: + "a : A C | A C;");
0591: String expecting = ".s0-A->.s1\n" + ".s1-C->:s2=>1\n";
0592: int[] unreachableAlts = new int[] { 2 };
0593: int[] nonDetAlts = new int[] { 1, 2 };
0594: String ambigInput = "A C";
0595: int[] danglingAlts = null;
0596: int numWarnings = 2;
0597: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0598: ambigInput, danglingAlts, numWarnings);
0599: }
0600:
0601: public void testResolveLL2ByChoosingFirst() throws Exception {
0602: Grammar g = new Grammar("parser grammar t;\n"
0603: + "a : A B | A B;");
0604: String expecting = ".s0-A->.s1\n" + ".s1-B->:s2=>1\n";
0605: int[] unreachableAlts = new int[] { 2 };
0606: int[] nonDetAlts = new int[] { 1, 2 };
0607: String ambigInput = "A B";
0608: int[] danglingAlts = null;
0609: int numWarnings = 2;
0610: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0611: ambigInput, danglingAlts, numWarnings);
0612: }
0613:
0614: public void testResolveLL2MixAlt() throws Exception {
0615: Grammar g = new Grammar("parser grammar t;\n"
0616: + "a : A B | A C | A B | Z;");
0617: String expecting = ".s0-A->.s1\n" + ".s0-Z->:s4=>4\n"
0618: + ".s1-B->:s2=>1\n" + ".s1-C->:s3=>2\n";
0619: int[] unreachableAlts = new int[] { 3 };
0620: int[] nonDetAlts = new int[] { 1, 3 };
0621: String ambigInput = "A B";
0622: int[] danglingAlts = null;
0623: int numWarnings = 2;
0624: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0625: ambigInput, danglingAlts, numWarnings);
0626: }
0627:
0628: public void testIndirectIFThenElseStyleAmbig() throws Exception {
0629: // the (c)+ loopback is ambig because it could match "CASE"
0630: // by entering the loop or by falling out and ignoring (s)*
0631: // back falling back into (cg)* loop which stats over and
0632: // calls cg again. Either choice allows it to get back to
0633: // the same node. The software catches it as:
0634: // "avoid infinite closure computation emanating from alt 1
0635: // of ():27|2|[8 $]" where state 27 is the first alt of (c)+
0636: // and 8 is the first alt of the (cg)* loop.
0637: Grammar g = new Grammar("parser grammar t;\n" + "s : stat ;\n"
0638: + "stat : LCURLY ( cg )* RCURLY | E SEMI ;\n"
0639: + "cg : (c)+ (stat)* ;\n" + "c : CASE E ;\n");
0640: String expecting = ".s0-CASE->:s2=>1\n"
0641: + ".s0-LCURLY..E->:s1=>2\n";
0642: int[] unreachableAlts = null;
0643: int[] nonDetAlts = new int[] { 1, 2 };
0644: String ambigInput = "CASE";
0645: int[] danglingAlts = null;
0646: int numWarnings = 1;
0647: checkDecision(g, 3, expecting, unreachableAlts, nonDetAlts,
0648: ambigInput, danglingAlts, numWarnings);
0649: }
0650:
0651: // S E T S
0652:
0653: public void testComplement() throws Exception {
0654: Grammar g = new Grammar("parser grammar t;\n"
0655: + "a : ~(A | B | C) | C {;} ;\n" + "b : X Y Z ;");
0656: String expecting = ".s0-C->:s2=>2\n" + ".s0-X..Z->:s1=>1\n";
0657: checkDecision(g, 1, expecting, null, null, null, null, 0);
0658: }
0659:
0660: public void testComplementToken() throws Exception {
0661: Grammar g = new Grammar("parser grammar t;\n"
0662: + "a : ~C | C {;} ;\n" + "b : X Y Z ;");
0663: String expecting = ".s0-C->:s2=>2\n" + ".s0-X..Z->:s1=>1\n";
0664: checkDecision(g, 1, expecting, null, null, null, null, 0);
0665: }
0666:
0667: public void testComplementChar() throws Exception {
0668: Grammar g = new Grammar("lexer grammar t;\n"
0669: + "A : ~'x' | 'x' {;} ;\n");
0670: String expecting = ".s0-'x'->:s2=>2\n"
0671: + ".s0-{'\\u0000'..'w', 'y'..'\\uFFFE'}->:s1=>1\n";
0672: checkDecision(g, 1, expecting, null, null, null, null, 0);
0673: }
0674:
0675: public void testComplementCharSet() throws Exception {
0676: Grammar g = new Grammar("lexer grammar t;\n"
0677: + "A : ~(' '|'\t'|'x'|'y') | 'x';\n" + // collapse into single set
0678: "B : 'y' ;");
0679: String expecting = ".s0-'y'->:s2=>2\n"
0680: + ".s0-{'\\u0000'..'\\b', '\\n'..'\\u001F', '!'..'x', 'z'..'\\uFFFE'}->:s1=>1\n";
0681: checkDecision(g, 1, expecting, null, null, null, null, 0);
0682: }
0683:
0684: public void testNoSetCollapseWithActions() throws Exception {
0685: Grammar g = new Grammar("parser grammar t;\n"
0686: + "a : (A | B {foo}) | C;");
0687: String expecting = ".s0-A->:s1=>1\n" + ".s0-B->:s2=>2\n";
0688: checkDecision(g, 1, expecting, null, null, null, null, 0);
0689: }
0690:
0691: public void testRuleAltsSetCollapse() throws Exception {
0692: Grammar g = new Grammar("parser grammar t;\n"
0693: + "a : A | B | C ;");
0694: String expecting = // still looks like block
0695: " ( grammar t ( rule a ARG RET scope ( BLOCK ( ALT A <end-of-alt> ) ( ALT B <end-of-alt> ) ( ALT C <end-of-alt> ) <end-of-block> ) <end-of-rule> ) )";
0696: assertEquals(expecting, g.getGrammarTree().toStringTree());
0697: }
0698:
0699: public void testTokensRuleAltsDoNotCollapse() throws Exception {
0700: Grammar g = new Grammar("lexer grammar t;\n" + "A : 'a';"
0701: + "B : 'b';\n");
0702: String expecting = ".s0-'a'->:s1=>1\n" + ".s0-'b'->:s2=>2\n";
0703: checkDecision(g, 1, expecting, null, null, null, null, 0);
0704: }
0705:
0706: public void testMultipleSequenceCollision() throws Exception {
0707: Grammar g = new Grammar("parser grammar t;\n"
0708: + "a : (A{;}|B)\n" + " | (A{;}|B)\n" + " | A\n"
0709: + " ;");
0710: String expecting = ".s0-A->:s1=>1\n" + ".s0-B->:s2=>1\n"; // not optimized because states are nondet
0711: int[] unreachableAlts = new int[] { 2, 3 };
0712: int[] nonDetAlts = new int[] { 1, 2, 3 };
0713: String ambigInput = "A";
0714: int[] danglingAlts = null;
0715: int numWarnings = 3;
0716: checkDecision(g, 3, expecting, unreachableAlts, nonDetAlts,
0717: ambigInput, danglingAlts, numWarnings);
0718: /* There are 2 nondet errors, but the checkDecision only checks first one :(
0719: The "B" conflicting input is not checked except by virtue of the
0720: result DFA.
0721: <string>:2:5: Decision can match input such as "A" using multiple alternatives:
0722: alt 1 via NFA path 7,2,3
0723: alt 2 via NFA path 14,9,10
0724: alt 3 via NFA path 16,17
0725: As a result, alternative(s) 2,3 were disabled for that input,
0726: <string>:2:5: Decision can match input such as "B" using multiple alternatives:
0727: alt 1 via NFA path 7,8,4,5
0728: alt 2 via NFA path 14,15,11,12
0729: As a result, alternative(s) 2 were disabled for that input
0730: <string>:2:5: The following alternatives are unreachable: 2,3
0731: */
0732: }
0733:
0734: public void testMultipleAltsSameSequenceCollision()
0735: throws Exception {
0736: Grammar g = new Grammar("parser grammar t;\n"
0737: + "a : type ID \n" + " | type ID\n" + " | type ID\n"
0738: + " | type ID\n" + " ;\n" + "\n" + "type : I | F;");
0739: // nondeterministic from left edge; no stop state
0740: String expecting = ".s0-I..F->.s1\n" + ".s1-ID->:s2=>1\n";
0741: int[] unreachableAlts = new int[] { 2, 3, 4 };
0742: int[] nonDetAlts = new int[] { 1, 2, 3, 4 };
0743: String ambigInput = "I..F ID";
0744: int[] danglingAlts = null;
0745: int numWarnings = 2;
0746: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0747: ambigInput, danglingAlts, numWarnings);
0748: }
0749:
0750: public void testFollowReturnsToLoopReenteringSameRule()
0751: throws Exception {
0752: // D07 can be matched in the (...)? or fall out of esc back into (..)*
0753: // loop in sl. Note that D07 is matched by ~(R|SLASH). No good
0754: // way to write that grammar I guess
0755: Grammar g = new Grammar("parser grammar t;\n"
0756: + "sl : L ( esc | ~(R|SLASH) )* R ;\n" + "\n"
0757: + "esc : SLASH ( N | D03 (D07)? ) ;");
0758: String expecting = ".s0-R->:s1=>3\n" + ".s0-SLASH->:s2=>1\n"
0759: + ".s0-{L, N..D07}->:s3=>2\n";
0760: int[] unreachableAlts = null;
0761: int[] nonDetAlts = new int[] { 1, 2 };
0762: String ambigInput = "D07";
0763: int[] danglingAlts = null;
0764: int numWarnings = 1;
0765: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0766: ambigInput, danglingAlts, numWarnings);
0767: }
0768:
0769: public void testTokenCallsAnotherOnLeftEdge() throws Exception {
0770: Grammar g = new Grammar("lexer grammar t;\n"
0771: + "F : I '.'\n" + " ;\n" + "I : '0'\n"
0772: + " ;\n");
0773: String expecting = ".s0-'0'->.s1\n" + ".s1-'.'->:s3=>1\n"
0774: + ".s1-<EOT>->:s2=>2\n";
0775: checkDecision(g, 1, expecting, null, null, null, null, 0);
0776: }
0777:
0778: public void testSelfRecursionAmbigAlts() throws Exception {
0779: // ambiguous grammar for "L ID R" (alts 1,2 of a)
0780: Grammar g = new Grammar("parser grammar t;\n" + "s : a;\n"
0781: + "a : L ID R\n" + " | L a R\n"
0782: + // disabled for L ID R
0783: " | b\n" + " ;\n" + "\n" + "b : ID\n"
0784: + " ;\n");
0785: String expecting = ".s0-ID->:s5=>3\n" + ".s0-L->.s1\n"
0786: + ".s1-ID->.s2\n" + ".s1-L->:s4=>2\n"
0787: + ".s2-R->:s3=>1\n";
0788: int[] unreachableAlts = null;
0789: int[] nonDetAlts = new int[] { 1, 2 };
0790: String ambigInput = "L ID R";
0791: int[] danglingAlts = null;
0792: int numWarnings = 1;
0793: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0794: ambigInput, danglingAlts, numWarnings);
0795: }
0796:
0797: public void testIndirectRecursionAmbigAlts() throws Exception {
0798: // ambiguous grammar for "L ID R" (alts 1,2 of a)
0799: // This was derived from the java grammar 12/4/2004 when it
0800: // was not handling a unaryExpression properly. I traced it
0801: // to incorrect closure-busy condition. It thought that the trace
0802: // of a->b->a->b again for "L ID" was an infinite loop, but actually
0803: // the repeat call to b only happens *after* an L has been matched.
0804: // I added a check to see what the initial stack looks like and it
0805: // seems to work now.
0806: Grammar g = new Grammar("parser grammar t;\n" + "s : a ;\n"
0807: + "a : L ID R\n" + " | b\n" + " ;\n" + "\n"
0808: + "b : ID\n" + " | L a R\n" + " ;");
0809: String expecting = ".s0-ID->:s4=>2\n" + ".s0-L->.s1\n"
0810: + ".s1-ID->.s2\n" + ".s1-L->:s4=>2\n"
0811: + ".s2-R->:s3=>1\n";
0812: int[] unreachableAlts = null;
0813: int[] nonDetAlts = new int[] { 1, 2 };
0814: String ambigInput = "L ID R";
0815: int[] danglingAlts = null;
0816: int numWarnings = 1;
0817: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0818: ambigInput, danglingAlts, numWarnings);
0819: }
0820:
0821: public void testTailRecursionInvokedFromArbitraryLookaheadDecision()
0822: throws Exception {
0823: Grammar g = new Grammar("parser grammar t;\n" + "a : b X\n"
0824: + " | b Y\n" + " ;\n" + "\n" + "b : A\n"
0825: + " | A b\n" + " ;\n");
0826: String expecting = ".s0-A->.s1\n" + ".s1-Y->:s3=>2\n"
0827: + ".s1-{X, A}->:s2=>1\n";
0828: int[] unreachableAlts = new int[] { 1, 2 };
0829: int[] nonDetAlts = new int[] { 1, 2 };
0830: String ambigInput = null;
0831: int[] danglingAlts = null;
0832: int numWarnings = 2;
0833: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0834: ambigInput, danglingAlts, numWarnings);
0835: }
0836:
0837: public void testWildcardStarK1AndNonGreedyByDefaultInParser()
0838: throws Exception {
0839: // no error because .* assumes it should finish when it sees R
0840: Grammar g = new Grammar("parser grammar t;\n"
0841: + "s : A block EOF ;\n" + "block : L .* R ;");
0842: String expecting = ".s0-A..L->:s2=>1\n" + ".s0-R->:s1=>2\n";
0843: int[] unreachableAlts = null;
0844: int[] nonDetAlts = null;
0845: String ambigInput = null;
0846: int[] danglingAlts = null;
0847: int numWarnings = 0;
0848: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0849: ambigInput, danglingAlts, numWarnings);
0850: }
0851:
0852: public void testWildcardPlusK1AndNonGreedyByDefaultInParser()
0853: throws Exception {
0854: Grammar g = new Grammar("parser grammar t;\n"
0855: + "s : A block EOF ;\n" + "block : L .+ R ;");
0856: String expecting = ".s0-A..L->:s2=>1\n" + ".s0-R->:s1=>2\n";
0857: int[] unreachableAlts = null;
0858: int[] nonDetAlts = null;
0859: String ambigInput = null;
0860: int[] danglingAlts = null;
0861: int numWarnings = 0;
0862: checkDecision(g, 1, expecting, unreachableAlts, nonDetAlts,
0863: ambigInput, danglingAlts, numWarnings);
0864: }
0865:
0866: // Check state table creation
0867:
0868: public void testCyclicTableCreation() throws Exception {
0869: Grammar g = new Grammar("parser grammar t;\n"
0870: + "a : A+ X | A+ Y ;");
0871: String expecting = ".s0-A->:s1=>1\n" + ".s0-B->:s2=>2\n";
0872: }
0873:
0874: // S U P P O R T
0875:
0876: public void _template() throws Exception {
0877: Grammar g = new Grammar("parser grammar t;\n" + "a : A | B;");
0878: String expecting = "\n";
0879: checkDecision(g, 1, expecting, null, null, null, null, 0);
0880: }
0881:
0882: protected void checkDecision(Grammar g, int decision,
0883: String expecting, int[] expectingUnreachableAlts,
0884: int[] expectingNonDetAlts, String expectingAmbigInput,
0885: int[] expectingDanglingAlts, int expectingNumWarnings)
0886: throws Exception {
0887: DecisionProbe.verbose = true; // make sure we get all error info
0888: ErrorQueue equeue = new ErrorQueue();
0889: ErrorManager.setErrorListener(equeue);
0890:
0891: // mimic actions of org.antlr.Tool first time for grammar g
0892: if (g.getNumberOfDecisions() == 0) {
0893: g.createNFAs();
0894: g.createLookaheadDFAs();
0895: }
0896: CodeGenerator generator = new CodeGenerator(newTool(), g,
0897: "Java");
0898: g.setCodeGenerator(generator);
0899:
0900: if (equeue.size() != expectingNumWarnings) {
0901: System.err.println("Warnings issued: " + equeue);
0902: }
0903:
0904: assertEquals("unexpected number of expected problems",
0905: expectingNumWarnings, equeue.size());
0906:
0907: DFA dfa = g.getLookaheadDFA(decision);
0908: assertNotNull("no DFA for decision " + decision, dfa);
0909: FASerializer serializer = new FASerializer(g);
0910: String result = serializer.serialize(dfa.startState);
0911:
0912: List unreachableAlts = dfa.getUnreachableAlts();
0913:
0914: // make sure unreachable alts are as expected
0915: if (expectingUnreachableAlts != null) {
0916: BitSet s = new BitSet();
0917: s.addAll(expectingUnreachableAlts);
0918: BitSet s2 = new BitSet();
0919: s2.addAll(unreachableAlts);
0920: assertEquals("unreachable alts mismatch", s, s2);
0921: } else {
0922: assertEquals("number of unreachable alts", 0,
0923: unreachableAlts.size());
0924: }
0925:
0926: // check conflicting input
0927: if (expectingAmbigInput != null) {
0928: // first, find nondet message
0929: Message msg = (Message) equeue.warnings.get(0);
0930: assertTrue("expecting nondeterminism; found "
0931: + msg.getClass().getName(),
0932: msg instanceof GrammarNonDeterminismMessage);
0933: GrammarNonDeterminismMessage nondetMsg = getNonDeterminismMessage(equeue.warnings);
0934: List labels = nondetMsg.probe
0935: .getSampleNonDeterministicInputSequence(nondetMsg.problemState);
0936: String input = nondetMsg.probe
0937: .getInputSequenceDisplay(labels);
0938: assertEquals(expectingAmbigInput, input);
0939: }
0940:
0941: // check nondet alts
0942: if (expectingNonDetAlts != null) {
0943: RecursionOverflowMessage recMsg = null;
0944: GrammarNonDeterminismMessage nondetMsg = getNonDeterminismMessage(equeue.warnings);
0945: List nonDetAlts = null;
0946: if (nondetMsg != null) {
0947: nonDetAlts = nondetMsg.probe
0948: .getNonDeterministicAltsForState(nondetMsg.problemState);
0949: } else {
0950: recMsg = getRecursionOverflowMessage(equeue.warnings);
0951: if (recMsg != null) {
0952: //nonDetAlts = new ArrayList(recMsg.alts);
0953: }
0954: }
0955: // compare nonDetAlts with expectingNonDetAlts
0956: BitSet s = new BitSet();
0957: s.addAll(expectingNonDetAlts);
0958: BitSet s2 = new BitSet();
0959: s2.addAll(nonDetAlts);
0960: assertEquals("nondet alts mismatch", s, s2);
0961: assertTrue("found no nondet alts; expecting: "
0962: + str(expectingNonDetAlts), nondetMsg != null
0963: || recMsg != null);
0964: } else {
0965: // not expecting any nondet alts, make sure there are none
0966: GrammarNonDeterminismMessage nondetMsg = getNonDeterminismMessage(equeue.warnings);
0967: assertNull("found nondet alts, but expecting none",
0968: nondetMsg);
0969: }
0970:
0971: assertEquals(expecting, result);
0972: }
0973:
0974: protected GrammarNonDeterminismMessage getNonDeterminismMessage(
0975: List warnings) {
0976: for (int i = 0; i < warnings.size(); i++) {
0977: Message m = (Message) warnings.get(i);
0978: if (m instanceof GrammarNonDeterminismMessage) {
0979: return (GrammarNonDeterminismMessage) m;
0980: }
0981: }
0982: return null;
0983: }
0984:
0985: protected RecursionOverflowMessage getRecursionOverflowMessage(
0986: List warnings) {
0987: for (int i = 0; i < warnings.size(); i++) {
0988: Message m = (Message) warnings.get(i);
0989: if (m instanceof RecursionOverflowMessage) {
0990: return (RecursionOverflowMessage) m;
0991: }
0992: }
0993: return null;
0994: }
0995:
0996: protected LeftRecursionCyclesMessage getLeftRecursionCyclesMessage(
0997: List warnings) {
0998: for (int i = 0; i < warnings.size(); i++) {
0999: Message m = (Message) warnings.get(i);
1000: if (m instanceof LeftRecursionCyclesMessage) {
1001: return (LeftRecursionCyclesMessage) m;
1002: }
1003: }
1004: return null;
1005: }
1006:
1007: protected GrammarDanglingStateMessage getDanglingStateMessage(
1008: List warnings) {
1009: for (int i = 0; i < warnings.size(); i++) {
1010: Message m = (Message) warnings.get(i);
1011: if (m instanceof GrammarDanglingStateMessage) {
1012: return (GrammarDanglingStateMessage) m;
1013: }
1014: }
1015: return null;
1016: }
1017:
1018: protected String str(int[] elements) {
1019: StringBuffer buf = new StringBuffer();
1020: for (int i = 0; i < elements.length; i++) {
1021: if (i > 0) {
1022: buf.append(", ");
1023: }
1024: int element = elements[i];
1025: buf.append(element);
1026: }
1027: return buf.toString();
1028: }
1029:
1030: }
|