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