1 package org.antlr.test; 2 3 import org.junit.Ignore; 4 import org.junit.Test; 5 6 import static org.junit.Assert.*; 7 8 /** */ 9 @Ignore 10 public class TestLeftRecursion extends BaseTest { 11 protected boolean debug = false; 12 testSimple()13 @Test public void testSimple() throws Exception { 14 String grammar = 15 "grammar T;\n" + 16 "s : a {System.out.println($a.text);} ;\n" + 17 "a : a ID\n" + 18 " | ID" + 19 " ;\n" + 20 "ID : 'a'..'z'+ ;\n" + 21 "WS : (' '|'\\n') {skip();} ;\n"; 22 String found = execParser("T.g", grammar, "TParser", "TLexer", 23 "s", "a b c", debug); 24 String expecting = "abc\n"; 25 assertEquals(expecting, found); 26 } 27 testSemPred()28 @Test public void testSemPred() throws Exception { 29 String grammar = 30 "grammar T;\n" + 31 "s : a {System.out.println($a.text);} ;\n" + 32 "a : a {true}? ID\n" + 33 " | ID" + 34 " ;\n" + 35 "ID : 'a'..'z'+ ;\n" + 36 "WS : (' '|'\\n') {skip();} ;\n"; 37 String found = execParser("T.g", grammar, "TParser", "TLexer", 38 "s", "a b c", debug); 39 String expecting = "abc\n"; 40 assertEquals(expecting, found); 41 } 42 testTernaryExpr()43 @Test public void testTernaryExpr() throws Exception { 44 String grammar = 45 "grammar T;\n" + 46 "options {output=AST;}\n" + 47 "e : e '*'^ e" + 48 " | e '+'^ e" + 49 " | e '?'<assoc=right>^ e ':'! e" + 50 " | e '='<assoc=right>^ e" + 51 " | ID" + 52 " ;\n" + 53 "ID : 'a'..'z'+ ;\n" + 54 "WS : (' '|'\\n') {skip();} ;\n"; 55 String[] tests = { 56 "a", "a", 57 "a+b", "(+ a b)", 58 "a*b", "(* a b)", 59 "a?b:c", "(? a b c)", 60 "a=b=c", "(= a (= b c))", 61 "a?b+c:d", "(? a (+ b c) d)", 62 "a?b=c:d", "(? a (= b c) d)", 63 "a? b?c:d : e", "(? a (? b c d) e)", 64 "a?b: c?d:e", "(? a b (? c d e))", 65 }; 66 runTests(grammar, tests, "e"); 67 } 68 testDeclarationsUsingASTOperators()69 @Test public void testDeclarationsUsingASTOperators() throws Exception { 70 String grammar = 71 "grammar T;\n" + 72 "options {output=AST;}\n" + 73 "declarator\n" + 74 " : declarator '['^ e ']'!\n" + 75 " | declarator '['^ ']'!\n" + 76 " | declarator '('^ ')'!\n" + 77 " | '*'^ declarator\n" + // binds less tight than suffixes 78 " | '('! declarator ')'!\n" + 79 " | ID\n" + 80 " ;\n" + 81 "e : INT ;\n" + 82 "ID : 'a'..'z'+ ;\n" + 83 "INT : '0'..'9'+ ;\n" + 84 "WS : (' '|'\\n') {skip();} ;\n"; 85 String[] tests = { 86 "a", "a", 87 "*a", "(* a)", 88 "**a", "(* (* a))", 89 "a[3]", "([ a 3)", 90 "b[]", "([ b)", 91 "(a)", "a", 92 "a[]()", "(( ([ a))", 93 "a[][]", "([ ([ a))", 94 "*a[]", "(* ([ a))", 95 "(*a)[]", "([ (* a))", 96 }; 97 runTests(grammar, tests, "declarator"); 98 } 99 testDeclarationsUsingRewriteOperators()100 @Test public void testDeclarationsUsingRewriteOperators() throws Exception { 101 String grammar = 102 "grammar T;\n" + 103 "options {output=AST;}\n" + 104 "declarator\n" + 105 " : declarator '[' e ']' -> ^('[' declarator e)\n" + 106 " | declarator '[' ']' -> ^('[' declarator)\n" + 107 " | declarator '(' ')' -> ^('(' declarator)\n" + 108 " | '*' declarator -> ^('*' declarator) \n" + // binds less tight than suffixes 109 " | '(' declarator ')' -> declarator\n" + 110 " | ID -> ID\n" + 111 " ;\n" + 112 "e : INT ;\n" + 113 "ID : 'a'..'z'+ ;\n" + 114 "INT : '0'..'9'+ ;\n" + 115 "WS : (' '|'\\n') {skip();} ;\n"; 116 String[] tests = { 117 "a", "a", 118 "*a", "(* a)", 119 "**a", "(* (* a))", 120 "a[3]", "([ a 3)", 121 "b[]", "([ b)", 122 "(a)", "a", 123 "a[]()", "(( ([ a))", 124 "a[][]", "([ ([ a))", 125 "*a[]", "(* ([ a))", 126 "(*a)[]", "([ (* a))", 127 }; 128 runTests(grammar, tests, "declarator"); 129 } 130 testExpressionsUsingASTOperators()131 @Test public void testExpressionsUsingASTOperators() throws Exception { 132 String grammar = 133 "grammar T;\n" + 134 "options {output=AST;}\n" + 135 "e : e '.'^ ID\n" + 136 " | e '.'^ 'this'\n" + 137 " | '-'^ e\n" + 138 " | e '*'^ e\n" + 139 " | e ('+'^|'-'^) e\n" + 140 " | INT\n" + 141 " | ID\n" + 142 " ;\n" + 143 "ID : 'a'..'z'+ ;\n" + 144 "INT : '0'..'9'+ ;\n" + 145 "WS : (' '|'\\n') {skip();} ;\n"; 146 String[] tests = { 147 "a", "a", 148 "1", "1", 149 "a+1", "(+ a 1)", 150 "a*1", "(* a 1)", 151 "a.b", "(. a b)", 152 "a.this", "(. a this)", 153 "a-b+c", "(+ (- a b) c)", 154 "a+b*c", "(+ a (* b c))", 155 "a.b+1", "(+ (. a b) 1)", 156 "-a", "(- a)", 157 "-a+b", "(+ (- a) b)", 158 "-a.b", "(- (. a b))", 159 }; 160 runTests(grammar, tests, "e"); 161 } 162 testExpressionsUsingRewriteOperators()163 @Test public void testExpressionsUsingRewriteOperators() throws Exception { 164 String grammar = 165 "grammar T;\n" + 166 "options {output=AST;}\n" + 167 "e : e '.' ID -> ^('.' e ID)\n" + 168 " | e '.' 'this' -> ^('.' e 'this')\n" + 169 " | '-' e -> ^('-' e)\n" + 170 " | e '*' b=e -> ^('*' e $b)\n" + 171 " | e (op='+'|op='-') b=e -> ^($op e $b)\n" + 172 " | INT -> INT\n" + 173 " | ID -> ID\n" + 174 " ;\n" + 175 "ID : 'a'..'z'+ ;\n" + 176 "INT : '0'..'9'+ ;\n" + 177 "WS : (' '|'\\n') {skip();} ;\n"; 178 String[] tests = { 179 "a", "a", 180 "1", "1", 181 "a+1", "(+ a 1)", 182 "a*1", "(* a 1)", 183 "a.b", "(. a b)", 184 "a.this", "(. a this)", 185 "a+b*c", "(+ a (* b c))", 186 "a.b+1", "(+ (. a b) 1)", 187 "-a", "(- a)", 188 "-a+b", "(+ (- a) b)", 189 "-a.b", "(- (. a b))", 190 }; 191 runTests(grammar, tests, "e"); 192 } 193 testExpressionAssociativity()194 @Test public void testExpressionAssociativity() throws Exception { 195 String grammar = 196 "grammar T;\n" + 197 "options {output=AST;}\n" + 198 "e\n" + 199 " : e '.'^ ID\n" + 200 " | '-'^ e\n" + 201 " | e '^'<assoc=right>^ e\n" + 202 " | e '*'^ e\n" + 203 " | e ('+'^|'-'^) e\n" + 204 " | e ('='<assoc=right>^ |'+='<assoc=right>^) e\n" + 205 " | INT\n" + 206 " | ID\n" + 207 " ;\n" + 208 "ID : 'a'..'z'+ ;\n" + 209 "INT : '0'..'9'+ ;\n" + 210 "WS : (' '|'\\n') {skip();} ;\n"; 211 String[] tests = { 212 "a", "a", 213 "1", "1", 214 "a+1", "(+ a 1)", 215 "a*1", "(* a 1)", 216 "a.b", "(. a b)", 217 "a-b+c", "(+ (- a b) c)", 218 219 "a+b*c", "(+ a (* b c))", 220 "a.b+1", "(+ (. a b) 1)", 221 "-a", "(- a)", 222 "-a+b", "(+ (- a) b)", 223 "-a.b", "(- (. a b))", 224 "a^b^c", "(^ a (^ b c))", 225 "a=b=c", "(= a (= b c))", 226 "a=b=c+d.e","(= a (= b (+ c (. d e))))", 227 }; 228 runTests(grammar, tests, "e"); 229 } 230 testJavaExpressions()231 @Test public void testJavaExpressions() throws Exception { 232 // Generates about 7k in bytecodes for generated e_ rule; 233 // Well within the 64k method limit. e_primary compiles 234 // to about 2k in bytecodes. 235 // this is simplified from real java 236 String grammar = 237 "grammar T;\n" + 238 "options {output=AST;}\n" + 239 "expressionList\n" + 240 " : e (','! e)*\n" + 241 " ;\n" + 242 "e : '('! e ')'!\n" + 243 " | 'this' \n" + 244 " | 'super'\n" + 245 " | INT\n" + 246 " | ID\n" + 247 " | type '.'^ 'class'\n" + 248 " | e '.'^ ID\n" + 249 " | e '.'^ 'this'\n" + 250 " | e '.'^ 'super' '('^ expressionList? ')'!\n" + 251 " | e '.'^ 'new'^ ID '('! expressionList? ')'!\n" + 252 " | 'new'^ type ( '(' expressionList? ')'! | (options {k=1;}:'[' e ']'!)+)\n" + // ugly; simplified 253 " | e '['^ e ']'!\n" + 254 " | '('^ type ')'! e\n" + 255 " | e ('++'^ | '--'^)\n" + 256 " | e '('^ expressionList? ')'!\n" + 257 " | ('+'^|'-'^|'++'^|'--'^) e\n" + 258 " | ('~'^|'!'^) e\n" + 259 " | e ('*'^|'/'^|'%'^) e\n" + 260 " | e ('+'^|'-'^) e\n" + 261 " | e ('<'^ '<' | '>'^ '>' '>' | '>'^ '>') e\n" + 262 " | e ('<='^ | '>='^ | '>'^ | '<'^) e\n" + 263 " | e 'instanceof'^ e\n" + 264 " | e ('=='^ | '!='^) e\n" + 265 " | e '&'^ e\n" + 266 " | e '^'<assoc=right>^ e\n" + 267 " | e '|'^ e\n" + 268 " | e '&&'^ e\n" + 269 " | e '||'^ e\n" + 270 " | e '?' e ':' e\n" + 271 " | e ('='<assoc=right>^\n" + 272 " |'+='<assoc=right>^\n" + 273 " |'-='<assoc=right>^\n" + 274 " |'*='<assoc=right>^\n" + 275 " |'/='<assoc=right>^\n" + 276 " |'&='<assoc=right>^\n" + 277 " |'|='<assoc=right>^\n" + 278 " |'^='<assoc=right>^\n" + 279 " |'>>='<assoc=right>^\n" + 280 " |'>>>='<assoc=right>^\n" + 281 " |'<<='<assoc=right>^\n" + 282 " |'%='<assoc=right>^) e\n" + 283 " ;\n" + 284 "type: ID \n" + 285 " | ID '['^ ']'!\n" + 286 " | 'int'\n" + 287 " | 'int' '['^ ']'! \n" + 288 " ;\n" + 289 "ID : ('a'..'z'|'A'..'Z'|'_'|'$')+;\n" + 290 "INT : '0'..'9'+ ;\n" + 291 "WS : (' '|'\\n') {skip();} ;\n"; 292 String[] tests = { 293 "a", "a", 294 "1", "1", 295 "a+1", "(+ a 1)", 296 "a*1", "(* a 1)", 297 "a.b", "(. a b)", 298 "a-b+c", "(+ (- a b) c)", 299 300 "a+b*c", "(+ a (* b c))", 301 "a.b+1", "(+ (. a b) 1)", 302 "-a", "(- a)", 303 "-a+b", "(+ (- a) b)", 304 "-a.b", "(- (. a b))", 305 "a^b^c", "(^ a (^ b c))", 306 "a=b=c", "(= a (= b c))", 307 "a=b=c+d.e","(= a (= b (+ c (. d e))))", 308 "a|b&c", "(| a (& b c))", 309 "(a|b)&c", "(& (| a b) c)", 310 "a > b", "(> a b)", 311 "a >> b", "(> a b)", // text is from one token 312 "a < b", "(< a b)", 313 314 "(T)x", "(( T x)", 315 "new A().b", "(. (new A () b)", 316 "(T)t.f()", "(( (( T (. t f)))", 317 "a.f(x)==T.c", "(== (( (. a f) x) (. T c))", 318 "a.f().g(x,1)", "(( (. (( (. a f)) g) x 1)", 319 "new T[((n-1) * x) + 1]", "(new T [ (+ (* (- n 1) x) 1))", 320 }; 321 runTests(grammar, tests, "e"); 322 } 323 testReturnValueAndActions()324 @Test public void testReturnValueAndActions() throws Exception { 325 String grammar = 326 "grammar T;\n" + 327 "s : e {System.out.println($e.v);} ;\n" + 328 "e returns [int v, List<String> ignored]\n" + 329 " : e '*' b=e {$v *= $b.v;}\n" + 330 " | e '+' b=e {$v += $b.v;}\n" + 331 " | INT {$v = $INT.int;}\n" + 332 " ;\n" + 333 "INT : '0'..'9'+ ;\n" + 334 "WS : (' '|'\\n') {skip();} ;\n"; 335 String[] tests = { 336 "4", "4", 337 "1+2", "3", 338 }; 339 runTests(grammar, tests, "s"); 340 } 341 testReturnValueAndActionsAndASTs()342 @Test public void testReturnValueAndActionsAndASTs() throws Exception { 343 String grammar = 344 "grammar T;\n" + 345 "options {output=AST;}\n" + 346 "s : e {System.out.print(\"v=\"+$e.v+\", \");} ;\n" + 347 "e returns [int v, List<String> ignored]\n" + 348 " : e '*'^ b=e {$v *= $b.v;}\n" + 349 " | e '+'^ b=e {$v += $b.v;}\n" + 350 " | INT {$v = $INT.int;}\n" + 351 " ;\n" + 352 "INT : '0'..'9'+ ;\n" + 353 "WS : (' '|'\\n') {skip();} ;\n"; 354 String[] tests = { 355 "4", "v=4, 4", 356 "1+2", "v=3, (+ 1 2)", 357 }; 358 runTests(grammar, tests, "s"); 359 } 360 runTests(String grammar, String[] tests, String startRule)361 public void runTests(String grammar, String[] tests, String startRule) { 362 rawGenerateAndBuildRecognizer("T.g", grammar, "TParser", "TLexer", debug); 363 boolean parserBuildsTrees = 364 grammar.indexOf("output=AST")>=0 || 365 grammar.indexOf("output = AST")>=0; 366 writeRecognizerAndCompile("TParser", 367 null, 368 "TLexer", 369 startRule, 370 null, 371 parserBuildsTrees, 372 false, 373 false, 374 debug); 375 376 for (int i=0; i<tests.length; i+=2) { 377 String test = tests[i]; 378 String expecting = tests[i+1]+"\n"; 379 writeFile(tmpdir, "input", test); 380 String found = execRecognizer(); 381 System.out.print(test+" -> "+found); 382 assertEquals(expecting, found); 383 } 384 } 385 386 } 387