1 /* 2 [The "BSD license"] 3 Copyright (c) 2005-2006 Terence Parr 4 Copyright (c) 2007-2008 Ronald Blaschke 5 All rights reserved. 6 7 Redistribution and use in source and binary forms, with or without 8 modification, are permitted provided that the following conditions 9 are met: 10 1. Redistributions of source code must retain the above copyright 11 notice, this list of conditions and the following disclaimer. 12 2. Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 3. The name of the author may not be used to endorse or promote products 16 derived from this software without specific prior written permission. 17 18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 group Perl5; 31 32 /** The overall file structure of a recognizer; stores methods for rules 33 * and cyclic DFAs plus support code. 34 */ 35 outputFile(LEXER,PARSER,TREE_PARSER, actionScope, actions, 36 docComment, recognizer, 37 name, tokens, tokenNames, rules, cyclicDFAs, 38 bitsets, buildTemplate, buildAST, rewriteMode, profile, 39 backtracking, synpreds, memoize, numRules, 40 fileName, ANTLRVersion, generatedTimestamp, trace, 41 scopes, superClass, literals) ::= 42 << 43 # $ANTLR <ANTLRVersion> <fileName> <generatedTimestamp> 44 <actions.(actionScope).header> 45 46 <@imports> 47 <if(TREE_PARSER)> 48 <endif> 49 <if(backtracking)> 50 <endif> 51 <@end> 52 53 <docComment> 54 <recognizer> 55 >> 56 57 lexer(grammar, name, tokens, scopes, rules, numRules, labelType="Token", 58 filterMode, superClass="ANTLR::Runtime::Lexer") ::= << 59 package <name>; 60 61 use Carp; 62 use English qw( -no_match_vars ) ; 63 use Readonly; 64 use Switch; 65 66 use ANTLR::Runtime::BaseRecognizer; 67 use ANTLR::Runtime::DFA; 68 use ANTLR::Runtime::NoViableAltException; 69 70 use Moose; 71 72 extends 'ANTLR::Runtime::Lexer'; 73 74 Readonly my $HIDDEN => ANTLR::Runtime::BaseRecognizer->HIDDEN; 75 sub HIDDEN { $HIDDEN } 76 77 use constant { 78 <tokens:{ <it.name> => <it.type>, }; separator="\n"> 79 }; 80 <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}> 81 <actions.lexer.members> 82 83 sub BUILD { 84 my ($self, $arg_ref) = @_; 85 86 $self->init_dfas(); 87 } 88 89 sub get_grammar_file_name { 90 return "<fileName>"; 91 } 92 93 <if(filterMode)> 94 <filteringNextToken()> 95 <endif> 96 <rules; separator="\n\n"> 97 98 <synpreds:{p | <lexerSynpred(p)>}> 99 100 <cyclicDFAs:{dfa | has 'dfa<dfa.decisionNumber>';}; separator="\n"> 101 102 sub init_dfas { 103 my ($self) = @_; 104 105 <cyclicDFAs:{dfa | 106 $self->dfa<dfa.decisionNumber>(<name>::DFA<dfa.decisionNumber>->new({ recognizer => $self })); 107 }; separator="\n"> 108 109 return; 110 } 111 112 <cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !> 113 114 no Moose; 115 __PACKAGE__->meta->make_immutable(); 116 1; 117 118 >> 119 120 perlTypeInitMap ::= [ 121 "$":"undef", 122 "@":"()", 123 "%":"()", 124 default:"undef" 125 ] 126 127 /** A override of Lexer.nextToken() that backtracks over mTokens() looking 128 * for matches. No error can be generated upon error; just rewind, consume 129 * a token and then try again. backtracking needs to be set as well. 130 * Make rule memoization happen only at levels above 1 as we start mTokens 131 * at backtracking==1. 132 */ 133 filteringNextToken() ::= << 134 public Token nextToken() { 135 while (true) { 136 if ( input.LA(1)==CharStream.EOF ) { 137 return Token.EOF_TOKEN; 138 } 139 token = null; 140 channel = Token.DEFAULT_CHANNEL; 141 tokenStartCharIndex = input.index(); 142 tokenStartCharPositionInLine = input.getCharPositionInLine(); 143 tokenStartLine = input.getLine(); 144 text = null; 145 try { 146 int m = input.mark(); 147 backtracking=1; <! means we won't throw slow exception !> 148 failed=false; 149 mTokens(); 150 backtracking=0; 151 <! mTokens backtracks with synpred at backtracking==2 152 and we set the synpredgate to allow actions at level 1. !> 153 if ( failed ) { 154 input.rewind(m); 155 input.consume(); <! advance one char and try again !> 156 } 157 else { 158 emit(); 159 return token; 160 } 161 } 162 catch (RecognitionException re) { 163 // shouldn't happen in backtracking mode, but... 164 reportError(re); 165 recover(re); 166 } 167 } 168 } 169 170 public void memoize(IntStream input, 171 int ruleIndex, 172 int ruleStartIndex) 173 { 174 if ( backtracking>1 ) super.memoize(input, ruleIndex, ruleStartIndex); 175 } 176 177 public boolean alreadyParsedRule(IntStream input, int ruleIndex) { 178 if ( backtracking>1 ) return super.alreadyParsedRule(input, ruleIndex); 179 return false; 180 } 181 >> 182 183 actionGate() ::= "$self->state->backtracking==0" 184 185 filteringActionGate() ::= "backtracking==1" 186 187 /** How to generate a parser */ 188 genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 189 bitsets, inputStreamType, superClass, filterMode, 190 ASTLabelType="Object", labelType, members) ::= << 191 package <name>; 192 193 use English qw( -no_match_vars ) ; 194 use Readonly; 195 use Switch; 196 use Carp; 197 use ANTLR::Runtime::BitSet; 198 199 use Moose; 200 201 extends '<@superClassName><superClass><@end>'; 202 203 Readonly my $token_names => [ 204 "\<invalid>", "\<EOR>", "\<DOWN>", "\<UP>", <tokenNames; separator=", "> 205 ]; 206 207 use constant { 208 <tokens:{ <it.name> => <it.type>, }; separator="\n"> 209 }; 210 211 <bitsets:bitset(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>}, 212 words64=it.bits)> 213 214 <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}> 215 <@members> 216 <! WARNING. bug in ST: this is cut-n-paste into Dbg.stg !> 217 218 sub BUILD { 219 my ($self, $arg_ref) = @_; 220 221 <if(backtracking)> 222 $self->state->rule_memo({});<\n> 223 <endif> 224 } 225 <@end> 226 227 sub get_token_names { 228 return $token_names; 229 } 230 231 sub get_grammar_file_name { 232 return "<fileName>"; 233 } 234 235 <members> 236 237 <rules; separator="\n\n"> 238 239 <synpreds:{p | <synpred(p)>}> 240 241 <cyclicDFAs:{dfa | dfa<dfa.decisionNumber> = __PACKAGE__::DFA<dfa.decisionNumber>->new($self);}; separator="\n"> 242 <cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !> 243 244 no Moose; 245 __PACKAGE__->meta->make_immutable(); 246 1; 247 __END__ 248 >> 249 250 parser(grammar, name, scopes, tokens, tokenNames, rules, numRules, bitsets, ASTLabelType, superClass="ANTLR::Runtime::Parser", labelType="ANTLR::Runtime::Token", members={<actions.parser.members>}) ::= << 251 <genericParser(inputStreamType="ANTLR::Runtime::TokenStream", ...)> 252 >> 253 254 /** How to generate a tree parser; same as parser except the input 255 * stream is a different type. 256 */ 257 treeParser(grammar, name, scopes, tokens, tokenNames, globalAction, rules, numRules, bitsets, labelType={<ASTLabelType>}, ASTLabelType="Object", superClass="ANTLR::Runtime::TreeParser", members={<actions.treeparser.members>}, filterMode) ::= << 258 <genericParser(inputStreamType="TreeNodeStream", ...)> 259 >> 260 261 /** A simpler version of a rule template that is specific to the imaginary 262 * rules created for syntactic predicates. As they never have return values 263 * nor parameters etc..., just give simplest possible method. Don't do 264 * any of the normal memoization stuff in here either; it's a waste. 265 * As predicates cannot be inlined into the invoking rule, they need to 266 * be in a rule by themselves. 267 */ 268 synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::= 269 << 270 # $ANTLR start <ruleName> 271 sub <ruleName>_fragment { 272 # <ruleDescriptor.parameterScope:parameterScope(scope=it)> 273 274 <if(trace)> 275 $self->traceIn("<ruleName>_fragment", <ruleDescriptor.index>); 276 eval { 277 <block> 278 }; 279 $self->traceOut("<ruleName>_fragment", <ruleDescriptor.index>); 280 if ($EVAL_ERROR) { 281 croak $EVAL_ERROR; 282 } 283 <else> 284 <block> 285 <endif> 286 } 287 # $ANTLR end <ruleName> 288 >> 289 290 synpred(name) ::= << 291 public final boolean <name>() { 292 backtracking++; 293 <@start()> 294 int start = input.mark(); 295 try { 296 <name>_fragment(); // can never throw exception 297 } catch (RecognitionException re) { 298 System.err.println("impossible: "+re); 299 } 300 boolean success = !failed; 301 input.rewind(start); 302 <@stop()> 303 backtracking--; 304 failed=false; 305 return success; 306 }<\n> 307 >> 308 309 lexerSynpred(name) ::= << 310 <synpred(name)> 311 >> 312 313 ruleMemoization(name) ::= << 314 <if(memoize)> 315 if ( backtracking>0 && alreadyParsedRule(input, <ruleDescriptor.index>) ) { return <ruleReturnValue()>; } 316 <endif> 317 >> 318 319 /** How to test for failure and return from rule */ 320 checkRuleBacktrackFailure() ::= << 321 <if(backtracking)> 322 if ($self->state->failed) { 323 return <ruleReturnValue()>; 324 } 325 <endif> 326 >> 327 328 /** This rule has failed, exit indicating failure during backtrack */ 329 ruleBacktrackFailure() ::= << 330 <if(backtracking)>if (backtracking>0) {failed=true; return <ruleReturnValue()>;}<endif> 331 >> 332 333 /** How to generate code for a rule. This includes any return type 334 * data aggregates required for multiple return values. 335 */ 336 rule(ruleName,ruleDescriptor,block,emptyRule,description,exceptions,finally,memoize) ::= << 337 <ruleAttributeScope(scope=ruleDescriptor.ruleScope)> 338 <returnScope(scope=ruleDescriptor.returnScope)> 339 340 # $ANTLR start <ruleName> 341 # <fileName>:<description> 342 sub <ruleName>() { 343 my ($self, <ruleDescriptor.parameterScope:parameterScope(scope=it)>) = @_; 344 <if(trace)>$self->traceIn("<ruleName>", <ruleDescriptor.index>);<endif> 345 <ruleScopeSetUp()> 346 <ruleDeclarations()> 347 <ruleLabelDefs()> 348 <ruleDescriptor.actions.init> 349 <@preamble()> 350 eval { 351 <ruleMemoization(name=ruleName)> 352 <block> 353 <ruleCleanUp()> 354 <(ruleDescriptor.actions.after):execAction()> 355 }; 356 <if(exceptions)> 357 <exceptions:{e|<catch(decl=e.decl,action=e.action)><\n>}> 358 <else> 359 <if(!emptyRule)> 360 <if(actions.(actionScope).rulecatch)> 361 <actions.(actionScope).rulecatch> 362 <else> 363 my $exception = $EVAL_ERROR; 364 if (ref $exception && $exception->isa('ANTLR::Runtime::RecognitionException')) { 365 $self->report_error($exception); 366 $self->recover($self->input, $exception); 367 $exception = undef; 368 }<\n> 369 <endif> 370 <endif> 371 <endif> 372 <if(trace)>$self->traceOut("<ruleName>", <ruleDescriptor.index>);<endif> 373 <memoize()> 374 <ruleScopeCleanUp()> 375 <finally> 376 if ($exception) { 377 croak $exception; 378 #$exception->rethrow(); 379 } 380 <@postamble()> 381 return <ruleReturnValue()>; 382 } 383 # $ANTLR end <ruleName> 384 >> 385 386 catch(decl,action) ::= << 387 catch (<e.decl>) { 388 <e.action> 389 } 390 >> 391 392 ruleDeclarations() ::= << 393 <if(ruleDescriptor.hasMultipleReturnValues)> 394 my $retval = <returnType()>->new(); 395 $retval->set_start($self->input->LT(1));<\n> 396 <else> 397 <ruleDescriptor.returnScope.attributes:{ a | 398 my $<a.name> = <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>; 399 }> 400 <endif> 401 <if(memoize)> 402 my $<ruleDescriptor.name>_start_index = $self->input->index(); 403 <endif> 404 >> 405 406 ruleScopeSetUp() ::= << 407 <ruleDescriptor.useScopes:{<it>_stack.push(new <it>_scope());}; separator="\n"> 408 <ruleDescriptor.ruleScope:{<it.name>_stack.push(new <it.name>_scope());}; separator="\n"> 409 >> 410 411 ruleScopeCleanUp() ::= << 412 <ruleDescriptor.useScopes:{<it>_stack.pop();}; separator="\n"> 413 <ruleDescriptor.ruleScope:{<it.name>_stack.pop();}; separator="\n"> 414 >> 415 416 ruleLabelDefs() ::= << 417 <[ruleDescriptor.tokenLabels,ruleDescriptor.tokenListLabels] 418 :{my $<it.label.text> = undef;}; separator="\n" 419 > 420 <[ruleDescriptor.tokenListLabels,ruleDescriptor.ruleListLabels] 421 :{List list_<it.label.text>=null;}; separator="\n" 422 > 423 <ruleDescriptor.ruleLabels:ruleLabelDef(label=it); separator="\n"> 424 <ruleDescriptor.ruleListLabels:{ll|RuleReturnScope <ll.label.text> = null;}; separator="\n"> 425 >> 426 427 lexerRuleLabelDefs() ::= << 428 <[ruleDescriptor.tokenLabels, 429 ruleDescriptor.tokenListLabels, 430 ruleDescriptor.ruleLabels] 431 :{<labelType> <it.label.text>=null;}; separator="\n" 432 > 433 <ruleDescriptor.charLabels:{my $<it.label.text>;}; separator="\n"> 434 <[ruleDescriptor.tokenListLabels, 435 ruleDescriptor.ruleListLabels, 436 ruleDescriptor.ruleListLabels] 437 :{List list_<it.label.text>=null;}; separator="\n" 438 > 439 >> 440 441 ruleReturnValue() ::= << 442 <if(!ruleDescriptor.isSynPred)> 443 <if(ruleDescriptor.hasReturnValue)> 444 <if(ruleDescriptor.hasSingleReturnValue)> 445 $<ruleDescriptor.singleValueReturnName> 446 <else> 447 $retval 448 <endif> 449 <endif> 450 <endif> 451 >> 452 453 ruleCleanUp() ::= << 454 <if(ruleDescriptor.hasMultipleReturnValues)> 455 <if(!TREE_PARSER)> 456 $retval->set_stop($self->input->LT(-1));<\n> 457 <endif> 458 <endif> 459 >> 460 461 memoize() ::= << 462 <if(memoize)> 463 <if(backtracking)> 464 if ( backtracking>0 ) { memoize(input, <ruleDescriptor.index>, <ruleDescriptor.name>_StartIndex); } 465 <endif> 466 <endif> 467 >> 468 469 /** How to generate a rule in the lexer; naked blocks are used for 470 * fragment rules. 471 */ 472 lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= << 473 # $ANTLR start <ruleName> 474 sub m_<ruleName> { 475 # <ruleDescriptor.parameterScope:parameterScope(scope=it)> 476 my ($self) = @_; 477 <if(trace)>traceIn("<ruleName>", <ruleDescriptor.index>);<endif> 478 <ruleDeclarations()> 479 eval { 480 <if(nakedBlock)> 481 <ruleMemoization(name=ruleName)> 482 <lexerRuleLabelDefs()> 483 <ruleDescriptor.actions.init> 484 <block><\n> 485 <else> 486 my $_type = <ruleName>; 487 my $_channel = $self->DEFAULT_TOKEN_CHANNEL; 488 <ruleMemoization(name=ruleName)> 489 <lexerRuleLabelDefs()> 490 <ruleDescriptor.actions.init> 491 <block> 492 <ruleCleanUp()> 493 $self->state->type($_type); 494 $self->state->channel($_channel); 495 <(ruleDescriptor.actions.after):execAction()> 496 <endif> 497 }; 498 <if(trace)>traceOut("<ruleName>", <ruleDescriptor.index>);<endif> 499 <memoize()> 500 501 if ($EVAL_ERROR) { 502 croak $EVAL_ERROR; 503 } 504 } 505 # $ANTLR end <ruleName> 506 >> 507 508 /** How to generate code for the implicitly-defined lexer grammar rule 509 * that chooses between lexer rules. 510 */ 511 tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= << 512 sub m_tokens { 513 my ($self) = @_; 514 <block><\n> 515 } 516 >> 517 518 // S U B R U L E S 519 520 /** A (...) subrule with multiple alternatives */ 521 block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 522 # <fileName>:<description> 523 my $alt<decisionNumber> = <maxAlt>; 524 <decls> 525 <@predecision()> 526 <decision> 527 <@postdecision()> 528 <@prebranch()> 529 switch ($alt<decisionNumber>) { 530 <alts:altSwitchCase()> 531 } 532 <@postbranch()> 533 >> 534 535 /** A rule block with multiple alternatives */ 536 ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 537 # <fileName>:<description> 538 my $alt<decisionNumber> = <maxAlt>; 539 <decls> 540 <@predecision()> 541 <decision> 542 <@postdecision()> 543 switch ($alt<decisionNumber>) { 544 <alts:altSwitchCase()> 545 } 546 >> 547 548 ruleBlockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= << 549 # <fileName>:<description> 550 <decls> 551 <@prealt()> 552 <alts> 553 <@postalt()> 554 >> 555 556 /** A special case of a (...) subrule with a single alternative */ 557 blockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= << 558 # <fileName>:<description> 559 <decls> 560 <@prealt()> 561 <alts> 562 <@postalt()> 563 >> 564 565 /** A (..)+ block with 1 or more alternatives */ 566 positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 567 # <fileName>:<description> 568 my $cnt<decisionNumber> = 0; 569 <decls> 570 <@preloop()> 571 LOOP<decisionNumber>: 572 while (1) { 573 my $alt<decisionNumber> = <maxAlt>; 574 <@predecision()> 575 <decision> 576 <@postdecision()> 577 switch ($alt<decisionNumber>) { 578 <alts:altSwitchCase()> 579 else { 580 if ( $cnt<decisionNumber> >= 1 ) { last LOOP<decisionNumber> } 581 <ruleBacktrackFailure()> 582 my $eee = 583 ANTLR::Runtime::EarlyExitException->new(<decisionNumber>, $self->input); 584 <@earlyExitException()> 585 croak $eee; 586 } 587 } 588 ++$cnt<decisionNumber>; 589 } 590 <@postloop()> 591 >> 592 593 positiveClosureBlockSingleAlt ::= positiveClosureBlock 594 595 /** A (..)* block with 1 or more alternatives */ 596 closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 597 # <fileName>:<description> 598 <decls> 599 <@preloop()> 600 LOOP<decisionNumber>: 601 while (1) { 602 my $alt<decisionNumber> = <maxAlt>; 603 <@predecision()> 604 <decision> 605 <@postdecision()> 606 switch ($alt<decisionNumber>) { 607 <alts:altSwitchCase()> 608 else { last LOOP<decisionNumber> } 609 } 610 } 611 <@postloop()> 612 >> 613 614 closureBlockSingleAlt ::= closureBlock 615 616 /** Optional blocks (x)? are translated to (x|) by before code generation 617 * so we can just use the normal block template 618 */ 619 optionalBlock ::= block 620 621 optionalBlockSingleAlt ::= block 622 623 /** A case in a switch that jumps to an alternative given the alternative 624 * number. A DFA predicts the alternative and then a simple switch 625 * does the jump to the code that actually matches that alternative. 626 */ 627 altSwitchCase() ::= << 628 case <i> { 629 <@prealt()> 630 <it> 631 }<\n> 632 >> 633 634 /** An alternative is just a list of elements; at outermost level */ 635 alt(elements,altNum,description,autoAST,outerAlt,treeLevel,rew) ::= << 636 # <fileName>:<description> 637 { 638 <@declarations()> 639 <elements:element()> 640 <rew> 641 <@cleanup()> 642 } 643 >> 644 645 /** What to emit when there is no rewrite. For auto build 646 * mode, does nothing. 647 */ 648 noRewrite(rewriteBlockLevel, treeLevel) ::= "" 649 650 // E L E M E N T S 651 652 /** Dump the elements one per line */ 653 element() ::= << 654 <@prematch()> 655 <it.el><\n> 656 >> 657 658 /** match a token optionally with a label in front */ 659 tokenRef(token,label,elementIndex,terminalOptions) ::= << 660 <if(label)>$<label> =<endif>$self->match($self->input, <token>, $FOLLOW_<token>_in_<ruleName><elementIndex>); 661 <checkRuleBacktrackFailure()> 662 >> 663 664 /** ids+=ID */ 665 tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 666 <tokenRef(...)> 667 <listLabel(elem=label,...)> 668 >> 669 670 listLabel(label,elem) ::= << 671 if (list_<label>==null) list_<label>=new ArrayList(); 672 list_<label>.add(<elem>);<\n> 673 >> 674 675 /** match a character */ 676 charRef(char,label) ::= << 677 <if(label)> 678 <label> = $self->input->LA(1);<\n> 679 <endif> 680 $self->match(<char>); <checkRuleBacktrackFailure()> 681 >> 682 683 /** match a character range */ 684 charRangeRef(a,b,label) ::= << 685 <if(label)> 686 <label> = $self->input->LA(1);<\n> 687 <endif> 688 $self->match_range(<a>,<b>); <checkRuleBacktrackFailure()> 689 >> 690 691 /** For now, sets are interval tests and must be tested inline */ 692 matchSet(s,label,elementIndex,postmatchCode="") ::= << 693 <if(label)> 694 <if(LEXER)> 695 <label>= $self->input->LA(1);<\n> 696 <else> 697 <label>=(<labelType>)input.LT(1);<\n> 698 <endif> 699 <endif> 700 if ( <s> ) { 701 $self->input->consume(); 702 <postmatchCode> 703 <if(!LEXER)> 704 $self->state->error_recovery(0); 705 <endif> 706 <if(backtracking)>failed=false;<endif> 707 } 708 else { 709 <ruleBacktrackFailure()> 710 my $mse = 711 ANTLR::Runtime::MismatchedSetException->new(undef, $self->input); 712 <@mismatchedSetException()> 713 <if(LEXER)> 714 $self->recover($mse); 715 $mse->throw(); 716 <else> 717 $mse->throw(); 718 <! use following code to make it recover inline; remove throw mse; 719 $self->recoverFromMismatchedSet($self->input, $mse, $FOLLOW_set_in_<ruleName><elementIndex>); 720 !> 721 <endif> 722 }<\n> 723 >> 724 725 matchRuleBlockSet ::= matchSet 726 727 matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= << 728 <matchSet(...)> 729 <listLabel(elem=label,...)> 730 >> 731 732 /** Match a string literal */ 733 lexerStringRef(string,label,elementIndex) ::= << 734 <if(label)> 735 int <label>Start = getCharIndex(); 736 $self->match(<string>); <checkRuleBacktrackFailure()> 737 <labelType> <label> = new CommonToken(input, Token.INVALID_TOKEN_TYPE, Token.DEFAULT_CHANNEL, <label>Start, getCharIndex()-1); 738 <else> 739 $self->match(<string>); <checkRuleBacktrackFailure()><\n> 740 <endif> 741 >> 742 743 wildcard(label,elementIndex) ::= << 744 <if(label)> 745 <label>=(<labelType>)input.LT(1);<\n> 746 <endif> 747 matchAny(input); <checkRuleBacktrackFailure()> 748 >> 749 750 wildcardAndListLabel(label,elementIndex) ::= << 751 <wildcard(...)> 752 <listLabel(elem=label,...)> 753 >> 754 755 /** Match . wildcard in lexer */ 756 wildcardChar(label, elementIndex) ::= << 757 <if(label)> 758 <label> = $self->input->LA(1);<\n> 759 <endif> 760 matchAny(); <checkRuleBacktrackFailure()> 761 >> 762 763 wildcardCharListLabel(label, elementIndex) ::= << 764 <wildcardChar(...)> 765 <listLabel(elem=label,...)> 766 >> 767 768 /** Match a rule reference by invoking it possibly with arguments 769 * and a return value or values. 770 */ 771 ruleRef(rule,label,elementIndex,args,scope) ::= << 772 $self->push_follow($FOLLOW_<rule.name>_in_<ruleName><elementIndex>); 773 <if(label)> 774 $<label> = $self-><rule.name>(<args; separator=", ">);<\n> 775 <else> 776 $self-><rule.name>(<args; separator=", ">);<\n> 777 <endif> 778 $self->state->_fsp($self->state->_fsp - 1); 779 <checkRuleBacktrackFailure()> 780 >> 781 782 /** ids+=r */ 783 ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= << 784 <ruleRef(...)> 785 <listLabel(elem=label,...)> 786 >> 787 788 /** A lexer rule reference. 789 * 790 * The 'rule' argument was the target rule name, but now 791 * is type Rule, whose toString is same: the rule name. 792 * Now though you can access full rule descriptor stuff. 793 */ 794 lexerRuleRef(rule,label,args,elementIndex,scope) ::= << 795 <if(label)> 796 int <label>Start<elementIndex> = getCharIndex(); 797 $self->m_<rule>(<args; separator=", ">); <checkRuleBacktrackFailure()> 798 <label> = new CommonToken(input, Token.INVALID_TOKEN_TYPE, Token.DEFAULT_CHANNEL, <label>Start<elementIndex>, getCharIndex()-1); 799 <else> 800 $self->m_<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()> 801 <endif> 802 >> 803 804 /** i+=INT in lexer */ 805 lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= << 806 <lexerRuleRef(...)> 807 <listLabel(elem=label,...)> 808 >> 809 810 /** EOF in the lexer */ 811 lexerMatchEOF(label,elementIndex) ::= << 812 <if(label)> 813 int <label>Start<elementIndex> = getCharIndex(); 814 match(EOF); <checkRuleBacktrackFailure()> 815 <labelType> <label> = new CommonToken(input, EOF, Token.DEFAULT_CHANNEL, <label>Start<elementIndex>, getCharIndex()-1); 816 <else> 817 match(EOF); <checkRuleBacktrackFailure()> 818 <endif> 819 >> 820 821 /** match ^(root children) in tree parser */ 822 tree(root, actionsAfterRoot, children, nullableChildList, 823 enclosingTreeLevel, treeLevel) ::= << 824 <root:element()> 825 <actionsAfterRoot:element()> 826 <if(nullableChildList)> 827 if ( input.LA(1)==Token.DOWN ) { 828 match(input, Token.DOWN, null); <checkRuleBacktrackFailure()> 829 <children:element()> 830 match(input, Token.UP, null); <checkRuleBacktrackFailure()> 831 } 832 <else> 833 match(input, Token.DOWN, null); <checkRuleBacktrackFailure()> 834 <children:element()> 835 match(input, Token.UP, null); <checkRuleBacktrackFailure()> 836 <endif> 837 >> 838 839 /** Every predicate is used as a validating predicate (even when it is 840 * also hoisted into a prediction expression). 841 */ 842 validateSemanticPredicate(pred,description) ::= << 843 if ( !(<evalPredicate(...)>) ) { 844 <ruleBacktrackFailure()> 845 throw new FailedPredicateException(input, "<ruleName>", "<description>"); 846 } 847 >> 848 849 // F i x e d D F A (if-then-else) 850 851 dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 852 my $LA<decisionNumber>_<stateNumber> = $self->input->LA(<k>);<\n> 853 <edges; separator="\nels"> 854 else { 855 <if(eotPredictsAlt)> 856 $alt<decisionNumber> = <eotPredictsAlt>; 857 <else> 858 <ruleBacktrackFailure()> 859 my $nvae = 860 ANTLR::Runtime::NoViableAltException->new({ 861 grammar_decision_description => "<description>", 862 decision_number => <decisionNumber>, 863 state_number => <stateNumber>, 864 input => $self->input, 865 });<\n> 866 <@noViableAltException()> 867 croak $nvae;<\n> 868 <endif> 869 } 870 >> 871 872 /** Same as a normal DFA state except that we don't examine lookahead 873 * for the bypass alternative. It delays error detection but this 874 * is faster, smaller, and more what people expect. For (X)? people 875 * expect "if ( LA(1)==X ) match(X);" and that's it. 876 */ 877 dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 878 my $LA<decisionNumber>_<stateNumber> = $self->input->LA(<k>);<\n> 879 <edges; separator="\nels"> 880 >> 881 882 /** A DFA state that is actually the loopback decision of a closure 883 * loop. If end-of-token (EOT) predicts any of the targets then it 884 * should act like a default clause (i.e., no error can be generated). 885 * This is used only in the lexer so that for ('a')* on the end of a rule 886 * anything other than 'a' predicts exiting. 887 */ 888 dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 889 my $LA<decisionNumber>_<stateNumber> = $self->input->LA(<k>);<\n> 890 <edges; separator="\nels"><\n> 891 <if(eotPredictsAlt)> 892 <if(!edges)> 893 $alt<decisionNumber> = <eotPredictsAlt>; <! if no edges, don't gen ELSE !> 894 <else> 895 else { 896 $alt<decisionNumber> = <eotPredictsAlt>; 897 }<\n> 898 <endif> 899 <endif> 900 >> 901 902 /** An accept state indicates a unique alternative has been predicted */ 903 dfaAcceptState(alt) ::= "$alt<decisionNumber> = <alt>;" 904 905 /** A simple edge with an expression. If the expression is satisfied, 906 * enter to the target state. To handle gated productions, we may 907 * have to evaluate some predicates for this edge. 908 */ 909 dfaEdge(labelExpr, targetState, predicates) ::= << 910 if ( (<labelExpr>) <if(predicates)>&& (<predicates>)<endif>) { 911 <targetState> 912 } 913 >> 914 915 // F i x e d D F A (switch case) 916 917 /** A DFA state where a SWITCH may be generated. The code generator 918 * decides if this is possible: CodeGenerator.canGenerateSwitch(). 919 */ 920 dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 921 switch ( $self->input->LA(<k>) ) { 922 <edges; separator="\n"> 923 else { 924 <if(eotPredictsAlt)> 925 $alt<decisionNumber> = <eotPredictsAlt>; 926 <else> 927 <ruleBacktrackFailure()> 928 my $nvae = 929 ANTLR::Runtime::NoViableAltException->new({ 930 grammar_decision_description => "<description>", 931 decision_number => <decisionNumber>, 932 state_number => <stateNumber>, 933 input => $self->input, 934 });<\n> 935 <@noViableAltException()> 936 croak $nvae;<\n> 937 <endif> 938 } 939 }<\n> 940 >> 941 942 dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 943 switch ( $self->input->LA(<k>) ) { 944 <edges; separator="\n"> 945 }<\n> 946 >> 947 948 dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 949 switch ( $self->input->LA(<k>) ) { 950 <edges; separator="\n"><\n> 951 <if(eotPredictsAlt)> 952 else { $alt<decisionNumber> = <eotPredictsAlt> }<\n> 953 <endif> 954 }<\n> 955 >> 956 957 dfaEdgeSwitch(labels, targetState) ::= << 958 case [<labels:{ <it> }; separator=", ">] { <targetState> } 959 >> 960 961 // C y c l i c D F A 962 963 /** The code to initiate execution of a cyclic DFA; this is used 964 * in the rule to predict an alt just like the fixed DFA case. 965 * The <name> attribute is inherited via the parser, lexer, ... 966 */ 967 dfaDecision(decisionNumber,description) ::= << 968 $alt<decisionNumber> = $self->dfa<decisionNumber>->predict($self->input); 969 >> 970 971 /* Dump DFA tables as run-length-encoded Strings of octal values. 972 * Can't use hex as compiler translates them before compilation. 973 * These strings are split into multiple, concatenated strings. 974 * Java puts them back together at compile time thankfully. 975 * Java cannot handle large static arrays, so we're stuck with this 976 * encode/decode approach. See analysis and runtime DFA for 977 * the encoding methods. 978 */ 979 cyclicDFA(dfa) ::= << 980 Readonly my $DFA<dfa.decisionNumber>_eot => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedEOT; separator=", "> ]); 981 Readonly my $DFA<dfa.decisionNumber>_eof => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedEOF; separator=", "> ]); 982 Readonly my $DFA<dfa.decisionNumber>_min => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedMin; separator=", "> ]); 983 Readonly my $DFA<dfa.decisionNumber>_max => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedMax; separator=", "> ]); 984 Readonly my $DFA<dfa.decisionNumber>_accept => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedAccept; separator=", "> ]); 985 Readonly my $DFA<dfa.decisionNumber>_special => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedSpecial; separator=", "> ]); 986 Readonly my $DFA<dfa.decisionNumber>_transition => [ <dfa.javaCompressedTransition:{s|ANTLR::Runtime::DFA->unpack_rle([ <s; separator=", "> ])}; separator=", "> ]; 987 988 { 989 package <name>::DFA<dfa.decisionNumber>; 990 use ANTLR::Runtime::Class; 991 992 use strict; 993 use warnings; 994 995 extends 'ANTLR::Runtime::DFA'; 996 997 sub BUILD { 998 my $self = shift; 999 my $param_ref = __PACKAGE__->unpack_params(@_, { 1000 spec => [ 1001 { 1002 name => 'recognizer', 1003 isa => 'ANTLR::Runtime::BaseRecognizer' 1004 }, 1005 ] 1006 }); 1007 1008 $self->recognizer($param_ref->{recognizer}); 1009 $self->decision_number(<dfa.decisionNumber>); 1010 $self->eot($DFA<dfa.decisionNumber>_eot); 1011 $self->eof($DFA<dfa.decisionNumber>_eof); 1012 $self->min($DFA<dfa.decisionNumber>_min); 1013 $self->max($DFA<dfa.decisionNumber>_max); 1014 $self->accept($DFA<dfa.decisionNumber>_accept); 1015 $self->special($DFA<dfa.decisionNumber>_special); 1016 $self->transition($DFA<dfa.decisionNumber>_transition); 1017 } 1018 1019 sub get_description { 1020 return "<dfa.description>"; 1021 } 1022 1023 <@errorMethod()> 1024 1025 <if(dfa.specialStateSTs)> 1026 sub special_state_transition { 1027 my ($self, $param_ref) = unpack_params(@_, { 1028 spec => [ 1029 { 1030 name => 's', 1031 type => SCALAR, 1032 }, 1033 { 1034 name => 'input', 1035 isa => 'ANTLR::Runtime::IntStream', 1036 } 1037 ] 1038 }); 1039 my $s = $param_ref->{s}; 1040 my $input = $param_ref->{input}; 1041 1042 switch ($s) { 1043 <dfa.specialStateSTs:{state | 1044 case <i0> \{ <! compressed special state numbers 0..n-1 !> 1045 <state>}; separator="\n"> 1046 } 1047 } 1048 1049 <if(backtracking)> 1050 if ($self->state->backtracking > 0) { 1051 $self->state->failed = 1; 1052 return -1; 1053 }<\n> 1054 <endif> 1055 1056 my $nvae = 1057 ANTLR::Runtime::NoViableAltException->new({ 1058 grammar_decision_description => $self->get_description(), 1059 decision_number => <dfa.decisionNumber>, 1060 state_number => $s, 1061 input => $input, 1062 });<\n> 1063 $self->error($nvae); 1064 $nvae->throw(); 1065 }<\n> 1066 <endif> 1067 }<\n> 1068 >> 1069 1070 /** A state in a cyclic DFA; it's a special state and part of a big switch on 1071 * state. 1072 */ 1073 cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= << 1074 my $input = $self->input; 1075 my $LA<decisionNumber>_<stateNumber> = $input->LA(1);<\n> 1076 <if(semPredState)> <! get next lookahead symbol to test edges, then rewind !> 1077 my $index<decisionNumber>_<stateNumber> = $input->index(); 1078 $input->rewind();<\n> 1079 <endif> 1080 s = -1; 1081 <edges; separator="\nels"> 1082 <if(semPredState)> <! return input cursor to state before we rewound !> 1083 input.seek(index<decisionNumber>_<stateNumber>);<\n> 1084 <endif> 1085 if ( s>=0 ) return s; 1086 break; 1087 >> 1088 1089 /** Just like a fixed DFA edge, test the lookahead and indicate what 1090 * state to jump to next if successful. 1091 */ 1092 cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= << 1093 if ( (<labelExpr>) <if(predicates)>&& (<predicates>)<endif>) {s = <targetStateNumber>;}<\n> 1094 >> 1095 1096 /** An edge pointing at end-of-token; essentially matches any char; 1097 * always jump to the target. 1098 */ 1099 eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= << 1100 s = <targetStateNumber>;<\n> 1101 >> 1102 1103 1104 // D F A E X P R E S S I O N S 1105 1106 andPredicates(left,right) ::= "(<left> && <right>)" 1107 1108 orPredicates(operands) ::= "(<first(operands)><rest(operands):{o | ||<o>}>)" 1109 1110 notPredicate(pred) ::= "!(<evalPredicate(...)>)" 1111 1112 evalPredicate(pred,description) ::= "<pred>" 1113 1114 evalSynPredicate(pred,description) ::= "<pred>()" 1115 1116 lookaheadTest(atom,k,atomAsInt) ::= "$LA<decisionNumber>_<stateNumber> eq <atom>" 1117 1118 /** Sometimes a lookahead test cannot assume that LA(k) is in a temp variable 1119 * somewhere. Must ask for the lookahead directly. 1120 */ 1121 isolatedLookaheadTest(atom,k,atomAsInt) ::= "$self->input->LA(<k>) eq <atom>" 1122 1123 lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= << 1124 ($LA<decisionNumber>_<stateNumber> ge <lower> && $LA<decisionNumber>_<stateNumber> le <upper>) 1125 >> 1126 1127 isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "($self->input->LA(<k>) ge <lower> && $self->input->LA(<k>) le <upper>)" 1128 1129 setTest(ranges) ::= "<ranges; separator=\" || \">" 1130 1131 // A T T R I B U T E S 1132 1133 globalAttributeScope(scope) ::= << 1134 <if(scope.attributes)> 1135 protected static class <scope.name>_scope { 1136 <scope.attributes:{<it.decl>;}; separator="\n"> 1137 } 1138 protected Stack <scope.name>_stack = new Stack();<\n> 1139 <endif> 1140 >> 1141 1142 ruleAttributeScope(scope) ::= << 1143 <if(scope.attributes)> 1144 protected static class <scope.name>_scope { 1145 <scope.attributes:{<it.decl>;}; separator="\n"> 1146 } 1147 protected Stack <scope.name>_stack = new Stack();<\n> 1148 <endif> 1149 >> 1150 1151 returnType() ::= << 1152 <if(ruleDescriptor.hasMultipleReturnValues)> 1153 <ruleDescriptor.name>_return 1154 <else> 1155 <if(ruleDescriptor.hasSingleReturnValue)> 1156 <ruleDescriptor.singleValueReturnType> 1157 <else> 1158 void 1159 <endif> 1160 <endif> 1161 >> 1162 1163 /** Generate the Java type associated with a single or multiple return 1164 * values. 1165 */ 1166 ruleLabelType(referencedRule) ::= << 1167 <if(referencedRule.hasMultipleReturnValues)> 1168 <referencedRule.name>_return 1169 <else> 1170 <if(referencedRule.hasSingleReturnValue)> 1171 <referencedRule.singleValueReturnType> 1172 <else> 1173 void 1174 <endif> 1175 <endif> 1176 >> 1177 1178 /** Using a type to init value map, try to init a type; if not in table 1179 * must be an object, default value is "undef". 1180 */ 1181 initValue(typeName) ::= << 1182 <if(typeName)> 1183 <perlTypeInitMap.(typeName)> 1184 <else> 1185 undef 1186 <endif> 1187 >> 1188 1189 /** Define a rule label including default value */ 1190 ruleLabelDef(label) ::= << 1191 my $<label.label.text> = <initValue(typeName=ruleLabelType(referencedRule=label.referencedRule))>;<\n> 1192 >> 1193 1194 /** Define a return struct for a rule if the code needs to access its 1195 * start/stop tokens, tree stuff, attributes, ... Leave a hole for 1196 * subgroups to stick in members. 1197 */ 1198 returnScope(scope) ::= << 1199 <if(ruleDescriptor.hasMultipleReturnValues)> 1200 { 1201 package <returnType()>; 1202 use ANTLR::Runtime::Class; 1203 1204 extends 'ANTLR::Runtime::<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope'; 1205 1206 <scope.attributes:{public <it.decl>;}; separator="\n"> 1207 <@ruleReturnMembers()> 1208 } 1209 <endif> 1210 >> 1211 1212 parameterScope(scope) ::= << 1213 <scope.attributes:{$<it.name>}; separator=", "> 1214 >> 1215 1216 parameterAttributeRef(attr) ::= "$<attr.name>" 1217 parameterSetAttributeRef(attr,expr) ::= "$<attr.name> =<expr>;" 1218 1219 scopeAttributeRef(scope,attr,index,negIndex) ::= << 1220 <if(negIndex)> 1221 ((<scope>_scope)<scope>_stack.elementAt(<scope>_stack.size()-<negIndex>-1)).<attr.name> 1222 <else> 1223 <if(index)> 1224 ((<scope>_scope)<scope>_stack.elementAt(<index>)).<attr.name> 1225 <else> 1226 ((<scope>_scope)<scope>_stack.peek()).<attr.name> 1227 <endif> 1228 <endif> 1229 >> 1230 1231 scopeSetAttributeRef(scope,attr,expr,index,negIndex) ::= << 1232 <if(negIndex)> 1233 ((<scope>_scope)<scope>_stack.elementAt(<scope>_stack.size()-<negIndex>-1)).<attr.name> =<expr>; 1234 <else> 1235 <if(index)> 1236 ((<scope>_scope)<scope>_stack.elementAt(<index>)).<attr.name> =<expr>; 1237 <else> 1238 ((<scope>_scope)<scope>_stack.peek()).<attr.name> =<expr>; 1239 <endif> 1240 <endif> 1241 >> 1242 1243 /** $x is either global scope or x is rule with dynamic scope; refers 1244 * to stack itself not top of stack. This is useful for predicates 1245 * like {$function.size()>0 && $function::name.equals("foo")}? 1246 */ 1247 isolatedDynamicScopeRef(scope) ::= "<scope>_stack" 1248 1249 /** reference an attribute of rule; might only have single return value */ 1250 ruleLabelRef(referencedRule,scope,attr) ::= << 1251 <if(referencedRule.hasMultipleReturnValues)> 1252 $<scope>.<attr.name> 1253 <else> 1254 $<scope> 1255 <endif> 1256 >> 1257 1258 returnAttributeRef(ruleDescriptor,attr) ::= << 1259 <if(ruleDescriptor.hasMultipleReturnValues)> 1260 retval.<attr.name> 1261 <else> 1262 $<attr.name> 1263 <endif> 1264 >> 1265 1266 returnSetAttributeRef(ruleDescriptor,attr,expr) ::= << 1267 <if(ruleDescriptor.hasMultipleReturnValues)> 1268 retval.<attr.name> =<expr>; 1269 <else> 1270 $<attr.name> =<expr>; 1271 <endif> 1272 >> 1273 1274 /** How to translate $tokenLabel */ 1275 tokenLabelRef(label) ::= "$<label>" 1276 1277 /** ids+=ID {$ids} or e+=expr {$e} */ 1278 listLabelRef(label) ::= "list_<label>" 1279 1280 1281 // not sure the next are the right approach 1282 1283 tokenLabelPropertyRef_text(scope,attr) ::= "$<scope>->get_text()" 1284 tokenLabelPropertyRef_type(scope,attr) ::= "<scope>.getType()" 1285 tokenLabelPropertyRef_line(scope,attr) ::= "<scope>.getLine()" 1286 tokenLabelPropertyRef_pos(scope,attr) ::= "<scope>.getCharPositionInLine()" 1287 tokenLabelPropertyRef_channel(scope,attr) ::= "<scope>.getChannel()" 1288 tokenLabelPropertyRef_index(scope,attr) ::= "<scope>.getTokenIndex()" 1289 tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree" 1290 1291 ruleLabelPropertyRef_start(scope,attr) ::= "((<labelType>)<scope>.start)" 1292 ruleLabelPropertyRef_stop(scope,attr) ::= "((<labelType>)<scope>.stop)" 1293 ruleLabelPropertyRef_tree(scope,attr) ::= "((<ASTLabelType>)<scope>.tree)" 1294 ruleLabelPropertyRef_text(scope,attr) ::= << 1295 <if(TREE_PARSER)> 1296 input.getTokenStream().toString( 1297 input.getTreeAdaptor().getTokenStartIndex(<scope>.start), 1298 input.getTreeAdaptor().getTokenStopIndex(<scope>.start)) 1299 <else> 1300 substr($self->input, $<scope>->start, $<scope>->stop) 1301 <endif> 1302 >> 1303 1304 ruleLabelPropertyRef_st(scope,attr) ::= "<scope>.st" 1305 1306 /** Isolated $RULE ref ok in lexer as it's a Token */ 1307 lexerRuleLabel(label) ::= "$<label>" 1308 1309 lexerRuleLabelPropertyRef_type(scope,attr) ::= "<scope>.getType()" 1310 lexerRuleLabelPropertyRef_line(scope,attr) ::= "<scope>.getLine()" 1311 lexerRuleLabelPropertyRef_pos(scope,attr) ::= "<scope>.getCharPositionInLine()" 1312 lexerRuleLabelPropertyRef_channel(scope,attr) ::= "<scope>.getChannel()" 1313 lexerRuleLabelPropertyRef_index(scope,attr) ::= "<scope>.getTokenIndex()" 1314 lexerRuleLabelPropertyRef_text(scope,attr) ::= "<scope>.getText()" 1315 1316 // Somebody may ref $template or $tree or $stop within a rule: 1317 rulePropertyRef_start(scope,attr) ::= "((<labelType>)retval.start)" 1318 rulePropertyRef_stop(scope,attr) ::= "((<labelType>)retval.stop)" 1319 rulePropertyRef_tree(scope,attr) ::= "((<ASTLabelType>)retval.tree)" 1320 rulePropertyRef_text(scope,attr) ::= << 1321 <if(TREE_PARSER)> 1322 input.getTokenStream().toString( 1323 input.getTreeAdaptor().getTokenStartIndex(retval.start), 1324 input.getTreeAdaptor().getTokenStopIndex(retval.start)) 1325 <else> 1326 input.toString(retval.start,input.LT(-1)) 1327 <endif> 1328 >> 1329 rulePropertyRef_st(scope,attr) ::= "retval.st" 1330 1331 lexerRulePropertyRef_text(scope,attr) ::= "getText()" 1332 lexerRulePropertyRef_type(scope,attr) ::= "$_type" 1333 lexerRulePropertyRef_line(scope,attr) ::= "tokenStartLine" 1334 lexerRulePropertyRef_pos(scope,attr) ::= "tokenStartCharPositionInLine" 1335 lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer 1336 lexerRulePropertyRef_channel(scope,attr) ::= "$_channel" 1337 lexerRulePropertyRef_start(scope,attr) ::= "tokenStartCharIndex" 1338 lexerRulePropertyRef_stop(scope,attr) ::= "(getCharIndex()-1)" 1339 lexerRulePropertyRef_self(scope,attr) ::= "$self" 1340 1341 // setting $st and $tree is allowed in local rule. everything else 1342 // is flagged as error 1343 ruleSetPropertyRef_tree(scope,attr,expr) ::= "retval.tree =<expr>;" 1344 ruleSetPropertyRef_st(scope,attr,expr) ::= "retval.st =<expr>;" 1345 1346 1347 /** How to execute an action */ 1348 execAction(action) ::= << 1349 <if(backtracking)> 1350 <if(actions.(actionScope).synpredgate)> 1351 if ( <actions.(actionScope).synpredgate> ) { 1352 <action> 1353 } 1354 <else> 1355 if ( backtracking==0 ) { 1356 <action> 1357 } 1358 <endif> 1359 <else> 1360 <action> 1361 <endif> 1362 >> 1363 1364 // M I S C (properties, etc...) 1365 1366 bitset(name, words64) ::= << 1367 Readonly my $<name> => ANTLR::Runtime::BitSet->new({ words64 => [ <words64:{'<it>'};separator=", "> ] });<\n> 1368 >> 1369 1370 codeFileExtension() ::= ".pm" 1371 1372 true() ::= "1" 1373 false() ::= "0" 1374