Home | History | Annotate | Download | only in ActionScript
      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