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 ActionScript; 29 30 asTypeInitMap ::= [ 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 */ 41 outputFile(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> 50 package<if(actions.(actionScope).package)> <actions.(actionScope).package><endif> { 51 <actions.(actionScope).header> 52 <@imports> 53 import 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 64 lexer(grammar, name, tokens, scopes, rules, numRules, labelType="Token", 65 filterMode, superClass="Lexer") ::= << 66 public 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 */ 113 filteringNextToken() ::= << 114 public 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 152 public override function memoize(input:IntStream, 153 ruleIndex:int, 154 ruleStartIndex:int):void 155 { 156 if ( this.state.backtracking>1 ) super.memoize(input, ruleIndex, ruleStartIndex); 157 } 158 159 public override function alreadyParsedRule(input:IntStream, ruleIndex:int):Boolean { 160 if ( this.state.backtracking>1 ) return super.alreadyParsedRule(input, ruleIndex); 161 return false; 162 } 163 >> 164 165 actionGate() ::= "this.state.backtracking==0" 166 167 filteringActionGate() ::= "this.state.backtracking==1" 168 169 /** How to generate a parser */ 170 genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 171 bitsets, inputStreamType, superClass, filterMode, 172 ASTLabelType="Object", labelType, members, rewriteElementType) ::= << 173 public 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 225 parserCtorBody() ::= << 226 <if(memoize)> 227 <if(grammar.grammarIsRoot)> 228 this.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 235 parser(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 */ 242 treeParser(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 */ 253 synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::= 254 << 255 // $ANTLR start <ruleName> 256 public 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 273 synpred(name) ::= << 274 public 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 292 lexerSynpred(name) ::= << 293 <synpred(name)> 294 >> 295 296 ruleMemoization(name) ::= << 297 <if(memoize)> 298 if ( this.state.backtracking>0 && alreadyParsedRule(input, <ruleDescriptor.index>) ) { return <ruleReturnValue()>; } 299 <endif> 300 >> 301 302 /** How to test for failure and return from rule */ 303 checkRuleBacktrackFailure() ::= << 304 <if(backtracking)>if (this.state.failed) return <ruleReturnValue()>;<endif> 305 >> 306 307 /** This rule has failed, exit indicating failure during backtrack */ 308 ruleBacktrackFailure() ::= << 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 */ 315 rule(ruleName,ruleDescriptor,block,emptyRule,description,exceptions,finally,memoize) ::= << 316 <ruleAttributeScope(scope=ruleDescriptor.ruleScope)> 317 // $ANTLR start <ruleName> 318 // <fileName>:<description> 319 public 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 359 catch(decl,action) ::= << 360 catch (<e.decl>) { 361 <e.action> 362 } 363 >> 364 365 ruleDeclarations() ::= << 366 <if(ruleDescriptor.hasMultipleReturnValues)> 367 var retval:<returnType()> = new <returnType()>(); 368 retval.start = input.LT(1);<\n> 369 <else> 370 <ruleDescriptor.returnScope.attributes:{ a | 371 var <a.name>:<a.type> = <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>; 372 }> 373 <endif> 374 <if(memoize)> 375 var <ruleDescriptor.name>_StartIndex:int = input.index; 376 <endif> 377 >> 378 379 ruleScopeSetUp() ::= << 380 <ruleDescriptor.useScopes:{<it>_stack.push(new Object());}; separator="\n"> 381 <ruleDescriptor.ruleScope:{<it.name>_stack.push(new Object());}; separator="\n"> 382 >> 383 384 ruleScopeCleanUp() ::= << 385 <ruleDescriptor.useScopes:{<it>_stack.pop();}; separator="\n"> 386 <ruleDescriptor.ruleScope:{<it.name>_stack.pop();}; separator="\n"> 387 >> 388 389 ruleLabelDefs() ::= << 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 401 lexerRuleLabelDefs() ::= << 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 414 ruleReturnValue() ::= << 415 <if(!ruleDescriptor.isSynPred)> 416 <if(ruleDescriptor.hasReturnValue)> 417 <if(ruleDescriptor.hasSingleReturnValue)> 418 <ruleDescriptor.singleValueReturnName> 419 <else> 420 retval 421 <endif> 422 <endif> 423 <endif> 424 >> 425 426 ruleCleanUp() ::= << 427 <if(ruleDescriptor.hasMultipleReturnValues)> 428 <if(!TREE_PARSER)> 429 retval.stop = input.LT(-1);<\n> 430 <endif> 431 <endif> 432 >> 433 434 memoize() ::= << 435 <if(memoize)> 436 <if(backtracking)> 437 if ( 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 */ 445 lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= << 446 // $ANTLR start <ruleName> 447 public 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 */ 482 tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= << 483 public 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 */ 491 block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 492 // <fileName>:<description> 493 var alt<decisionNumber>:int=<maxAlt>; 494 <decls> 495 <@predecision()> 496 <decision> 497 <@postdecision()> 498 <@prebranch()> 499 switch (alt<decisionNumber>) { 500 <alts:altSwitchCase()> 501 } 502 <@postbranch()> 503 >> 504 505 /** A rule block with multiple alternatives */ 506 ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 507 // <fileName>:<description> 508 var alt<decisionNumber>:int=<maxAlt>; 509 <decls> 510 <@predecision()> 511 <decision> 512 <@postdecision()> 513 switch (alt<decisionNumber>) { 514 <alts:altSwitchCase()> 515 } 516 >> 517 518 ruleBlockSingleAlt(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 */ 527 blockSingleAlt(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 */ 536 positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 537 // <fileName>:<description> 538 var cnt<decisionNumber>:int=0; 539 <decls> 540 <@preloop()> 541 loop<decisionNumber>: 542 do { 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 560 positiveClosureBlockSingleAlt ::= positiveClosureBlock 561 562 /** A (..)* block with 1 or more alternatives */ 563 closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 564 // <fileName>:<description> 565 <decls> 566 <@preloop()> 567 loop<decisionNumber>: 568 do { 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 582 closureBlockSingleAlt ::= 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 */ 587 optionalBlock ::= block 588 589 optionalBlockSingleAlt ::= 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 */ 595 altSwitchCase() ::= << 596 case <i> : 597 <@prealt()> 598 <it> 599 break;<\n> 600 >> 601 602 /** An alternative is just a list of elements; at outermost level */ 603 alt(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 */ 616 noRewrite(rewriteBlockLevel, treeLevel) ::= "" 617 618 // E L E M E N T S 619 620 /** Dump the elements one per line */ 621 element() ::= << 622 <@prematch()> 623 <it.el><\n> 624 >> 625 626 /** match a token optionally with a label in front */ 627 tokenRef(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 */ 632 tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 633 <tokenRef(...)> 634 <listLabel(elem=label,...)> 635 >> 636 637 listLabel(label,elem) ::= << 638 if (list_<label>==null) list_<label>=new Array(); 639 list_<label>.push(<elem>);<\n> 640 >> 641 642 /** match a character */ 643 charRef(char,label) ::= << 644 <if(label)> 645 <label> = input.LA(1);<\n> 646 <endif> 647 match(<char>); <checkRuleBacktrackFailure()> 648 >> 649 650 /** match a character range */ 651 charRangeRef(a,b,label) ::= << 652 <if(label)> 653 <label> = input.LA(1);<\n> 654 <endif> 655 matchRange(<a>,<b>); <checkRuleBacktrackFailure()> 656 >> 657 658 /** For now, sets are interval tests and must be tested inline */ 659 matchSet(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> 667 if ( <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 } 675 else { 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 689 matchRuleBlockSet ::= matchSet 690 691 matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= << 692 <matchSet(...)> 693 <listLabel(elem=label,...)> 694 >> 695 696 /** Match a string literal */ 697 lexerStringRef(string,label,elementIndex) ::= << 698 <if(label)> 699 var <label>Start:int = charIndex; 700 matchString(<string>); <checkRuleBacktrackFailure()> 701 <label> = CommonToken.createFromStream(input, TokenConstants.INVALID_TOKEN_TYPE, TokenConstants.DEFAULT_CHANNEL, <label>Start, charIndex-1); 702 <else> 703 matchString(<string>); <checkRuleBacktrackFailure()><\n> 704 <endif> 705 >> 706 707 wildcard(label,elementIndex) ::= << 708 <if(label)> 709 <label>=<labelType>(input.LT(1));<\n> 710 <endif> 711 matchAny(input); <checkRuleBacktrackFailure()> 712 >> 713 714 wildcardAndListLabel(label,elementIndex) ::= << 715 <wildcard(...)> 716 <listLabel(elem=label,...)> 717 >> 718 719 /** Match . wildcard in lexer */ 720 wildcardChar(label, elementIndex) ::= << 721 <if(label)> 722 <label> = input.LA(1);<\n> 723 <endif> 724 matchAny(); <checkRuleBacktrackFailure()> 725 >> 726 727 wildcardCharListLabel(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 */ 741 ruleRef(rule,label,elementIndex,args,scope) ::= << 742 pushFollow(FOLLOW_<rule.name>_in_<ruleName><elementIndex>); 743 <if(label)><label>=<endif><if(scope)><scope:delegateName()>.<endif><rule.name>(<args; separator=", ">);<\n> 744 state._fsp = state._fsp - 1; 745 <checkRuleBacktrackFailure()> 746 >> 747 748 749 /** ids+=r */ 750 ruleRefAndListLabel(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 */ 761 lexerRuleRef(rule,label,args,elementIndex,scope) ::= << 762 <if(label)> 763 var <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 */ 772 lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= << 773 <lexerRuleRef(...)> 774 <listLabel(elem=label,...)> 775 >> 776 777 /** EOF in the lexer */ 778 lexerMatchEOF(label,elementIndex) ::= << 779 <if(label)> 780 var <label>Start<elementIndex>:int = charIndex; 781 match(EOF); <checkRuleBacktrackFailure()> 782 var <label>:<labelType> = CommonToken.createFromStream(input, EOF, TokenConstants.DEFAULT_CHANNEL, <label>Start<elementIndex>, charIndex-1); 783 <else> 784 match(EOF); <checkRuleBacktrackFailure()> 785 <endif> 786 >> 787 788 /** match ^(root children) in tree parser */ 789 tree(root, actionsAfterRoot, children, nullableChildList, 790 enclosingTreeLevel, treeLevel) ::= << 791 <root:element()> 792 <actionsAfterRoot:element()> 793 <if(nullableChildList)> 794 if ( 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> 800 matchStream(input, TokenConstants.DOWN, null); <checkRuleBacktrackFailure()> 801 <children:element()> 802 matchStream(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 */ 809 validateSemanticPredicate(pred,description) ::= << 810 if ( !(<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 818 dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 819 var LA<decisionNumber>_<stateNumber>:int = input.LA(<k>);<\n> 820 <edges; separator="\nelse "> 821 else { 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 */ 837 dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 838 var 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 */ 848 dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 849 var LA<decisionNumber>_<stateNumber>:int = input.LA(<k>);<\n> 850 <edges; separator="\nelse "><\n> 851 <if(eotPredictsAlt)> 852 <if(!edges)> 853 alt<decisionNumber>=<eotPredictsAlt>; <! if no edges, don't gen ELSE !> 854 <else> 855 else { 856 alt<decisionNumber>=<eotPredictsAlt>; 857 }<\n> 858 <endif> 859 <endif> 860 >> 861 862 /** An accept state indicates a unique alternative has been predicted */ 863 dfaAcceptState(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 */ 869 dfaEdge(labelExpr, targetState, predicates) ::= << 870 if ( (<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 */ 880 dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 881 switch ( input.LA(<k>) ) { 882 <edges; separator="\n"> 883 default: 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 894 dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 895 switch ( input.LA(<k>) ) { 896 <edges; separator="\n"> 897 }<\n> 898 >> 899 900 dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 901 switch ( input.LA(<k>) ) { 902 <edges; separator="\n"><\n> 903 <if(eotPredictsAlt)> 904 default: 905 alt<decisionNumber>=<eotPredictsAlt>; 906 break;<\n> 907 <endif> 908 }<\n> 909 >> 910 911 dfaEdgeSwitch(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 */ 925 dfaDecision(decisionNumber,description) ::= << 926 alt<decisionNumber> = dfa<decisionNumber>.predict(input); 927 >> 928 929 cyclicDFACtor(dfa) ::= << 930 931 dfa<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 */ 946 cyclicDFA(dfa) ::= << 947 948 private const DFA<dfa.decisionNumber>_eot:Array = 949 DFA.unpackEncodedString("<dfa.javaCompressedEOT; wrap="\"+\n \"">"); 950 private const DFA<dfa.decisionNumber>_eof:Array = 951 DFA.unpackEncodedString("<dfa.javaCompressedEOF; wrap="\"+\n \"">"); 952 private const DFA<dfa.decisionNumber>_min:Array = 953 DFA.unpackEncodedString("<dfa.javaCompressedMin; wrap="\"+\n \"">", true); 954 private const DFA<dfa.decisionNumber>_max:Array = 955 DFA.unpackEncodedString("<dfa.javaCompressedMax; wrap="\"+\n \"">", true); 956 private const DFA<dfa.decisionNumber>_accept:Array = 957 DFA.unpackEncodedString("<dfa.javaCompressedAccept; wrap="\"+\n \"">"); 958 private const DFA<dfa.decisionNumber>_special:Array = 959 DFA.unpackEncodedString("<dfa.javaCompressedSpecial; wrap="\"+\n \"">"); 960 private 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 987 protected 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 */ 994 cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= << 995 var LA<decisionNumber>_<stateNumber>:int = input.LA(1);<\n> 996 <if(semPredState)> <! get next lookahead symbol to test edges, then rewind !> 997 var index<decisionNumber>_<stateNumber>:int = input.index; 998 input.rewind();<\n> 999 <endif> 1000 s = -1; 1001 <edges; separator="\nelse "> 1002 <if(semPredState)> <! return input cursor to state before we rewound !> 1003 input.seek(index<decisionNumber>_<stateNumber>);<\n> 1004 <endif> 1005 if ( s>=0 ) return s; 1006 break; 1007 >> 1008 1009 /** Just like a fixed DFA edge, test the lookahead and indicate what 1010 * state to jump to next if successful. 1011 */ 1012 cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= << 1013 if ( (<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 */ 1019 eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= << 1020 s = <targetStateNumber>;<\n> 1021 >> 1022 1023 1024 // D F A E X P R E S S I O N S 1025 1026 andPredicates(left,right) ::= "(<left>&&<right>)" 1027 1028 orPredicates(operands) ::= "(<first(operands)><rest(operands):{o | ||<o>}>)" 1029 1030 notPredicate(pred) ::= "!(<evalPredicate(...)>)" 1031 1032 evalPredicate(pred,description) ::= "(<pred>)" 1033 1034 evalSynPredicate(pred,description) ::= "<pred>()" 1035 1036 lookaheadTest(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 */ 1041 isolatedLookaheadTest(atom,k,atomAsInt) ::= "input.LA(<k>)==<atomAsInt>" 1042 1043 lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= << 1044 (LA<decisionNumber>_<stateNumber>\>=<lowerAsInt> && LA<decisionNumber>_<stateNumber>\<=<upperAsInt>) 1045 >> 1046 1047 isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "(input.LA(<k>)\>=<lowerAsInt> && input.LA(<k>)\<=<upperAsInt>)" 1048 1049 setTest(ranges) ::= "<ranges; separator=\"||\">" 1050 1051 // A T T R I B U T E S 1052 1053 globalAttributeScope(scope) ::= << 1054 <if(scope.attributes)> 1055 protected var <scope.name>_stack:Array = new Array();<\n> 1056 <endif> 1057 >> 1058 1059 ruleAttributeScope(scope) ::= << 1060 <if(scope.attributes)> 1061 protected var <scope.name>_stack:Array = new Array();<\n> 1062 <endif> 1063 >> 1064 1065 returnStructName() ::= "<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope" 1066 1067 returnType() ::= << 1068 <if(ruleDescriptor.hasMultipleReturnValues)> 1069 <returnStructName()> 1070 <else> 1071 <if(ruleDescriptor.hasSingleReturnValue)> 1072 <ruleDescriptor.singleValueReturnType> 1073 <else> 1074 void 1075 <endif> 1076 <endif> 1077 >> 1078 1079 /** Generate the Java type associated with a single or multiple return 1080 * values. 1081 */ 1082 ruleLabelType(referencedRule) ::= << 1083 <if(referencedRule.hasMultipleReturnValues)> 1084 <returnStructName()> 1085 <else> 1086 <if(referencedRule.hasSingleReturnValue)> 1087 <referencedRule.singleValueReturnType> 1088 <else> 1089 void 1090 <endif> 1091 <endif> 1092 >> 1093 1094 delegateName() ::= << 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 */ 1101 initValue(typeName) ::= << 1102 <asTypeInitMap.(typeName)> 1103 >> 1104 1105 /** Define a rule label including default value */ 1106 ruleLabelDef(label) ::= << 1107 var <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 */ 1114 returnScope(scope) ::= << 1115 <if(ruleDescriptor.hasMultipleReturnValues)> 1116 public 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 1123 parameterScope(scope) ::= << 1124 <scope.attributes:{<it.name>:<it.type>}; separator=", "> 1125 >> 1126 1127 parameterAttributeRef(attr) ::= "<attr.name>" 1128 parameterSetAttributeRef(attr,expr) ::= "<attr.name> =<expr>;" 1129 1130 scopeAttributeRef(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 1142 scopeSetAttributeRef(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 */ 1158 isolatedDynamicScopeRef(scope) ::= "<scope>_stack" 1159 1160 /** reference an attribute of rule; might only have single return value */ 1161 ruleLabelRef(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 1169 returnAttributeRef(ruleDescriptor,attr) ::= << 1170 <if(ruleDescriptor.hasMultipleReturnValues)> 1171 retval.values.<attr.name> 1172 <else> 1173 <attr.name> 1174 <endif> 1175 >> 1176 1177 returnSetAttributeRef(ruleDescriptor,attr,expr) ::= << 1178 <if(ruleDescriptor.hasMultipleReturnValues)> 1179 retval.values.<attr.name> =<expr>; 1180 <else> 1181 <attr.name> =<expr>; 1182 <endif> 1183 >> 1184 1185 /** How to translate $tokenLabel */ 1186 tokenLabelRef(label) ::= "<label>" 1187 1188 /** ids+=ID {$ids} or e+=expr {$e} */ 1189 listLabelRef(label) ::= "list_<label>" 1190 1191 1192 // not sure the next are the right approach 1193 1194 tokenLabelPropertyRef_text(scope,attr) ::= "(<scope>!=null?<scope>.text:null)" 1195 tokenLabelPropertyRef_type(scope,attr) ::= "(<scope>!=null?<scope>.type:0)" 1196 tokenLabelPropertyRef_line(scope,attr) ::= "(<scope>!=null?<scope>.line:0)" 1197 tokenLabelPropertyRef_pos(scope,attr) ::= "(<scope>!=null?<scope>.charPositionInLine:0)" 1198 tokenLabelPropertyRef_channel(scope,attr) ::= "(<scope>!=null?<scope>.channel:0)" 1199 tokenLabelPropertyRef_index(scope,attr) ::= "(<scope>!=null?<scope>.tokenIndex:0)" 1200 tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree" 1201 tokenLabelPropertyRef_int(scope,attr) ::= "(<scope>!=null?int(<scope>.text):0)" 1202 1203 ruleLabelPropertyRef_start(scope,attr) ::= "(<scope>!=null?<labelType>(<scope>.start):null)" 1204 ruleLabelPropertyRef_stop(scope,attr) ::= "(<scope>!=null?<labelType>(<scope>.stop):null)" 1205 ruleLabelPropertyRef_tree(scope,attr) ::= "(<scope>!=null?<ASTLabelType>(<scope>.tree):null)" 1206 ruleLabelPropertyRef_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 1216 ruleLabelPropertyRef_st(scope,attr) ::= "(<scope>!=null?<scope>.st:null)" 1217 1218 /** Isolated $RULE ref ok in lexer as it's a Token */ 1219 lexerRuleLabel(label) ::= "<label>" 1220 1221 lexerRuleLabelPropertyRef_type(scope,attr) ::= 1222 "(<scope>!=null?<scope>.type:0)" 1223 lexerRuleLabelPropertyRef_line(scope,attr) ::= 1224 "(<scope>!=null?<scope>.lien:0)" 1225 lexerRuleLabelPropertyRef_pos(scope,attr) ::= 1226 "(<scope>!=null?<scope>.charPositionInLine:0)" 1227 lexerRuleLabelPropertyRef_channel(scope,attr) ::= 1228 "(<scope>!=null?<scope>.channel:0)" 1229 lexerRuleLabelPropertyRef_index(scope,attr) ::= 1230 "(<scope>!=null?<scope>.tokenIndex:0)" 1231 lexerRuleLabelPropertyRef_text(scope,attr) ::= 1232 "(<scope>!=null?<scope>.text:null)" 1233 lexerRuleLabelPropertyRef_int(scope,attr) ::= 1234 "(<scope>!=null?int(<scope>.text):0)" 1235 1236 // Somebody may ref $template or $tree or $stop within a rule: 1237 rulePropertyRef_start(scope,attr) ::= "<labelType>(retval.start)" 1238 rulePropertyRef_stop(scope,attr) ::= "<labelType>(retval.stop)" 1239 rulePropertyRef_tree(scope,attr) ::= "<ASTLabelType>(retval.tree)" 1240 rulePropertyRef_text(scope,attr) ::= << 1241 <if(TREE_PARSER)> 1242 input.tokenStream.toStringWithRange( 1243 input.treeAdaptor.getTokenStartIndex(retval.start), 1244 input.treeAdaptor.getTokenStopIndex(retval.start)) 1245 <else> 1246 input.toStringWithTokenRange(retval.start,input.LT(-1)) 1247 <endif> 1248 >> 1249 rulePropertyRef_st(scope,attr) ::= "retval.st" 1250 1251 lexerRulePropertyRef_text(scope,attr) ::= "text" 1252 lexerRulePropertyRef_type(scope,attr) ::= "_type" 1253 lexerRulePropertyRef_line(scope,attr) ::= "state.tokenStartLine" 1254 lexerRulePropertyRef_pos(scope,attr) ::= "state.tokenStartCharPositionInLine" 1255 lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer 1256 lexerRulePropertyRef_channel(scope,attr) ::= "_channel" 1257 lexerRulePropertyRef_start(scope,attr) ::= "state.tokenStartCharIndex" 1258 lexerRulePropertyRef_stop(scope,attr) ::= "(charIndex-1)" 1259 lexerRulePropertyRef_int(scope,attr) ::= "int(<scope>.text)" 1260 1261 // setting $st and $tree is allowed in local rule. everything else 1262 // is flagged as error 1263 ruleSetPropertyRef_tree(scope,attr,expr) ::= "retval.tree =<expr>;" 1264 ruleSetPropertyRef_st(scope,attr,expr) ::= "retval.st =<expr>;" 1265 1266 /** How to execute an action (only when not backtracking) */ 1267 execAction(action) ::= << 1268 <if(backtracking)> 1269 if ( <actions.(actionScope).synpredgate> ) { 1270 <action> 1271 } 1272 <else> 1273 <action> 1274 <endif> 1275 >> 1276 1277 /** How to always execute an action even when backtracking */ 1278 execForcedAction(action) ::= "<action>" 1279 1280 // M I S C (properties, etc...) 1281 1282 bitset(name, words64) ::= << 1283 public static const <name>:BitSet = new BitSet([<words64:{<it>};separator=", ">]);<\n> 1284 >> 1285 1286 codeFileExtension() ::= ".as" 1287 1288 true() ::= "true" 1289 false() ::= "false" 1290