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