1#!/usr/bin/ruby 2# encoding: utf-8 3 4require 'antlr3/test/functional' 5 6 7class TestHeterogeneousNodeTypes < ANTLR3::Test::Functional 8 9 inline_grammar( <<-'END' ) 10 grammar VToken; 11 options { 12 language=Ruby; 13 output=AST; 14 } 15 @members { 16 class V < ANTLR3::CommonTree 17 def to_s 18 return @token.text + "<V>" 19 end 20 end 21 } 22 a : ID<V> ; 23 ID : 'a'..'z'+ ; 24 WS : (' '|'\n') {$channel=HIDDEN;} ; 25 END 26 27 28 inline_grammar( <<-'END' ) 29 grammar TokenWithQualifiedType; 30 options { 31 language=Ruby; 32 output=AST; 33 } 34 @members { 35 class V < ANTLR3::CommonTree 36 def to_s 37 return @token.text + "<V>" 38 end 39 end 40 } 41 a : ID<TokenWithQualifiedType.Parser.V> ; 42 ID : 'a'..'z'+ ; 43 WS : (' '|'\n') {$channel=HIDDEN;} ; 44 END 45 46 47 inline_grammar( <<-'END' ) 48 grammar TokenWithLabel; 49 options { 50 language=Ruby; 51 output=AST; 52 } 53 @members { 54 class V < ANTLR3::CommonTree 55 def to_s 56 return @token.text + "<V>" 57 end 58 end 59 } 60 a : x=ID<V> ; 61 ID : 'a'..'z'+ ; 62 WS : (' '|'\n') {$channel=HIDDEN;} ; 63 END 64 65 66 inline_grammar( <<-'END' ) 67 grammar TokenWithListLabel; 68 options { 69 language=Ruby; 70 output=AST; 71 } 72 @members { 73 class V < ANTLR3::CommonTree 74 def to_s 75 return @token.text + "<V>" 76 end 77 end 78 } 79 a : x+=ID<V> ; 80 ID : 'a'..'z'+ ; 81 WS : (' '|'\n') {$channel=HIDDEN;} ; 82 END 83 84 85 inline_grammar( <<-'END' ) 86 grammar TokenRoot; 87 options { 88 language=Ruby; 89 output=AST; 90 } 91 @members { 92 class V < ANTLR3::CommonTree 93 def to_s 94 return @token.text + "<V>" 95 end 96 end 97 98 } 99 a : ID<V>^ ; 100 ID : 'a'..'z'+ ; 101 WS : (' '|'\n') {$channel=HIDDEN;} ; 102 END 103 104 105 inline_grammar( <<-'END' ) 106 grammar TokenRootWithListLabel; 107 options { 108 language=Ruby; 109 output=AST; 110 } 111 @members { 112 class V < ANTLR3::CommonTree 113 def to_s 114 return @token.text + "<V>" 115 end 116 end 117 118 } 119 a : x+=ID<V>^ ; 120 ID : 'a'..'z'+ ; 121 WS : (' '|'\n') {$channel=HIDDEN;} ; 122 END 123 124 125 inline_grammar( <<-'END' ) 126 grammar FromString; 127 options { 128 language=Ruby; 129 output=AST; 130 } 131 @members { 132 class V < ANTLR3::CommonTree 133 def to_s 134 return @token.text + "<V>" 135 end 136 end 137 138 } 139 a : 'begin'<V> ; 140 ID : 'a'..'z'+ ; 141 WS : (' '|'\n') {$channel=HIDDEN;} ; 142 END 143 144 145 inline_grammar( <<-'END' ) 146 grammar StringRoot; 147 options { 148 language=Ruby; 149 output=AST; 150 } 151 @members { 152 class V < ANTLR3::CommonTree 153 def to_s 154 return @token.text + "<V>" 155 end 156 end 157 158 } 159 a : 'begin'<V>^ ; 160 ID : 'a'..'z'+ ; 161 WS : (' '|'\n') {$channel=HIDDEN;} ; 162 END 163 164 165 inline_grammar( <<-'END' ) 166 grammar RewriteToken; 167 options { 168 language=Ruby; 169 output=AST; 170 } 171 @members { 172 class V < ANTLR3::CommonTree 173 def to_s 174 return @token.text + "<V>" 175 end 176 end 177 178 } 179 a : ID -> ID<V> ; 180 ID : 'a'..'z'+ ; 181 WS : (' '|'\n') {$channel=HIDDEN;} ; 182 END 183 184 185 inline_grammar( <<-'END' ) 186 grammar RewriteTokenWithArgs; 187 options { 188 language=Ruby; 189 output=AST; 190 } 191 @members { 192 class V < ANTLR3::CommonTree 193 def initialize(*args) 194 case args.length 195 when 4 196 ttype, @x, @y, @z = args 197 token = ANTLR3::CommonToken.new(ttype, nil, '') 198 when 3 199 ttype, token, @x = args 200 @y = @z = 0 201 else raise ArgumentError, "invalid number of arguments: #{args.length} for 3-4" 202 end 203 super(token) 204 end 205 206 def to_s 207 (@token.text.to_s rescue '') << "<V>;\%d\%d\%d" \% [@x, @y, @z] 208 end 209 end 210 211 } 212 a : ID -> ID<V>[42,19,30] ID<V>[$ID,99]; 213 ID : 'a'..'z'+ ; 214 WS : (' '|'\n') {$channel=HIDDEN;} ; 215 END 216 217 218 inline_grammar( <<-'END' ) 219 grammar RewriteTokenRoot; 220 options { 221 language=Ruby; 222 output=AST; 223 } 224 @members { 225 class V < ANTLR3::CommonTree 226 def to_s 227 return @token.text + "<V>" 228 end 229 end 230 231 } 232 a : ID INT -> ^(ID<V> INT) ; 233 ID : 'a'..'z'+ ; 234 INT : '0'..'9'+ ; 235 WS : (' '|'\n') {$channel=HIDDEN;} ; 236 END 237 238 239 inline_grammar( <<-'END' ) 240 grammar RewriteString; 241 options { 242 language=Ruby; 243 output=AST; 244 } 245 @members { 246 class V < ANTLR3::CommonTree 247 def to_s 248 return @token.text + "<V>" 249 end 250 end 251 252 } 253 a : 'begin' -> 'begin'<V> ; 254 ID : 'a'..'z'+ ; 255 WS : (' '|'\n') {$channel=HIDDEN;} ; 256 END 257 258 259 inline_grammar( <<-'END' ) 260 grammar RewriteStringRoot; 261 options { 262 language=Ruby; 263 output=AST; 264 } 265 @members { 266 class V < ANTLR3::CommonTree 267 def to_s 268 return @token.text + "<V>" 269 end 270 end 271 272 } 273 a : 'begin' INT -> ^('begin'<V> INT) ; 274 ID : 'a'..'z'+ ; 275 INT : '0'..'9'+ ; 276 WS : (' '|'\n') {$channel=HIDDEN;} ; 277 END 278 279 280 inline_grammar( <<-'END' ) 281 grammar RewriteRuleResults; 282 options { 283 language=Ruby; 284 output=AST; 285 } 286 tokens {LIST;} 287 @members { 288 class V < ANTLR3::CommonTree 289 def to_s 290 return @token.text + "<V>" 291 end 292 end 293 class W < ANTLR3::CommonTree 294 def initialize(tok, text) 295 tok.text = text 296 super(tok) 297 end 298 def to_s 299 return @token.text + "<W>" 300 end 301 end 302 303 } 304 a : id (',' id)* -> ^(LIST<W>["LIST"] id+); 305 id : ID -> ID<V>; 306 ID : 'a'..'z'+ ; 307 WS : (' '|'\n') {$channel=HIDDEN;} ; 308 END 309 310 311 inline_grammar( <<-'END' ) 312 grammar CopySemanticsWithHetero; 313 options { 314 language=Ruby; 315 output=AST; 316 } 317 @members { 318 class V < ANTLR3::CommonTree 319 def dup_node 320 return V.new(self) 321 end 322 def to_s 323 return @token.text + "<V>" 324 end 325 end 326 } 327 a : type ID (',' ID)* ';' -> ^(type ID)+; 328 type : 'int'<V> ; 329 ID : 'a'..'z'+ ; 330 INT : '0'..'9'+; 331 WS : (' '|'\\n') {$channel=HIDDEN;} ; 332 END 333 334 335 inline_grammar( <<-'END' ) 336 grammar TreeParserRewriteFlatList; 337 options { 338 language=Ruby; 339 output=AST; 340 } 341 a : ID INT; 342 ID : 'a'..'z'+ ; 343 INT : '0'..'9'+; 344 WS : (' '|'\n') {$channel=HIDDEN;} ; 345 END 346 347 348 inline_grammar( <<-'END' ) 349 tree grammar TreeParserRewriteFlatListWalker; 350 options { 351 language=Ruby; 352 output=AST; 353 ASTLabelType=CommonTree; 354 tokenVocab=TreeParserRewriteFlatList; 355 } 356 @members { 357 class V < ANTLR3::CommonTree 358 def to_s 359 return @token.text + "<V>" 360 end 361 end 362 class W < ANTLR3::CommonTree 363 def to_s 364 return @token.text + "<W>" 365 end 366 end 367 } 368 a : ID INT -> INT<V> ID<W> 369 ; 370 END 371 372 373 inline_grammar( <<-'END' ) 374 grammar TreeParserRewriteTree; 375 options { 376 language=Ruby; 377 output=AST; 378 } 379 a : ID INT; 380 ID : 'a'..'z'+ ; 381 INT : '0'..'9'+; 382 WS : (' '|'\n') {$channel=HIDDEN;} ; 383 END 384 385 386 inline_grammar( <<-'END' ) 387 tree grammar TreeParserRewriteTreeWalker; 388 options { 389 language=Ruby; 390 output=AST; 391 ASTLabelType=CommonTree; 392 tokenVocab=TreeParserRewriteTree; 393 } 394 @members { 395 class V < ANTLR3::CommonTree 396 def to_s 397 return @token.text + "<V>" 398 end 399 end 400 401 class W < ANTLR3::CommonTree 402 def to_s 403 return @token.text + "<W>" 404 end 405 end 406 } 407 a : ID INT -> ^(INT<V> ID<W>) 408 ; 409 END 410 411 412 inline_grammar( <<-'END' ) 413 grammar TreeParserRewriteImaginary; 414 options { 415 language=Ruby; 416 output=AST; 417 } 418 a : ID ; 419 ID : 'a'..'z'+ ; 420 INT : '0'..'9'+; 421 WS : (' '|'\n') {$channel=HIDDEN;} ; 422 END 423 424 425 inline_grammar( <<-'END' ) 426 tree grammar TreeParserRewriteImaginaryWalker; 427 options { 428 language=Ruby; 429 output=AST; 430 ASTLabelType=CommonTree; 431 tokenVocab=TreeParserRewriteImaginary; 432 } 433 tokens { ROOT; } 434 @members { 435 class V < ANTLR3::CommonTree 436 def to_s 437 return @token.name + "<V>" 438 end 439 end 440 } 441 a : ID -> ROOT<V> ID 442 ; 443 END 444 445 446 inline_grammar( <<-'END' ) 447 grammar TreeParserRewriteImaginaryWithArgs; 448 options { 449 language=Ruby; 450 output=AST; 451 } 452 a : ID ; 453 ID : 'a'..'z'+ ; 454 INT : '0'..'9'+; 455 WS : (' '|'\n') {$channel=HIDDEN;} ; 456 END 457 458 459 inline_grammar( <<-'END' ) 460 tree grammar TreeParserRewriteImaginaryWithArgsWalker; 461 options { 462 language=Ruby; 463 output=AST; 464 ASTLabelType=CommonTree; 465 tokenVocab=TreeParserRewriteImaginaryWithArgs; 466 } 467 tokens { ROOT; } 468 @members { 469 class V < ANTLR3::CommonTree 470 def initialize(token_type, x) 471 super(token_type) 472 @x = x 473 end 474 def to_s 475 return @token.name + "<V>;#@x" 476 end 477 end 478 } 479 a : ID -> ROOT<V>[42] ID 480 ; 481 END 482 483 484 inline_grammar( <<-'END' ) 485 grammar TreeParserRewriteImaginaryRoot; 486 options { 487 language=Ruby; 488 output=AST; 489 } 490 a : ID ; 491 ID : 'a'..'z'+ ; 492 INT : '0'..'9'+; 493 WS : (' '|'\n') {$channel=HIDDEN;} ; 494 END 495 496 497 inline_grammar( <<-'END' ) 498 tree grammar TreeParserRewriteImaginaryRootWalker; 499 options { 500 language=Ruby; 501 output=AST; 502 ASTLabelType=CommonTree; 503 tokenVocab=TreeParserRewriteImaginaryRoot; 504 } 505 tokens { ROOT; } 506 @members { 507 class V < ANTLR3::CommonTree 508 def to_s 509 return @token.name + "<V>" 510 end 511 end 512 } 513 a : ID -> ^(ROOT<V> ID) 514 ; 515 END 516 517 518 inline_grammar( <<-'END' ) 519 grammar TreeParserRewriteImaginaryFromReal; 520 options { 521 language=Ruby; 522 output=AST; 523 } 524 a : ID ; 525 ID : 'a'..'z'+ ; 526 INT : '0'..'9'+; 527 WS : (' '|'\n') {$channel=HIDDEN;} ; 528 END 529 530 531 inline_grammar( <<-'END' ) 532 tree grammar TreeParserRewriteImaginaryFromRealWalker; 533 options { 534 language=Ruby; 535 output=AST; 536 ASTLabelType=CommonTree; 537 tokenVocab=TreeParserRewriteImaginaryFromReal; 538 } 539 tokens { ROOT; } 540 @members { 541 class V < ANTLR3::CommonTree 542 def initialize(token, tree = nil) 543 if tree.nil? then super(token) 544 else 545 super(tree) 546 @token = TokenData::Token.from_token(@token) 547 @token.type = token.type 548 end 549 end 550 def to_s 551 return @token.name + "<V>@" + @token.line.to_s 552 end 553 end 554 } 555 a : ID -> ROOT<V>[$ID] 556 ; 557 END 558 559 560 inline_grammar( <<-'END' ) 561 grammar TreeParserAutoHeteroAST; 562 options { 563 language=Ruby; 564 output=AST; 565 } 566 a : ID ';' ; 567 ID : 'a'..'z'+ ; 568 INT : '0'..'9'+; 569 WS : (' '|'\n') {$channel=HIDDEN;} ; 570 END 571 572 573 inline_grammar( <<-'END' ) 574 tree grammar TreeParserAutoHeteroASTWalker; 575 options { 576 language=Ruby; 577 output=AST; 578 ASTLabelType=CommonTree; 579 tokenVocab=TreeParserAutoHeteroAST; 580 } 581 tokens { ROOT; } 582 @members { 583 class V < ANTLR3::CommonTree 584 def to_s 585 return @token.text + "<V>" 586 end 587 end 588 } 589 590 a : ID<V> ';'<V>; 591 END 592 593 def parse( grammar_name, grammar_rule, input ) 594 grammar_module = self.class.const_get( grammar_name.to_s ) 595 lexer = grammar_module::Lexer.new( input ) 596 tokens = ANTLR3::CommonTokenStream.new( lexer ) 597 parser = grammar_module::Parser.new( tokens ) 598 r = parser.send( grammar_rule ) 599 600 return( r.tree.inspect rescue '' ) 601 end 602 603 def tree_parse( grammar_name, grammar_rule, tree_grammar_rule, input ) 604 grammar_module = self.class.const_get( grammar_name.to_s ) 605 tree_grammar_module = self.class.const_get( grammar_name.to_s + 'Walker' ) 606 607 lexer = grammar_module::Lexer.new( input ) 608 tokens = ANTLR3::CommonTokenStream.new( lexer ) 609 parser = grammar_module::Parser.new( tokens ) 610 r = parser.send( grammar_rule ) 611 612 nodes = ANTLR3::CommonTreeNodeStream.new( r.tree ) 613 nodes.token_stream = tokens 614 tree_parser = tree_grammar_module::TreeParser.new( nodes ) 615 r = tree_parser.send( tree_grammar_rule ) 616 617 return( r.tree.inspect rescue '' ) 618 end 619 620 example "v token" do 621 result = parse( :VToken, :a, 'a' ) 622 result.should == 'a<V>' 623 end 624 625 626 example "token with qualified type" do 627 result = parse( :TokenWithQualifiedType, :a, 'a' ) 628 result.should == 'a<V>' 629 end 630 631 632 example "token with label" do 633 result = parse( :TokenWithLabel, :a, 'a' ) 634 result.should == 'a<V>' 635 end 636 637 638 example "token with list label" do 639 result = parse( :TokenWithListLabel, :a, 'a' ) 640 result.should == 'a<V>' 641 end 642 643 644 example "token root" do 645 result = parse( :TokenRoot, :a, 'a' ) 646 result.should == 'a<V>' 647 end 648 649 650 example "token root with list label" do 651 result = parse( :TokenRootWithListLabel, :a, 'a' ) 652 result.should == 'a<V>' 653 end 654 655 656 example "string" do 657 result = parse( :FromString, :a, 'begin' ) 658 result.should == 'begin<V>' 659 end 660 661 662 example "string root" do 663 result = parse( :StringRoot, :a, 'begin' ) 664 result.should == 'begin<V>' 665 end 666 667 668 example "rewrite token" do 669 result = parse( :RewriteToken, :a, 'a' ) 670 result.should == 'a<V>' 671 end 672 673 674 example "rewrite token with args" do 675 result = parse( :RewriteTokenWithArgs, :a, 'a' ) 676 result.should == '<V>;421930 a<V>;9900' 677 end 678 679 680 example "rewrite token root" do 681 result = parse( :RewriteTokenRoot, :a, 'a 2' ) 682 result.should == '(a<V> 2)' 683 end 684 685 686 example "rewrite string" do 687 result = parse( :RewriteString, :a, 'begin' ) 688 result.should == 'begin<V>' 689 end 690 691 692 example "rewrite string root" do 693 result = parse( :RewriteStringRoot, :a, 'begin 2' ) 694 result.should == '(begin<V> 2)' 695 end 696 697 698 example "rewrite rule results" do 699 result = parse( :RewriteRuleResults, :a, 'a,b,c' ) 700 result.should == '(LIST<W> a<V> b<V> c<V>)' 701 end 702 703 704 example "copy semantics with hetero" do 705 result = parse( :CopySemanticsWithHetero, :a, 'int a, b, c;' ) 706 result.should == '(int<V> a) (int<V> b) (int<V> c)' 707 end 708 709 710 example "tree parser rewrite flat list" do 711 result = tree_parse( :TreeParserRewriteFlatList, :a, :a, 'abc 34' ) 712 result.should == '34<V> abc<W>' 713 end 714 715 716 example "tree parser rewrite tree" do 717 result = tree_parse( :TreeParserRewriteTree, :a, :a, 'abc 34' ) 718 result.should == '(34<V> abc<W>)' 719 end 720 721 722 example "tree parser rewrite imaginary" do 723 result = tree_parse( :TreeParserRewriteImaginary, :a, :a, 'abc' ) 724 result.should == 'ROOT<V> abc' 725 end 726 727 728 example "tree parser rewrite imaginary with args" do 729 result = tree_parse( :TreeParserRewriteImaginaryWithArgs, :a, :a, 'abc' ) 730 result.should == 'ROOT<V>;42 abc' 731 end 732 733 734 example "tree parser rewrite imaginary root" do 735 result = tree_parse( :TreeParserRewriteImaginaryRoot, :a, :a, 'abc' ) 736 result.should == '(ROOT<V> abc)' 737 end 738 739 740 example "tree parser rewrite imaginary from real" do 741 result = tree_parse( :TreeParserRewriteImaginaryFromReal, :a, :a, 'abc' ) 742 result.should == 'ROOT<V>@1' 743 end 744 745 746 example "tree parser auto hetero ast" do 747 result = tree_parse( :TreeParserAutoHeteroAST, :a, :a, 'abc;' ) 748 result.should == 'abc<V> ;<V>' 749 end 750 751end 752