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