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 public class TestSemanticPredicateEvaluation extends BaseTest { testSimpleCyclicDFAWithPredicate()33 @Test public void testSimpleCyclicDFAWithPredicate() throws Exception { 34 String grammar = 35 "grammar foo;\n" + 36 "a : {false}? 'x'* 'y' {System.out.println(\"alt1\");}\n" + 37 " | {true}? 'x'* 'y' {System.out.println(\"alt2\");}\n" + 38 " ;\n" ; 39 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 40 "a", "xxxy", false); 41 assertEquals("alt2\n", found); 42 } 43 testSimpleCyclicDFAWithInstanceVarPredicate()44 @Test public void testSimpleCyclicDFAWithInstanceVarPredicate() throws Exception { 45 String grammar = 46 "grammar foo;\n" + 47 "@members {boolean v=true;}\n" + 48 "a : {false}? 'x'* 'y' {System.out.println(\"alt1\");}\n" + 49 " | {v}? 'x'* 'y' {System.out.println(\"alt2\");}\n" + 50 " ;\n" ; 51 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 52 "a", "xxxy", false); 53 assertEquals("alt2\n", found); 54 } 55 testPredicateValidation()56 @Test public void testPredicateValidation() throws Exception { 57 String grammar = 58 "grammar foo;\n" + 59 "@members {\n" + 60 "public void reportError(RecognitionException e) {\n" + 61 " System.out.println(\"error: \"+e.toString());\n" + 62 "}\n" + 63 "}\n" + 64 "\n" + 65 "a : {false}? 'x'\n" + 66 " ;\n" ; 67 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 68 "a", "x", false); 69 assertEquals("error: FailedPredicateException(a,{false}?)\n", found); 70 } 71 testLexerPreds()72 @Test public void testLexerPreds() throws Exception { 73 String grammar = 74 "grammar foo;" + 75 "@lexer::members {boolean p=false;}\n" + 76 "a : (A|B)+ ;\n" + 77 "A : {p}? 'a' {System.out.println(\"token 1\");} ;\n" + 78 "B : {!p}? 'a' {System.out.println(\"token 2\");} ;\n"; 79 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 80 "a", "a", false); 81 // "a" is ambig; can match both A, B. Pred says match 2 82 assertEquals("token 2\n", found); 83 } 84 testLexerPreds2()85 @Test public void testLexerPreds2() throws Exception { 86 String grammar = 87 "grammar foo;" + 88 "@lexer::members {boolean p=true;}\n" + 89 "a : (A|B)+ ;\n" + 90 "A : {p}? 'a' {System.out.println(\"token 1\");} ;\n" + 91 "B : ('a'|'b')+ {System.out.println(\"token 2\");} ;\n"; 92 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 93 "a", "a", false); 94 // "a" is ambig; can match both A, B. Pred says match 1 95 assertEquals("token 1\n", found); 96 } 97 testLexerPredInExitBranch()98 @Test public void testLexerPredInExitBranch() throws Exception { 99 // p says it's ok to exit; it has precendence over the !p loopback branch 100 String grammar = 101 "grammar foo;" + 102 "@lexer::members {boolean p=true;}\n" + 103 "a : (A|B)+ ;\n" + 104 "A : ('a' {System.out.print(\"1\");})*\n" + 105 " {p}?\n" + 106 " ('a' {System.out.print(\"2\");})* ;\n"; 107 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 108 "a", "aaa", false); 109 assertEquals("222\n", found); 110 } 111 testLexerPredInExitBranch2()112 @Test public void testLexerPredInExitBranch2() throws Exception { 113 String grammar = 114 "grammar foo;" + 115 "@lexer::members {boolean p=true;}\n" + 116 "a : (A|B)+ ;\n" + 117 "A : ({p}? 'a' {System.out.print(\"1\");})*\n" + 118 " ('a' {System.out.print(\"2\");})* ;\n"; 119 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 120 "a", "aaa", false); 121 assertEquals("111\n", found); 122 } 123 testLexerPredInExitBranch3()124 @Test public void testLexerPredInExitBranch3() throws Exception { 125 String grammar = 126 "grammar foo;" + 127 "@lexer::members {boolean p=true;}\n" + 128 "a : (A|B)+ ;\n" + 129 "A : ({p}? 'a' {System.out.print(\"1\");} | )\n" + 130 " ('a' {System.out.print(\"2\");})* ;\n"; 131 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 132 "a", "aaa", false); 133 assertEquals("122\n", found); 134 } 135 testLexerPredInExitBranch4()136 @Test public void testLexerPredInExitBranch4() throws Exception { 137 String grammar = 138 "grammar foo;" + 139 "a : (A|B)+ ;\n" + 140 "A @init {int n=0;} : ({n<2}? 'a' {System.out.print(n++);})+\n" + 141 " ('a' {System.out.print(\"x\");})* ;\n"; 142 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 143 "a", "aaaaa", false); 144 assertEquals("01xxx\n", found); 145 } 146 testLexerPredsInCyclicDFA()147 @Test public void testLexerPredsInCyclicDFA() throws Exception { 148 String grammar = 149 "grammar foo;" + 150 "@lexer::members {boolean p=false;}\n" + 151 "a : (A|B)+ ;\n" + 152 "A : {p}? ('a')+ 'x' {System.out.println(\"token 1\");} ;\n" + 153 "B : ('a')+ 'x' {System.out.println(\"token 2\");} ;\n"; 154 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 155 "a", "aax", false); 156 assertEquals("token 2\n", found); 157 } 158 testLexerPredsInCyclicDFA2()159 @Test public void testLexerPredsInCyclicDFA2() throws Exception { 160 String grammar = 161 "grammar foo;" + 162 "@lexer::members {boolean p=false;}\n" + 163 "a : (A|B)+ ;\n" + 164 "A : {p}? ('a')+ 'x' ('y')? {System.out.println(\"token 1\");} ;\n" + 165 "B : ('a')+ 'x' {System.out.println(\"token 2\");} ;\n"; 166 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 167 "a", "aax", false); 168 assertEquals("token 2\n", found); 169 } 170 testGatedPred()171 @Test public void testGatedPred() throws Exception { 172 String grammar = 173 "grammar foo;" + 174 "a : (A|B)+ ;\n" + 175 "A : {true}?=> 'a' {System.out.println(\"token 1\");} ;\n" + 176 "B : {false}?=>('a'|'b')+ {System.out.println(\"token 2\");} ;\n"; 177 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 178 "a", "aa", false); 179 // "a" is ambig; can match both A, B. Pred says match A twice 180 assertEquals("token 1\ntoken 1\n", found); 181 } 182 testGatedPred2()183 @Test public void testGatedPred2() throws Exception { 184 String grammar = 185 "grammar foo;\n" + 186 "@lexer::members {boolean sig=false;}\n"+ 187 "a : (A|B)+ ;\n" + 188 "A : 'a' {System.out.print(\"A\"); sig=true;} ;\n" + 189 "B : 'b' ;\n" + 190 "C : {sig}?=> ('a'|'b') {System.out.print(\"C\");} ;\n"; 191 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 192 "a", "aa", false); 193 assertEquals("AC\n", found); 194 } 195 testPredWithActionTranslation()196 @Test public void testPredWithActionTranslation() throws Exception { 197 String grammar = 198 "grammar foo;\n" + 199 "a : b[2] ;\n" + 200 "b[int i]\n" + 201 " : {$i==1}? 'a' {System.out.println(\"alt 1\");}\n" + 202 " | {$b.i==2}? 'a' {System.out.println(\"alt 2\");}\n" + 203 " ;\n"; 204 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 205 "a", "aa", false); 206 assertEquals("alt 2\n", found); 207 } 208 testPredicatesOnEOTTarget()209 @Test public void testPredicatesOnEOTTarget() throws Exception { 210 String grammar = 211 "grammar foo; \n" + 212 "@lexer::members {boolean p=true, q=false;}" + 213 "a : B ;\n" + 214 "A: '</'; \n" + 215 "B: {p}? '<!' {System.out.println(\"B\");};\n" + 216 "C: {q}? '<' {System.out.println(\"C\");}; \n" + 217 "D: '<';\n" ; 218 String found = execParser("foo.g", grammar, "fooParser", "fooLexer", 219 "a", "<!", false); 220 assertEquals("B\n", found); 221 } 222 223 224 // S U P P O R T 225 _test()226 public void _test() throws Exception { 227 String grammar = 228 "grammar T;\n" + 229 "options {output=AST;}\n" + 230 "a : ;\n" + 231 "ID : 'a'..'z'+ ;\n" + 232 "INT : '0'..'9'+;\n" + 233 "WS : (' '|'\\n') {channel=99;} ;\n"; 234 String found = execParser("t.g", grammar, "T", "TLexer", 235 "a", "abc 34", false); 236 assertEquals("\n", found); 237 } 238 239 } 240