1 /* 2 * [The "BSD license"] 3 * Copyright (c) 2010 Terence Parr 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 package org.antlr.test; 29 30 import org.junit.Test; 31 32 import static org.junit.Assert.*; 33 34 public class TestSemanticPredicateEvaluation extends BaseTest { testSimpleCyclicDFAWithPredicate()35 @Test public void testSimpleCyclicDFAWithPredicate() throws Exception { 36 String grammar = 37 "grammar foo;\n" + 38 "a : {false}? 'x'* 'y' {System.out.println(\"alt1\");}\n" + 39 " | {true}? 'x'* 'y' {System.out.println(\"alt2\");}\n" + 40 " ;\n" ; 41 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 42 "a", "xxxy", false); 43 assertEquals("alt2\n", found); 44 } 45 testSimpleCyclicDFAWithInstanceVarPredicate()46 @Test public void testSimpleCyclicDFAWithInstanceVarPredicate() throws Exception { 47 String grammar = 48 "grammar foo;\n" + 49 "@members {boolean v=true;}\n" + 50 "a : {false}? 'x'* 'y' {System.out.println(\"alt1\");}\n" + 51 " | {v}? 'x'* 'y' {System.out.println(\"alt2\");}\n" + 52 " ;\n" ; 53 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 54 "a", "xxxy", false); 55 assertEquals("alt2\n", found); 56 } 57 testPredicateValidation()58 @Test public void testPredicateValidation() throws Exception { 59 String grammar = 60 "grammar foo;\n" + 61 "@members {\n" + 62 "public void reportError(RecognitionException e) {\n" + 63 " System.out.println(\"error: \"+e.toString());\n" + 64 "}\n" + 65 "}\n" + 66 "\n" + 67 "a : {false}? 'x'\n" + 68 " ;\n" ; 69 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 70 "a", "x", false); 71 assertEquals("error: FailedPredicateException(a,{false}?)\n", found); 72 } 73 testLexerPreds()74 @Test public void testLexerPreds() throws Exception { 75 String grammar = 76 "grammar foo;" + 77 "@lexer::members {boolean p=false;}\n" + 78 "a : (A|B)+ ;\n" + 79 "A : {p}? 'a' {System.out.println(\"token 1\");} ;\n" + 80 "B : {!p}? 'a' {System.out.println(\"token 2\");} ;\n"; 81 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 82 "a", "a", false); 83 // "a" is ambig; can match both A, B. Pred says match 2 84 assertEquals("token 2\n", found); 85 } 86 testLexerPreds2()87 @Test public void testLexerPreds2() throws Exception { 88 String grammar = 89 "grammar foo;" + 90 "@lexer::members {boolean p=true;}\n" + 91 "a : (A|B)+ ;\n" + 92 "A : {p}? 'a' {System.out.println(\"token 1\");} ;\n" + 93 "B : ('a'|'b')+ {System.out.println(\"token 2\");} ;\n"; 94 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 95 "a", "a", false); 96 // "a" is ambig; can match both A, B. Pred says match 1 97 assertEquals("token 1\n", found); 98 } 99 testLexerPredInExitBranch()100 @Test public void testLexerPredInExitBranch() throws Exception { 101 // p says it's ok to exit; it has precendence over the !p loopback branch 102 String grammar = 103 "grammar foo;" + 104 "@lexer::members {boolean p=true;}\n" + 105 "a : (A|B)+ ;\n" + 106 "A : ('a' {System.out.print(\"1\");})*\n" + 107 " {p}?\n" + 108 " ('a' {System.out.print(\"2\");})* ;\n"; 109 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 110 "a", "aaa", false); 111 assertEquals("222\n", found); 112 } 113 testLexerPredInExitBranch2()114 @Test public void testLexerPredInExitBranch2() throws Exception { 115 String grammar = 116 "grammar foo;" + 117 "@lexer::members {boolean p=true;}\n" + 118 "a : (A|B)+ ;\n" + 119 "A : ({p}? 'a' {System.out.print(\"1\");})*\n" + 120 " ('a' {System.out.print(\"2\");})* ;\n"; 121 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 122 "a", "aaa", false); 123 assertEquals("111\n", found); 124 } 125 testLexerPredInExitBranch3()126 @Test public void testLexerPredInExitBranch3() throws Exception { 127 String grammar = 128 "grammar foo;" + 129 "@lexer::members {boolean p=true;}\n" + 130 "a : (A|B)+ ;\n" + 131 "A : ({p}? 'a' {System.out.print(\"1\");} | )\n" + 132 " ('a' {System.out.print(\"2\");})* ;\n"; 133 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 134 "a", "aaa", false); 135 assertEquals("122\n", found); 136 } 137 testLexerPredInExitBranch4()138 @Test public void testLexerPredInExitBranch4() throws Exception { 139 String grammar = 140 "grammar foo;" + 141 "a : (A|B)+ ;\n" + 142 "A @init {int n=0;} : ({n<2}? 'a' {System.out.print(n++);})+\n" + 143 " ('a' {System.out.print(\"x\");})* ;\n"; 144 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 145 "a", "aaaaa", false); 146 assertEquals("01xxx\n", found); 147 } 148 testLexerPredsInCyclicDFA()149 @Test public void testLexerPredsInCyclicDFA() throws Exception { 150 String grammar = 151 "grammar foo;" + 152 "@lexer::members {boolean p=false;}\n" + 153 "a : (A|B)+ ;\n" + 154 "A : {p}? ('a')+ 'x' {System.out.println(\"token 1\");} ;\n" + 155 "B : ('a')+ 'x' {System.out.println(\"token 2\");} ;\n"; 156 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 157 "a", "aax", false); 158 assertEquals("token 2\n", found); 159 } 160 testLexerPredsInCyclicDFA2()161 @Test public void testLexerPredsInCyclicDFA2() throws Exception { 162 String grammar = 163 "grammar foo;" + 164 "@lexer::members {boolean p=false;}\n" + 165 "a : (A|B)+ ;\n" + 166 "A : {p}? ('a')+ 'x' ('y')? {System.out.println(\"token 1\");} ;\n" + 167 "B : ('a')+ 'x' {System.out.println(\"token 2\");} ;\n"; 168 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 169 "a", "aax", false); 170 assertEquals("token 2\n", found); 171 } 172 testGatedPred()173 @Test public void testGatedPred() throws Exception { 174 String grammar = 175 "grammar foo;" + 176 "a : (A|B)+ ;\n" + 177 "A : {true}?=> 'a' {System.out.println(\"token 1\");} ;\n" + 178 "B : {false}?=>('a'|'b')+ {System.out.println(\"token 2\");} ;\n"; 179 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 180 "a", "aa", false); 181 // "a" is ambig; can match both A, B. Pred says match A twice 182 assertEquals("token 1\ntoken 1\n", found); 183 } 184 testGatedPred2()185 @Test public void testGatedPred2() throws Exception { 186 String grammar = 187 "grammar foo;\n" + 188 "@lexer::members {boolean sig=false;}\n"+ 189 "a : (A|B)+ ;\n" + 190 "A : 'a' {System.out.print(\"A\"); sig=true;} ;\n" + 191 "B : 'b' ;\n" + 192 "C : {sig}?=> ('a'|'b') {System.out.print(\"C\");} ;\n"; 193 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 194 "a", "aa", false); 195 assertEquals("AC\n", found); 196 } 197 testPredWithActionTranslation()198 @Test public void testPredWithActionTranslation() throws Exception { 199 String grammar = 200 "grammar foo;\n" + 201 "a : b[2] ;\n" + 202 "b[int i]\n" + 203 " : {$i==1}? 'a' {System.out.println(\"alt 1\");}\n" + 204 " | {$b.i==2}? 'a' {System.out.println(\"alt 2\");}\n" + 205 " ;\n"; 206 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 207 "a", "aa", false); 208 assertEquals("alt 2\n", found); 209 } 210 testPredicatesOnEOTTarget()211 @Test public void testPredicatesOnEOTTarget() throws Exception { 212 String grammar = 213 "grammar foo; \n" + 214 "@lexer::members {boolean p=true, q=false;}" + 215 "a : B ;\n" + 216 "A: '</'; \n" + 217 "B: {p}? '<!' {System.out.println(\"B\");};\n" + 218 "C: {q}? '<' {System.out.println(\"C\");}; \n" + 219 "D: '<';\n" ; 220 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 221 "a", "<!", false); 222 assertEquals("B\n", found); 223 } 224 225 226 // S U P P O R T 227 _test()228 public void _test() throws Exception { 229 String grammar = 230 "grammar T;\n" + 231 "options {output=AST;}\n" + 232 "a : ;\n" + 233 "ID : 'a'..'z'+ ;\n" + 234 "INT : '0'..'9'+;\n" + 235 "WS : (' '|'\\n') {channel=99;} ;\n"; 236 String found = execParser("t.g", grammar, "T", "TLexer", 237 "a", "abc 34", false); 238 assertEquals("\n", found); 239 } 240 241 } 242