1#!/usr/bin/ruby 2# encoding: utf-8 3 4require 'antlr3/test/functional' 5 6class TestASTConstructingParser < ANTLR3::Test::Functional 7 8 compile inline_grammar( <<-'END' ) 9 grammar ASTBuilder; 10 options { 11 language = Ruby; 12 output = AST; 13 } 14 15 tokens { 16 VARDEF; 17 FLOAT; 18 EXPR; 19 BLOCK; 20 VARIABLE; 21 FIELD; 22 CALL; 23 INDEX; 24 FIELDACCESS; 25 } 26 27 @init { 28 @flag = false 29 } 30 31 @members { 32 attr_accessor :flag 33 34 def report_error(e) 35 # do nothing 36 end 37 38 } 39 40 41 r1 42 : INT ('+'^ INT)* 43 ; 44 45 r2 46 : 'assert'^ x=expression (':'! y=expression)? ';'! 47 ; 48 49 r3 50 : 'if'^ expression s1=statement ('else'! s2=statement)? 51 ; 52 53 r4 54 : 'while'^ expression statement 55 ; 56 57 r5 58 : 'return'^ expression? ';'! 59 ; 60 61 r6 62 : (INT|ID)+ 63 ; 64 65 r7 66 : INT -> 67 ; 68 69 r8 70 : 'var' ID ':' type -> ^('var' type ID) 71 ; 72 73 r9 74 : type ID ';' -> ^(VARDEF type ID) 75 ; 76 77 r10 78 : INT -> { ANTLR3::AST::CommonTree.new(ANTLR3::CommonToken.create(:type => FLOAT, :text => ($INT.text + ".0")))} 79 ; 80 81 r11 82 : expression -> ^(EXPR expression) 83 | -> EXPR 84 ; 85 86 r12 87 : ID (',' ID)* -> ID+ 88 ; 89 90 r13 91 : type ID (',' ID)* ';' -> ^(type ID+) 92 ; 93 94 r14 95 : expression? statement* type+ 96 -> ^(EXPR expression? statement* type+) 97 ; 98 99 r15 100 : INT -> INT INT 101 ; 102 103 r16 104 : 'int' ID (',' ID)* -> ^('int' ID)+ 105 ; 106 107 r17 108 : 'for' '(' start=statement ';' expression ';' next=statement ')' statement 109 -> ^('for' $start expression $next statement) 110 ; 111 112 r18 113 : t='for' -> ^(BLOCK) 114 ; 115 116 r19 117 : t='for' -> ^(BLOCK[$t]) 118 ; 119 120 r20 121 : t='for' -> ^(BLOCK[$t,"FOR"]) 122 ; 123 124 r21 125 : t='for' -> BLOCK 126 ; 127 128 r22 129 : t='for' -> BLOCK[$t] 130 ; 131 132 r23 133 : t='for' -> BLOCK[$t,"FOR"] 134 ; 135 136 r24 137 : r=statement expression -> ^($r expression) 138 ; 139 140 r25 141 : r+=statement (',' r+=statement)+ expression -> ^($r expression) 142 ; 143 144 r26 145 : r+=statement (',' r+=statement)+ -> ^(BLOCK $r+) 146 ; 147 148 r27 149 : r=statement expression -> ^($r ^($r expression)) 150 ; 151 152 r28 153 : ('foo28a'|'foo28b') -> 154 ; 155 156 r29 157 : (r+=statement)* -> ^(BLOCK $r+) 158 ; 159 160 r30 161 : statement* -> ^(BLOCK statement?) 162 ; 163 164 r31 165 : modifier type ID ('=' expression)? ';' 166 -> {@flag == 0}? ^(VARDEF ID modifier* type expression?) 167 -> {@flag == 1}? ^(VARIABLE ID modifier* type expression?) 168 -> ^(FIELD ID modifier* type expression?) 169 ; 170 171 r32[which] 172 : ID INT -> {which==1}? ID 173 -> {which==2}? INT 174 -> // yield nothing as else-clause 175 ; 176 177 r33 178 : modifiers! statement 179 ; 180 181 r34 182 : modifiers! r34a[$modifiers.tree] 183 //| modifiers! r33b[$modifiers.tree] 184 ; 185 186 r34a[mod] 187 : 'class' ID ('extends' sup=type)? 188 ( 'implements' i+=type (',' i+=type)*)? 189 '{' statement* '}' 190 -> ^('class' ID {$mod} ^('extends' $sup)? ^('implements' $i+)? statement* ) 191 ; 192 193 r35 194 : '{' 'extends' (sup=type)? '}' 195 -> ^('extends' $sup)? 196 ; 197 198 r36 199 : 'if' '(' expression ')' s1=statement 200 ( 'else' s2=statement -> ^('if' ^(EXPR expression) $s1 $s2) 201 | -> ^('if' ^(EXPR expression) $s1) 202 ) 203 ; 204 205 r37 206 : (INT -> INT) ('+' i=INT -> ^('+' $r37 $i) )* 207 ; 208 209 r38 210 : INT ('+'^ INT)* 211 ; 212 213 r39 214 : (primary->primary) // set return tree to just primary 215 ( '(' arg=expression ')' 216 -> ^(CALL $r39 $arg) 217 | '[' ie=expression ']' 218 -> ^(INDEX $r39 $ie) 219 | '.' p=primary 220 -> ^(FIELDACCESS $r39 $p) 221 )* 222 ; 223 224 r40 225 : (INT -> INT) ( ('+' i+=INT)* -> ^('+' $r40 $i*) ) ';' 226 ; 227 228 r41 229 : (INT -> INT) ( ('+' i=INT) -> ^($i $r41) )* ';' 230 ; 231 232 r42 233 : ids+=ID (','! ids+=ID)* 234 ; 235 236 r43 returns [res] 237 : ids+=ID! (','! ids+=ID!)* {$res = $ids.map { |id| id.text }} 238 ; 239 240 r44 241 : ids+=ID^ (','! ids+=ID^)* 242 ; 243 244 r45 245 : primary^ 246 ; 247 248 r46 returns [res] 249 : ids+=primary! (','! ids+=primary!)* {$res = $ids.map { |id| id.text }} 250 ; 251 252 r47 253 : ids+=primary (','! ids+=primary)* 254 ; 255 256 r48 257 : ids+=. (','! ids+=.)* 258 ; 259 260 r49 261 : .^ ID 262 ; 263 264 r50 265 : ID 266 -> ^({ANTLR3::AST::CommonTree.new(ANTLR3::CommonToken.create(:type => FLOAT, :text => "1.0"))} ID) 267 ; 268 269 /** templates tested: 270 tokenLabelPropertyRef_tree 271 */ 272 r51 returns [res] 273 : ID t=ID ID 274 { $res = $t.tree } 275 ; 276 277 /** templates tested: 278 rulePropertyRef_tree 279 */ 280 r52 returns [res] 281 @after { 282 $res = $tree 283 } 284 : ID 285 ; 286 287 /** templates tested: 288 ruleLabelPropertyRef_tree 289 */ 290 r53 returns [res] 291 : t=primary 292 { $res = $t.tree } 293 ; 294 295 /** templates tested: 296 ruleSetPropertyRef_tree 297 */ 298 r54 returns [res] 299 @after { 300 $tree = $t.tree; 301 } 302 : ID t=expression ID 303 ; 304 305 /** backtracking */ 306 r55 307 options { backtrack=true; k=1; } 308 : (modifier+ INT)=> modifier+ expression 309 | modifier+ statement 310 ; 311 312 313 /** templates tested: 314 rewriteTokenRef with len(args)>0 315 */ 316 r56 317 : t=ID* -> ID[$t,'foo'] 318 ; 319 320 /** templates tested: 321 rewriteTokenRefRoot with len(args)>0 322 */ 323 r57 324 : t=ID* -> ^(ID[$t,'foo']) 325 ; 326 327 /** templates tested: 328 ??? 329 */ 330 r58 331 : ({CommonTree.new(CommonToken.create(:type => FLOAT, :text => "2.0"))})^ 332 ; 333 334 /** templates tested: 335 rewriteTokenListLabelRefRoot 336 */ 337 r59 338 : (t+=ID)+ statement -> ^($t statement)+ 339 ; 340 341 primary 342 : ID 343 ; 344 345 expression 346 : r1 347 ; 348 349 statement 350 : 'fooze' 351 | 'fooze2' 352 ; 353 354 modifiers 355 : modifier+ 356 ; 357 358 modifier 359 : 'public' 360 | 'private' 361 ; 362 363 type 364 : 'int' 365 | 'bool' 366 ; 367 368 ID : 'a'..'z' + ; 369 INT : '0'..'9' +; 370 WS: (' ' | '\n' | '\t')+ {$channel = HIDDEN;}; 371 END 372 373 def self.ast_test( opts, &special_test ) 374 input = opts[ :input ] 375 rule = opts[ :rule ] 376 expected_tree = opts[ :ast ] 377 flag = opts[ :flag ] 378 args = opts[ :arguments ] || [] 379 message = opts[ :message ] || rule.to_s #"should parse %p with rule %s and make tree %s" % [input, rule, expected_tree] 380 381 example( message ) do 382 lexer = ASTBuilder::Lexer.new( input ) 383 parser = ASTBuilder::Parser.new( lexer ) 384 parser.flag = flag unless flag.nil? 385 result = parser.send( rule, *args ) 386 if special_test then instance_exec( result, &special_test ) 387 elsif expected_tree then 388 result.tree.inspect.should == expected_tree 389 else result.tree.should be_nil 390 end 391 end 392 end 393 394 ast_test :input => "1 + 2", :rule => :r1, :ast => "(+ 1 2)" 395 396 ast_test :input => "assert 2+3", :rule => :r2, :ast => "(assert (+ 2 3))" 397 398 ast_test :input => "assert 2+3 : 5", :rule => :r2, :ast => "(assert (+ 2 3) 5)" 399 400 ast_test :input => "if 1 fooze", :rule => :r3, :ast => "(if 1 fooze)" 401 402 ast_test :input => "if 1 fooze else fooze", :rule => :r3, :ast => "(if 1 fooze fooze)" 403 404 ast_test :input => "while 2 fooze", :rule => :r4, :ast => "(while 2 fooze)" 405 406 ast_test :input => "return;", :rule => :r5, :ast => "return" 407 408 ast_test :input => "return 2+3;", :rule => :r5, :ast => "(return (+ 2 3))" 409 410 ast_test :input => "3", :rule => :r6, :ast => "3" 411 412 ast_test :input => "3 a", :rule => :r6, :ast => "3 a" 413 414 ast_test :input => "3", :rule => :r7, :ast => nil 415 416 ast_test :input => "var foo:bool", :rule => :r8, :ast => "(var bool foo)" 417 418 ast_test :input => "int foo;", :rule => :r9, :ast => "(VARDEF int foo)" 419 420 ast_test :input => "10", :rule => :r10, :ast => "10.0" 421 422 ast_test :input => "1+2", :rule => :r11, :ast => "(EXPR (+ 1 2))" 423 424 ast_test :input => "", :rule => :r11, :ast => "EXPR" 425 426 ast_test :input => "foo", :rule => :r12, :ast => "foo" 427 428 ast_test :input => "foo, bar, gnurz", :rule => :r12, :ast => "foo bar gnurz" 429 430 ast_test :input => "int foo;", :rule => :r13, :ast => "(int foo)" 431 432 ast_test :input => "bool foo, bar, gnurz;", :rule => :r13, :ast => "(bool foo bar gnurz)" 433 434 ast_test :input => "1+2 int", :rule => :r14, :ast => "(EXPR (+ 1 2) int)" 435 436 ast_test :input => "1+2 int bool", :rule => :r14, :ast => "(EXPR (+ 1 2) int bool)" 437 438 ast_test :input => "int bool", :rule => :r14, :ast => "(EXPR int bool)" 439 440 ast_test :input => "fooze fooze int bool", :rule => :r14, :ast => "(EXPR fooze fooze int bool)" 441 442 ast_test :input => "7+9 fooze fooze int bool", :rule => :r14, :ast => "(EXPR (+ 7 9) fooze fooze int bool)" 443 444 ast_test :input => "7", :rule => :r15, :ast => "7 7" 445 446 ast_test :input => "int foo", :rule => :r16, :ast => "(int foo)" 447 448 ast_test :input => "int foo, bar, gnurz", :rule => :r16, :ast => "(int foo) (int bar) (int gnurz)" 449 450 ast_test :input => "for ( fooze ; 1 + 2 ; fooze ) fooze", :rule => :r17, :ast => "(for fooze (+ 1 2) fooze fooze)" 451 452 ast_test :input => "for", :rule => :r18, :ast => "BLOCK" 453 454 ast_test :input => "for", :rule => :r19, :ast => "for" 455 456 ast_test :input => "for", :rule => :r20, :ast => "FOR" 457 458 ast_test :input => "for", :rule => :r21, :ast => "BLOCK" 459 460 ast_test :input => "for", :rule => :r22, :ast => "for" 461 462 ast_test :input => "for", :rule => :r23, :ast => "FOR" 463 464 ast_test :input => "fooze 1 + 2", :rule => :r24, :ast => "(fooze (+ 1 2))" 465 466 ast_test :input => "fooze, fooze2 1 + 2", :rule => :r25, :ast => "(fooze (+ 1 2))" 467 468 ast_test :input => "fooze, fooze2", :rule => :r26, :ast => "(BLOCK fooze fooze2)" 469 470 ast_test :input => "fooze 1 + 2", :rule => :r27, :ast => "(fooze (fooze (+ 1 2)))" 471 472 ast_test :input => "foo28a", :rule => :r28, :ast => nil 473 474 ast_test :input => "public int gnurz = 1 + 2;", :rule => :r31, :ast => "(VARDEF gnurz public int (+ 1 2))", :flag => 0 475 476 ast_test :input => "public int gnurz = 1 + 2;", :rule => :r31, :ast => "(VARIABLE gnurz public int (+ 1 2))", :flag => 1 477 478 ast_test :input => "public int gnurz = 1 + 2;", :rule => :r31, :ast => "(FIELD gnurz public int (+ 1 2))", :flag => 2 479 480 ast_test :input => 'gnurz 32', :rule => :r32, :arguments => [ 1 ], :flag => 2, :ast => 'gnurz' 481 482 ast_test :input => 'gnurz 32', :rule => :r32, :arguments => [ 2 ], :flag => 2, :ast => '32' 483 484 ast_test :input => 'gnurz', :rule => :r32, :arguments => [ 3 ], :flag => 2, :ast => nil 485 486 ast_test :input => "public private fooze", :rule => :r33, :ast => "fooze" 487 488 ast_test :input => "public class gnurz { fooze fooze2 }", :rule => :r34, :ast => "(class gnurz public fooze fooze2)" 489 490 ast_test :input => "public class gnurz extends bool implements int, bool { fooze fooze2 }", :rule => :r34, :ast => "(class gnurz public (extends bool) (implements int bool) fooze fooze2)" 491 492 ast_test :input => "if ( 1 + 2 ) fooze", :rule => :r36, :ast => "(if (EXPR (+ 1 2)) fooze)" 493 494 ast_test :input => "1 + 2 + 3", :rule => :r37, :ast => "(+ (+ 1 2) 3)" 495 496 ast_test :input => "1 + 2 + 3", :rule => :r38, :ast => "(+ (+ 1 2) 3)" 497 498 ast_test :input => "gnurz[1]", :rule => :r39, :ast => "(INDEX gnurz 1)" 499 500 ast_test :input => "gnurz(2)", :rule => :r39, :ast => "(CALL gnurz 2)" 501 502 ast_test :input => "gnurz.gnarz", :rule => :r39, :ast => "(FIELDACCESS gnurz gnarz)" 503 504 ast_test :input => "gnurz.gnarz.gnorz", :rule => :r39, :ast => "(FIELDACCESS (FIELDACCESS gnurz gnarz) gnorz)" 505 506 ast_test :input => "1 + 2 + 3;", :rule => :r40, :ast => "(+ 1 2 3)" 507 508 ast_test :input => "1 + 2 + 3;", :rule => :r41, :ast => "(3 (2 1))" 509 510 ast_test :input => "gnurz, gnarz, gnorz", :rule => :r42, :ast => "gnurz gnarz gnorz" 511 512 ast_test :input => "gnurz, gnarz, gnorz", :rule => :r43 do |result| 513 result.tree.should be_nil 514 result.res.should == %w(gnurz gnarz gnorz) 515 end 516 517 ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r44, :ast => '(gnorz (gnarz gnurz))' 518 519 ast_test :input => 'gnurz', :rule => :r45, :ast => 'gnurz' 520 521 ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r46 do |result| 522 result.tree.should be_nil 523 result.res.should == %w(gnurz gnarz gnorz) 524 end 525 526 ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r47, :ast => 'gnurz gnarz gnorz' 527 528 ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r48, :ast => 'gnurz gnarz gnorz' 529 530 ast_test :input => 'gnurz gnorz', :rule => :r49, :ast => '(gnurz gnorz)' 531 532 ast_test :input => 'gnurz', :rule => :r50, :ast => '(1.0 gnurz)' 533 534 ast_test :input => 'gnurza gnurzb gnurzc', :rule => :r51 do |result| 535 result.res.inspect.should == 'gnurzb' 536 end 537 538 ast_test :input => 'gnurz', :rule => :r52, :ast => 'gnurz' 539 540 ast_test :input => 'gnurz', :rule => :r53, :ast => 'gnurz' 541 542 ast_test :input => 'gnurza 1 + 2 gnurzb', :rule => :r54, :ast => '(+ 1 2)' 543 544 ast_test :input => 'public private 1 + 2', :rule => :r55, :ast => 'public private (+ 1 2)' 545 546 ast_test :input => 'public fooze', :rule => :r55, :ast => 'public fooze' 547 548 ast_test :input => 'a b c d', :rule => :r56, :ast => 'foo' 549 550 ast_test :input => 'a b c d', :rule => :r57, :ast => 'foo' 551 552 ast_test :input => 'a b c fooze', :rule => :r59, :ast => '(a fooze) (b fooze) (c fooze)' 553 554end 555