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 30group Perl5; 31 32/** The overall file structure of a recognizer; stores methods for rules 33 * and cyclic DFAs plus support code. 34 */ 35outputFile(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 57lexer(grammar, name, tokens, scopes, rules, numRules, labelType="Token", 58 filterMode, superClass="ANTLR::Runtime::Lexer") ::= << 59package <name>; 60 61use Carp; 62use English qw( -no_match_vars ) ; 63use Readonly; 64use Switch; 65 66use ANTLR::Runtime::BaseRecognizer; 67use ANTLR::Runtime::DFA; 68use ANTLR::Runtime::NoViableAltException; 69 70use Moose; 71 72extends 'ANTLR::Runtime::Lexer'; 73 74Readonly my $HIDDEN => ANTLR::Runtime::BaseRecognizer->HIDDEN; 75sub HIDDEN { $HIDDEN } 76 77use constant { 78 <tokens:{ <it.name> => <it.type>, }; separator="\n"> 79}; 80<scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}> 81<actions.lexer.members> 82 83sub BUILD { 84 my ($self, $arg_ref) = @_; 85 86 $self->init_dfas(); 87} 88 89sub 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 102sub 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 114no Moose; 115__PACKAGE__->meta->make_immutable(); 1161; 117 118>> 119 120perlTypeInitMap ::= [ 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 */ 133filteringNextToken() ::= << 134public 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 170public void memoize(IntStream input, 171 int ruleIndex, 172 int ruleStartIndex) 173{ 174if ( backtracking>1 ) super.memoize(input, ruleIndex, ruleStartIndex); 175} 176 177public boolean alreadyParsedRule(IntStream input, int ruleIndex) { 178if ( backtracking>1 ) return super.alreadyParsedRule(input, ruleIndex); 179return false; 180} 181>> 182 183actionGate() ::= "$self->state->backtracking==0" 184 185filteringActionGate() ::= "backtracking==1" 186 187/** How to generate a parser */ 188genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 189 bitsets, inputStreamType, superClass, filterMode, 190 ASTLabelType="Object", labelType, members) ::= << 191package <name>; 192 193use English qw( -no_match_vars ) ; 194use Readonly; 195use Switch; 196use Carp; 197use ANTLR::Runtime::BitSet; 198 199use Moose; 200 201extends '<@superClassName><superClass><@end>'; 202 203Readonly my $token_names => [ 204 "\<invalid>", "\<EOR>", "\<DOWN>", "\<UP>", <tokenNames; separator=", "> 205]; 206 207use 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 218sub BUILD { 219 my ($self, $arg_ref) = @_; 220 221<if(backtracking)> 222 $self->state->rule_memo({});<\n> 223<endif> 224} 225<@end> 226 227sub get_token_names { 228 return $token_names; 229} 230 231sub 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 244no Moose; 245__PACKAGE__->meta->make_immutable(); 2461; 247__END__ 248>> 249 250parser(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 */ 257treeParser(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 */ 268synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::= 269<< 270# $ANTLR start <ruleName> 271sub <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 290synpred(name) ::= << 291public 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 309lexerSynpred(name) ::= << 310<synpred(name)> 311>> 312 313ruleMemoization(name) ::= << 314<if(memoize)> 315if ( backtracking>0 && alreadyParsedRule(input, <ruleDescriptor.index>) ) { return <ruleReturnValue()>; } 316<endif> 317>> 318 319/** How to test for failure and return from rule */ 320checkRuleBacktrackFailure() ::= << 321<if(backtracking)> 322if ($self->state->failed) { 323 return <ruleReturnValue()>; 324} 325<endif> 326>> 327 328/** This rule has failed, exit indicating failure during backtrack */ 329ruleBacktrackFailure() ::= << 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 */ 336rule(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> 342sub <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 386catch(decl,action) ::= << 387catch (<e.decl>) { 388 <e.action> 389} 390>> 391 392ruleDeclarations() ::= << 393<if(ruleDescriptor.hasMultipleReturnValues)> 394my $retval = <returnType()>->new(); 395$retval->set_start($self->input->LT(1));<\n> 396<else> 397<ruleDescriptor.returnScope.attributes:{ a | 398my $<a.name> = <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>; 399}> 400<endif> 401<if(memoize)> 402my $<ruleDescriptor.name>_start_index = $self->input->index(); 403<endif> 404>> 405 406ruleScopeSetUp() ::= << 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 411ruleScopeCleanUp() ::= << 412<ruleDescriptor.useScopes:{<it>_stack.pop();}; separator="\n"> 413<ruleDescriptor.ruleScope:{<it.name>_stack.pop();}; separator="\n"> 414>> 415 416ruleLabelDefs() ::= << 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 427lexerRuleLabelDefs() ::= << 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 441ruleReturnValue() ::= << 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 453ruleCleanUp() ::= << 454<if(ruleDescriptor.hasMultipleReturnValues)> 455<if(!TREE_PARSER)> 456$retval->set_stop($self->input->LT(-1));<\n> 457<endif> 458<endif> 459>> 460 461memoize() ::= << 462<if(memoize)> 463<if(backtracking)> 464if ( 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 */ 472lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= << 473# $ANTLR start <ruleName> 474sub 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 */ 511tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= << 512sub 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 */ 521block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 522# <fileName>:<description> 523my $alt<decisionNumber> = <maxAlt>; 524<decls> 525<@predecision()> 526<decision> 527<@postdecision()> 528<@prebranch()> 529switch ($alt<decisionNumber>) { 530 <alts:altSwitchCase()> 531} 532<@postbranch()> 533>> 534 535/** A rule block with multiple alternatives */ 536ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 537# <fileName>:<description> 538my $alt<decisionNumber> = <maxAlt>; 539<decls> 540<@predecision()> 541<decision> 542<@postdecision()> 543switch ($alt<decisionNumber>) { 544 <alts:altSwitchCase()> 545} 546>> 547 548ruleBlockSingleAlt(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 */ 557blockSingleAlt(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 */ 566positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 567# <fileName>:<description> 568my $cnt<decisionNumber> = 0; 569<decls> 570<@preloop()> 571LOOP<decisionNumber>: 572while (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 593positiveClosureBlockSingleAlt ::= positiveClosureBlock 594 595/** A (..)* block with 1 or more alternatives */ 596closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 597# <fileName>:<description> 598<decls> 599<@preloop()> 600LOOP<decisionNumber>: 601while (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 614closureBlockSingleAlt ::= 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 */ 619optionalBlock ::= block 620 621optionalBlockSingleAlt ::= 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 */ 627altSwitchCase() ::= << 628case <i> { 629 <@prealt()> 630 <it> 631}<\n> 632>> 633 634/** An alternative is just a list of elements; at outermost level */ 635alt(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 */ 648noRewrite(rewriteBlockLevel, treeLevel) ::= "" 649 650// E L E M E N T S 651 652/** Dump the elements one per line */ 653element() ::= << 654<@prematch()> 655<it.el><\n> 656>> 657 658/** match a token optionally with a label in front */ 659tokenRef(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 */ 665tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 666<tokenRef(...)> 667<listLabel(elem=label,...)> 668>> 669 670listLabel(label,elem) ::= << 671if (list_<label>==null) list_<label>=new ArrayList(); 672list_<label>.add(<elem>);<\n> 673>> 674 675/** match a character */ 676charRef(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 */ 684charRangeRef(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 */ 692matchSet(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> 700if ( <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} 708else { 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 725matchRuleBlockSet ::= matchSet 726 727matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= << 728<matchSet(...)> 729<listLabel(elem=label,...)> 730>> 731 732/** Match a string literal */ 733lexerStringRef(string,label,elementIndex) ::= << 734<if(label)> 735int <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 743wildcard(label,elementIndex) ::= << 744<if(label)> 745<label>=(<labelType>)input.LT(1);<\n> 746<endif> 747matchAny(input); <checkRuleBacktrackFailure()> 748>> 749 750wildcardAndListLabel(label,elementIndex) ::= << 751<wildcard(...)> 752<listLabel(elem=label,...)> 753>> 754 755/** Match . wildcard in lexer */ 756wildcardChar(label, elementIndex) ::= << 757<if(label)> 758<label> = $self->input->LA(1);<\n> 759<endif> 760matchAny(); <checkRuleBacktrackFailure()> 761>> 762 763wildcardCharListLabel(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 */ 771ruleRef(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 */ 783ruleRefAndListLabel(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 */ 794lexerRuleRef(rule,label,args,elementIndex,scope) ::= << 795<if(label)> 796int <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 */ 805lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= << 806<lexerRuleRef(...)> 807<listLabel(elem=label,...)> 808>> 809 810/** EOF in the lexer */ 811lexerMatchEOF(label,elementIndex) ::= << 812<if(label)> 813int <label>Start<elementIndex> = getCharIndex(); 814match(EOF); <checkRuleBacktrackFailure()> 815<labelType> <label> = new CommonToken(input, EOF, Token.DEFAULT_CHANNEL, <label>Start<elementIndex>, getCharIndex()-1); 816<else> 817match(EOF); <checkRuleBacktrackFailure()> 818<endif> 819>> 820 821/** match ^(root children) in tree parser */ 822tree(root, actionsAfterRoot, children, nullableChildList, 823 enclosingTreeLevel, treeLevel) ::= << 824<root:element()> 825<actionsAfterRoot:element()> 826<if(nullableChildList)> 827if ( 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> 833match(input, Token.DOWN, null); <checkRuleBacktrackFailure()> 834<children:element()> 835match(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 */ 842validateSemanticPredicate(pred,description) ::= << 843if ( !(<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 851dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 852my $LA<decisionNumber>_<stateNumber> = $self->input->LA(<k>);<\n> 853<edges; separator="\nels"> 854else { 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 */ 877dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 878my $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 */ 888dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 889my $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> 895else { 896 $alt<decisionNumber> = <eotPredictsAlt>; 897}<\n> 898<endif> 899<endif> 900>> 901 902/** An accept state indicates a unique alternative has been predicted */ 903dfaAcceptState(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 */ 909dfaEdge(labelExpr, targetState, predicates) ::= << 910if ( (<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 */ 920dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 921switch ( $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 942dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 943switch ( $self->input->LA(<k>) ) { 944 <edges; separator="\n"> 945}<\n> 946>> 947 948dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 949switch ( $self->input->LA(<k>) ) { 950<edges; separator="\n"><\n> 951<if(eotPredictsAlt)> 952else { $alt<decisionNumber> = <eotPredictsAlt> }<\n> 953<endif> 954}<\n> 955>> 956 957dfaEdgeSwitch(labels, targetState) ::= << 958case [<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 */ 967dfaDecision(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 */ 979cyclicDFA(dfa) ::= << 980Readonly my $DFA<dfa.decisionNumber>_eot => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedEOT; separator=", "> ]); 981Readonly my $DFA<dfa.decisionNumber>_eof => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedEOF; separator=", "> ]); 982Readonly my $DFA<dfa.decisionNumber>_min => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedMin; separator=", "> ]); 983Readonly my $DFA<dfa.decisionNumber>_max => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedMax; separator=", "> ]); 984Readonly my $DFA<dfa.decisionNumber>_accept => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedAccept; separator=", "> ]); 985Readonly my $DFA<dfa.decisionNumber>_special => ANTLR::Runtime::DFA->unpack_rle([ <dfa.javaCompressedSpecial; separator=", "> ]); 986Readonly my $DFA<dfa.decisionNumber>_transition => [ <dfa.javaCompressedTransition:{s|ANTLR::Runtime::DFA->unpack_rle([ <s; separator=", "> ])}; separator=", "> ]; 987 988{ 989package <name>::DFA<dfa.decisionNumber>; 990use ANTLR::Runtime::Class; 991 992use strict; 993use warnings; 994 995extends 'ANTLR::Runtime::DFA'; 996 997sub 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 1019sub get_description { 1020 return "<dfa.description>"; 1021} 1022 1023<@errorMethod()> 1024 1025<if(dfa.specialStateSTs)> 1026sub 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 */ 1073cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= << 1074my $input = $self->input; 1075my $LA<decisionNumber>_<stateNumber> = $input->LA(1);<\n> 1076<if(semPredState)> <! get next lookahead symbol to test edges, then rewind !> 1077my $index<decisionNumber>_<stateNumber> = $input->index(); 1078$input->rewind();<\n> 1079<endif> 1080s = -1; 1081<edges; separator="\nels"> 1082<if(semPredState)> <! return input cursor to state before we rewound !> 1083input.seek(index<decisionNumber>_<stateNumber>);<\n> 1084<endif> 1085if ( s>=0 ) return s; 1086break; 1087>> 1088 1089/** Just like a fixed DFA edge, test the lookahead and indicate what 1090 * state to jump to next if successful. 1091 */ 1092cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= << 1093if ( (<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 */ 1099eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= << 1100s = <targetStateNumber>;<\n> 1101>> 1102 1103 1104// D F A E X P R E S S I O N S 1105 1106andPredicates(left,right) ::= "(<left> && <right>)" 1107 1108orPredicates(operands) ::= "(<first(operands)><rest(operands):{o | ||<o>}>)" 1109 1110notPredicate(pred) ::= "!(<evalPredicate(...)>)" 1111 1112evalPredicate(pred,description) ::= "<pred>" 1113 1114evalSynPredicate(pred,description) ::= "<pred>()" 1115 1116lookaheadTest(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 */ 1121isolatedLookaheadTest(atom,k,atomAsInt) ::= "$self->input->LA(<k>) eq <atom>" 1122 1123lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= << 1124($LA<decisionNumber>_<stateNumber> ge <lower> && $LA<decisionNumber>_<stateNumber> le <upper>) 1125>> 1126 1127isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "($self->input->LA(<k>) ge <lower> && $self->input->LA(<k>) le <upper>)" 1128 1129setTest(ranges) ::= "<ranges; separator=\" || \">" 1130 1131// A T T R I B U T E S 1132 1133globalAttributeScope(scope) ::= << 1134<if(scope.attributes)> 1135protected static class <scope.name>_scope { 1136 <scope.attributes:{<it.decl>;}; separator="\n"> 1137} 1138protected Stack <scope.name>_stack = new Stack();<\n> 1139<endif> 1140>> 1141 1142ruleAttributeScope(scope) ::= << 1143<if(scope.attributes)> 1144protected static class <scope.name>_scope { 1145 <scope.attributes:{<it.decl>;}; separator="\n"> 1146} 1147protected Stack <scope.name>_stack = new Stack();<\n> 1148<endif> 1149>> 1150 1151returnType() ::= << 1152<if(ruleDescriptor.hasMultipleReturnValues)> 1153<ruleDescriptor.name>_return 1154<else> 1155<if(ruleDescriptor.hasSingleReturnValue)> 1156<ruleDescriptor.singleValueReturnType> 1157<else> 1158void 1159<endif> 1160<endif> 1161>> 1162 1163/** Generate the Java type associated with a single or multiple return 1164 * values. 1165 */ 1166ruleLabelType(referencedRule) ::= << 1167<if(referencedRule.hasMultipleReturnValues)> 1168<referencedRule.name>_return 1169<else> 1170<if(referencedRule.hasSingleReturnValue)> 1171<referencedRule.singleValueReturnType> 1172<else> 1173void 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 */ 1181initValue(typeName) ::= << 1182<if(typeName)> 1183<perlTypeInitMap.(typeName)> 1184<else> 1185undef 1186<endif> 1187>> 1188 1189/** Define a rule label including default value */ 1190ruleLabelDef(label) ::= << 1191my $<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 */ 1198returnScope(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 1212parameterScope(scope) ::= << 1213<scope.attributes:{$<it.name>}; separator=", "> 1214>> 1215 1216parameterAttributeRef(attr) ::= "$<attr.name>" 1217parameterSetAttributeRef(attr,expr) ::= "$<attr.name> =<expr>;" 1218 1219scopeAttributeRef(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 1231scopeSetAttributeRef(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 */ 1247isolatedDynamicScopeRef(scope) ::= "<scope>_stack" 1248 1249/** reference an attribute of rule; might only have single return value */ 1250ruleLabelRef(referencedRule,scope,attr) ::= << 1251<if(referencedRule.hasMultipleReturnValues)> 1252$<scope>.<attr.name> 1253<else> 1254$<scope> 1255<endif> 1256>> 1257 1258returnAttributeRef(ruleDescriptor,attr) ::= << 1259<if(ruleDescriptor.hasMultipleReturnValues)> 1260retval.<attr.name> 1261<else> 1262$<attr.name> 1263<endif> 1264>> 1265 1266returnSetAttributeRef(ruleDescriptor,attr,expr) ::= << 1267<if(ruleDescriptor.hasMultipleReturnValues)> 1268retval.<attr.name> =<expr>; 1269<else> 1270$<attr.name> =<expr>; 1271<endif> 1272>> 1273 1274/** How to translate $tokenLabel */ 1275tokenLabelRef(label) ::= "$<label>" 1276 1277/** ids+=ID {$ids} or e+=expr {$e} */ 1278listLabelRef(label) ::= "list_<label>" 1279 1280 1281// not sure the next are the right approach 1282 1283tokenLabelPropertyRef_text(scope,attr) ::= "$<scope>->get_text()" 1284tokenLabelPropertyRef_type(scope,attr) ::= "<scope>.getType()" 1285tokenLabelPropertyRef_line(scope,attr) ::= "<scope>.getLine()" 1286tokenLabelPropertyRef_pos(scope,attr) ::= "<scope>.getCharPositionInLine()" 1287tokenLabelPropertyRef_channel(scope,attr) ::= "<scope>.getChannel()" 1288tokenLabelPropertyRef_index(scope,attr) ::= "<scope>.getTokenIndex()" 1289tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree" 1290 1291ruleLabelPropertyRef_start(scope,attr) ::= "((<labelType>)<scope>.start)" 1292ruleLabelPropertyRef_stop(scope,attr) ::= "((<labelType>)<scope>.stop)" 1293ruleLabelPropertyRef_tree(scope,attr) ::= "((<ASTLabelType>)<scope>.tree)" 1294ruleLabelPropertyRef_text(scope,attr) ::= << 1295<if(TREE_PARSER)> 1296input.getTokenStream().toString( 1297 input.getTreeAdaptor().getTokenStartIndex(<scope>.start), 1298 input.getTreeAdaptor().getTokenStopIndex(<scope>.start)) 1299<else> 1300substr($self->input, $<scope>->start, $<scope>->stop) 1301<endif> 1302>> 1303 1304ruleLabelPropertyRef_st(scope,attr) ::= "<scope>.st" 1305 1306/** Isolated $RULE ref ok in lexer as it's a Token */ 1307lexerRuleLabel(label) ::= "$<label>" 1308 1309lexerRuleLabelPropertyRef_type(scope,attr) ::= "<scope>.getType()" 1310lexerRuleLabelPropertyRef_line(scope,attr) ::= "<scope>.getLine()" 1311lexerRuleLabelPropertyRef_pos(scope,attr) ::= "<scope>.getCharPositionInLine()" 1312lexerRuleLabelPropertyRef_channel(scope,attr) ::= "<scope>.getChannel()" 1313lexerRuleLabelPropertyRef_index(scope,attr) ::= "<scope>.getTokenIndex()" 1314lexerRuleLabelPropertyRef_text(scope,attr) ::= "<scope>.getText()" 1315 1316// Somebody may ref $template or $tree or $stop within a rule: 1317rulePropertyRef_start(scope,attr) ::= "((<labelType>)retval.start)" 1318rulePropertyRef_stop(scope,attr) ::= "((<labelType>)retval.stop)" 1319rulePropertyRef_tree(scope,attr) ::= "((<ASTLabelType>)retval.tree)" 1320rulePropertyRef_text(scope,attr) ::= << 1321<if(TREE_PARSER)> 1322input.getTokenStream().toString( 1323 input.getTreeAdaptor().getTokenStartIndex(retval.start), 1324 input.getTreeAdaptor().getTokenStopIndex(retval.start)) 1325<else> 1326input.toString(retval.start,input.LT(-1)) 1327<endif> 1328>> 1329rulePropertyRef_st(scope,attr) ::= "retval.st" 1330 1331lexerRulePropertyRef_text(scope,attr) ::= "getText()" 1332lexerRulePropertyRef_type(scope,attr) ::= "$_type" 1333lexerRulePropertyRef_line(scope,attr) ::= "tokenStartLine" 1334lexerRulePropertyRef_pos(scope,attr) ::= "tokenStartCharPositionInLine" 1335lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer 1336lexerRulePropertyRef_channel(scope,attr) ::= "$_channel" 1337lexerRulePropertyRef_start(scope,attr) ::= "tokenStartCharIndex" 1338lexerRulePropertyRef_stop(scope,attr) ::= "(getCharIndex()-1)" 1339lexerRulePropertyRef_self(scope,attr) ::= "$self" 1340 1341// setting $st and $tree is allowed in local rule. everything else 1342// is flagged as error 1343ruleSetPropertyRef_tree(scope,attr,expr) ::= "retval.tree =<expr>;" 1344ruleSetPropertyRef_st(scope,attr,expr) ::= "retval.st =<expr>;" 1345 1346 1347/** How to execute an action */ 1348execAction(action) ::= << 1349<if(backtracking)> 1350<if(actions.(actionScope).synpredgate)> 1351if ( <actions.(actionScope).synpredgate> ) { 1352 <action> 1353} 1354<else> 1355if ( backtracking==0 ) { 1356 <action> 1357} 1358<endif> 1359<else> 1360<action> 1361<endif> 1362>> 1363 1364// M I S C (properties, etc...) 1365 1366bitset(name, words64) ::= << 1367Readonly my $<name> => ANTLR::Runtime::BitSet->new({ words64 => [ <words64:{'<it>'};separator=", "> ] });<\n> 1368>> 1369 1370codeFileExtension() ::= ".pm" 1371 1372true() ::= "1" 1373false() ::= "0" 1374