Scala.stg revision 324c4644fee44b9898524c09511bd33c3f12e2df
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*/
30scalaTypeInitMap ::= [
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 */
45outputFile(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>
57import org.antlr.runtime._
58<if(TREE_PARSER)>
59import org.antlr.runtime.tree._
60<endif>
61<@end>
62
63<docComment>
64<recognizer>
65>>
66
67lexer(grammar, name, tokens, scopes, rules, numRules, filterMode, labelType="CommonToken",
68      superClass="Lexer") ::= <<
69object <grammar.recognizerName> {
70    <tokens:{it | val <it.name> = <it.type>}; separator="\n">
71
72    <cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !>
73}
74
75class <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 */
121filteringNextToken() ::= <<
122override 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
164override def memoize(input: IntStream,
165		ruleIndex: Int,
166		ruleStartIndex: Int) = {
167if ( state.backtracking>1 ) super.memoize(input, ruleIndex, ruleStartIndex)
168}
169
170override def alreadyParsedRule(input: IntStream, ruleIndex: Int):Boolean {
171if ( state.backtracking>1 ) return super.alreadyParsedRule(input, ruleIndex)
172return false
173}
174>>
175
176actionGate() ::= "state.backtracking==0"
177
178filteringActionGate() ::= "state.backtracking==1"
179
180/** How to generate a parser */
181genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules,
182              bitsets, inputStreamType, superClass,
183              labelType, members, rewriteElementType,
184              filterMode, ASTLabelType="Object") ::= <<
185object <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
200class <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
244parserCtorBody() ::= <<
245<if(memoize)>
246<if(grammar.grammarIsRoot)>
247this.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
254parser(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 */
263treeParser(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 */
278synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::=
279<<
280// $ANTLR start <ruleName>
281@throws(classOf[RecognitionException])
282def <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
299synpred(name) ::= <<
300final 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
319lexerSynpred(name) ::= <<
320<synpred(name)>
321>>
322
323ruleMemoization(name) ::= <<
324<if(memoize)>
325if ( state.backtracking>0 && alreadyParsedRule(input, <ruleDescriptor.index>) ) { return <ruleReturnValue()> }
326<endif>
327>>
328
329/** How to test for failure and return from rule */
330checkRuleBacktrackFailure() ::= <<
331<if(backtracking)>if (state.failed) return <ruleReturnValue()><endif>
332>>
333
334/** This rule has failed, exit indicating failure during backtrack */
335ruleBacktrackFailure() ::= <<
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 */
342rule(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])
349final 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
390catch(decl,action) ::= <<
391catch (<e.decl>) {
392    <e.action>
393}
394>>
395
396ruleDeclarations() ::= <<
397<if(ruleDescriptor.hasMultipleReturnValues)>
398val retval = new <returnType()>()
399retval.start = input.LT(1)<\n>
400<else>
401<ruleDescriptor.returnScope.attributes:{ a |
402var <a.name>: <a.type> = <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>
403}>
404<endif>
405<if(memoize)>
406val <ruleDescriptor.name>_StartIndex = input.index()
407<endif>
408>>
409
410ruleScopeSetUp() ::= <<
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
415ruleScopeCleanUp() ::= <<
416<ruleDescriptor.useScopes:{it | <it>_stack.pop()}; separator="\n">
417<ruleDescriptor.ruleScope:{it | <it.name>_stack.pop()}; separator="\n">
418>>
419
420
421ruleLabelDefs() ::= <<
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
433lexerRuleLabelDefs() ::= <<
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
446ruleReturnValue() ::= <<
447<if(!ruleDescriptor.isSynPred)>
448<if(ruleDescriptor.hasReturnValue)>
449<if(ruleDescriptor.hasSingleReturnValue)>
450<ruleDescriptor.singleValueReturnName>
451<else>
452retval
453<endif>
454<endif>
455<endif>
456>>
457
458ruleCleanUp() ::= <<
459<if(ruleDescriptor.hasMultipleReturnValues)>
460<if(!TREE_PARSER)>
461retval.stop = input.LT(-1)<\n>
462<endif>
463<endif>
464>>
465
466memoize() ::= <<
467<if(memoize)>
468<if(backtracking)>
469if ( 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 */
477lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= <<
478// $ANTLR start "<ruleName>"
479@throws(classOf[RecognitionException])
480final 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 */
515tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= <<
516@throws(classOf[RecognitionException])
517def mTokens(): Unit = {
518    <block><\n>
519}
520>>
521
522// S U B R U L E S
523
524/** A (...) subrule with multiple alternatives */
525block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
526// <fileName>:<description>
527var alt<decisionNumber> = <maxAlt>
528<decls>
529<@predecision()>
530<decision>
531<@postdecision()>
532<@prebranch()>
533alt<decisionNumber> match {
534    <alts:{a | <altSwitchCase(i,a)>}>
535    case _ =>
536}
537<@postbranch()>
538>>
539
540/** A rule block with multiple alternatives */
541ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
542// <fileName>:<description>
543var alt<decisionNumber> = <maxAlt>
544<decls>
545<@predecision()>
546<decision>
547<@postdecision()>
548alt<decisionNumber> match {
549    <alts:{a | <altSwitchCase(i,a)>}>
550    case _ =>
551}
552>>
553
554ruleBlockSingleAlt(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 */
563blockSingleAlt(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 */
572positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
573// <fileName>:<description>
574var cnt<decisionNumber>: Int = 0
575<decls>
576<@preloop()>
577var loop<decisionNumber>_quitflag = false
578while (!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
599positiveClosureBlockSingleAlt ::= positiveClosureBlock
600
601/** A (..)* block with 1 or more alternatives */
602closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
603// <fileName>:<description>
604<decls>
605<@preloop()>
606var loop<decisionNumber>_quitflag = false
607while (!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
620closureBlockSingleAlt ::= 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 */
625optionalBlock ::= block
626
627optionalBlockSingleAlt ::= 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 */
633altSwitchCase(altNum, alt) ::= <<
634case <altNum> =>
635    <@prealt()>
636    <alt>
637>>
638
639/** An alternative is just a list of elements; at outermost level */
640alt(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 */
653noRewrite(rewriteBlockLevel, treeLevel) ::= ""
654
655// E L E M E N T S
656
657/** Dump the elements one per line */
658element(e) ::= <<
659<@prematch()>
660<e.el><\n>
661>>
662
663/** match a token optionally with a label in front */
664tokenRef(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 */
670tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
671<tokenRef(...)>
672<listLabel(elem=label,...)>
673>>
674
675listLabel(label,elem) ::= <<
676if (list_<label>==null) list_<label>=new java.util.ArrayList()
677list_<label>.add(<elem>)<\n>
678>>
679
680/** match a character */
681charRef(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 */
690charRangeRef(a,b,label) ::= <<
691<if(label)>
692<label> = input.LA(1)<\n>
693<endif>
694matchRange(<a>,<b>); <checkRuleBacktrackFailure()>
695>>
696
697/** For now, sets are interval tests and must be tested inline */
698matchSet(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>
706if ( <s> ) {
707    input.consume()
708    <postmatchCode>
709<if(!LEXER)>
710    state.errorRecovery=false<\n>
711<endif>
712    <if(backtracking)>state.failed=false<endif>
713}
714else {
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
730matchRuleBlockSet ::= matchSet
731
732matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= <<
733<matchSet(...)>
734<listLabel(elem=label,...)>
735>>
736
737/** Match a string literal */
738lexerStringRef(string,label,elementIndex="0") ::= <<
739<if(label)>
740val <label>Start = getCharIndex()
741`match`(<string>)
742<checkRuleBacktrackFailure()>
743val <label>StartLine<elementIndex> = getLine()
744val <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
754wildcard(token,label,elementIndex,terminalOptions) ::= <<
755<if(label)>
756<label>=input.LT(1).asInstanceOf[<labelType>]<\n>
757<endif>
758matchAny(input)
759<checkRuleBacktrackFailure()>
760>>
761
762wildcardAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
763<wildcard(...)>
764<listLabel(elem=label,...)>
765>>
766
767/** Match . wildcard in lexer */
768wildcardChar(label, elementIndex) ::= <<
769<if(label)>
770<label> = input.LA(1)<\n>
771<endif>
772matchAny()
773<checkRuleBacktrackFailure()>
774>>
775
776wildcardCharListLabel(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 */
787ruleRef(rule,label,elementIndex,args,scope) ::= <<
788pushFollow(FOLLOW_<rule.name>_in_<ruleName><elementIndex>)
789<if(label)><label>=<endif><if(scope)><scope:delegateName()>.<endif><rule.name>(<args; separator=", ">)<\n>
790state._fsp-=1
791<checkRuleBacktrackFailure()>
792>>
793
794/** ids+=r */
795ruleRefAndListLabel(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 */
806lexerRuleRef(rule,label,args,elementIndex,scope) ::= <<
807<if(label)>
808val <label>Start<elementIndex> = getCharIndex()
809val <label>StartLine<elementIndex> = getLine()
810val <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 */
823lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= <<
824<lexerRuleRef(...)>
825<listLabel(elem=label,...)>
826>>
827
828/** EOF in the lexer */
829lexerMatchEOF(label,elementIndex) ::= <<
830<if(label)>
831val <label>Start<elementIndex> = getCharIndex()
832val <label>StartLine<elementIndex> = getLine()
833val <label>StartCharPos<elementIndex> = getCharPositionInLine()
834`match`(EOF)
835<checkRuleBacktrackFailure()>
836val <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
846recRuleDefArg()                       ::= "int <recRuleArg()>"
847recRuleArg()                          ::= "_p"
848recRuleAltPredicate(ruleName,opPrec)  ::= "<recRuleArg()> \<= <opPrec>"
849recRuleSetResultAction()              ::= "root_0=$<ruleName>_primary.tree;"
850recRuleSetReturnAction(src,name)      ::= "$<name>=$<src>.<name>;"
851
852/** match ^(root children) in tree parser */
853tree(root, actionsAfterRoot, children, nullableChildList,
854     enclosingTreeLevel, treeLevel) ::= <<
855<root:element()>
856<actionsAfterRoot:element()>
857<if(nullableChildList)>
858if ( 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 */
877validateSemanticPredicate(pred,description) ::= <<
878if ( !(<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
886dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
887val LA<decisionNumber>_<stateNumber> = input.LA(<k>)<\n>
888<edges; separator="\nelse ">
889else {
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 */
906dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
907val 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 */
917dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
918val LA<decisionNumber>_<stateNumber> = input.LA(<k>)<\n>
919<edges; separator="\nelse "><\n>
920<if(eotPredictsAlt)>
921<if(!edges)>
922alt<decisionNumber>=<eotPredictsAlt> <! if no edges, don't gen ELSE !>
923<else>
924else {
925    alt<decisionNumber>=<eotPredictsAlt>
926}<\n>
927<endif>
928<endif>
929>>
930
931/** An accept state indicates a unique alternative has been predicted */
932dfaAcceptState(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 */
938dfaEdge(labelExpr, targetState, predicates) ::= <<
939if ( (<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 */
949dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
950input.LA(<k>) match {
951<edges; separator="\n">
952case _ =>
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
964dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
965input.LA(<k>) match {
966    <edges; separator="\n">
967    case _ =>
968}<\n>
969>>
970
971dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
972input.LA(<k>) match {
973<edges; separator="\n"><\n>
974case _ =>
975<if(eotPredictsAlt)>
976    alt<decisionNumber>=<eotPredictsAlt>;
977<endif>
978}<\n>
979>>
980
981dfaEdgeSwitch(labels, targetState) ::= <<
982case <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 */
994dfaDecision(decisionNumber,description) ::= <<
995alt<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 */
1006cyclicDFA(dfa) ::= <<
1007val DFA<dfa.decisionNumber>_eotS =
1008    "<dfa.javaCompressedEOT; wrap="\"+\n    \"">"
1009val DFA<dfa.decisionNumber>_eofS =
1010    "<dfa.javaCompressedEOF; wrap="\"+\n    \"">"
1011val DFA<dfa.decisionNumber>_minS =
1012    "<dfa.javaCompressedMin; wrap="\"+\n    \"">"
1013val DFA<dfa.decisionNumber>_maxS =
1014    "<dfa.javaCompressedMax; wrap="\"+\n    \"">"
1015val DFA<dfa.decisionNumber>_acceptS =
1016    "<dfa.javaCompressedAccept; wrap="\"+\n    \"">"
1017val DFA<dfa.decisionNumber>_specialS =
1018    "<dfa.javaCompressedSpecial; wrap="\"+\n    \"">}>"
1019val DFA<dfa.decisionNumber>_transitionS: Array[String] = Array(
1020        <dfa.javaCompressedTransition:{s|"<s; wrap="\"+\n\"">"}; separator=",\n">
1021)
1022
1023val DFA<dfa.decisionNumber>_eot: Array[Short] = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_eotS)
1024val DFA<dfa.decisionNumber>_eof: Array[Short] = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_eofS)
1025val DFA<dfa.decisionNumber>_min: Array[Char] = DFA.unpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_minS)
1026val DFA<dfa.decisionNumber>_max: Array[Char] = DFA.unpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_maxS)
1027val DFA<dfa.decisionNumber>_accept: Array[Short] = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_acceptS)
1028val DFA<dfa.decisionNumber>_special: Array[Short] = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_specialS)
1029val DFA<dfa.decisionNumber>_transition = new Array[Array[Short]](DFA<dfa.decisionNumber>_transitionS.length)
1030
1031for (i \<- DFA<dfa.decisionNumber>_transition.indices) {
1032    DFA<dfa.decisionNumber>_transition(i) = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_transitionS(i))
1033}
1034
1035class 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 */
1084cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= <<
1085val LA<decisionNumber>_<stateNumber>: Int = input.LA(1)<\n>
1086<if(semPredState)> <! get next lookahead symbol to test edges, then rewind !>
1087val index<decisionNumber>_<stateNumber>: Int = input.index()
1088input.rewind()<\n>
1089<endif>
1090s = -1
1091<edges; separator="\nelse ">
1092<if(semPredState)> <! return input cursor to state before we rewound !>
1093input.seek(index<decisionNumber>_<stateNumber>)<\n>
1094<endif>
1095if ( 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 */
1101cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= <<
1102if ( (<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 */
1108eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= <<
1109s = <targetStateNumber><\n>
1110>>
1111
1112
1113// D F A  E X P R E S S I O N S
1114
1115andPredicates(left,right) ::= "(<left>&&<right>)"
1116
1117orPredicates(operands) ::= "(<first(operands)><rest(operands):{o | ||<o>}>)"
1118
1119notPredicate(pred) ::= "!(<evalPredicate(pred,\"\")>)"
1120
1121evalPredicate(pred,description) ::= "(<pred>)"
1122
1123evalSynPredicate(pred,description) ::= "<pred>()"
1124
1125lookaheadTest(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 */
1130isolatedLookaheadTest(atom,k,atomAsInt) ::= "input.LA(<k>)==<atom>"
1131
1132lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= <<
1133(LA<decisionNumber>_<stateNumber> >= <lower> && LA<decisionNumber>_<stateNumber> \<= <upper>)
1134>>
1135
1136isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "(input.LA(<k>) >=<lower> && input.LA(<k>) \<= <upper>)"
1137
1138setTest(ranges) ::= "<ranges; separator=\"||\">"
1139
1140// A T T R I B U T E S
1141
1142globalAttributeScope(scope) ::= <<
1143<if(scope.attributes)>
1144class <scope.name>_scope {
1145    <scope.attributes:{it | var <it.name>: <it.type> = _}; separator="\n">
1146}
1147val <scope.name>_stack = new collection.mutable.Stack[<scope.name>_scope]<\n>
1148<endif>
1149>>
1150
1151ruleAttributeScope(scope) ::= <<
1152<if(scope.attributes)>
1153class <scope.name>_scope {
1154    <scope.attributes:{it | var <it.name>: <it.type> = _}; separator="\n">
1155}
1156val <scope.name>_stack = new collection.mutable.Stack[<scope.name>_scope]<\n>
1157<endif>
1158>>
1159
1160returnStructName(r) ::= "<r.name>_return"
1161
1162returnType() ::= <<
1163<if(ruleDescriptor.hasMultipleReturnValues)>
1164<ruleDescriptor:returnStructName()>
1165<else>
1166<if(ruleDescriptor.hasSingleReturnValue)>
1167<ruleDescriptor.singleValueReturnType>
1168<else>
1169Unit
1170<endif>
1171<endif>
1172>>
1173
1174/** Generate the Java type associated with a single or multiple return
1175 *  values.
1176 */
1177ruleLabelType(referencedRule) ::= <<
1178<if(referencedRule.hasMultipleReturnValues)>
1179<referencedRule.name>_return
1180<else>
1181<if(referencedRule.hasSingleReturnValue)>
1182<referencedRule.singleValueReturnType>
1183<else>
1184Unit
1185<endif>
1186<endif>
1187>>
1188
1189delegateName(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 */
1196initValue(typeName) ::= <<
1197<scalaTypeInitMap.(typeName)>
1198>>
1199
1200/** Define a rule label including default value */
1201ruleLabelDef(label) ::= <<
1202var <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 */
1210returnScope(scope) ::= <<
1211<if(ruleDescriptor.hasMultipleReturnValues)>
1212final 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
1219parameterScope(scope) ::= <<
1220<scope.attributes:{it | <it.name>: <it.type>}; separator=", ">
1221>>
1222
1223parameterAttributeRef(attr) ::= "<attr.name>"
1224parameterSetAttributeRef(attr,expr) ::= "<attr.name> =<expr>"
1225
1226scopeAttributeRef(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
1238scopeSetAttributeRef(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 */
1254isolatedDynamicScopeRef(scope) ::= "<scope>_stack"
1255
1256/** reference an attribute of rule; might only have single return value */
1257ruleLabelRef(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
1265returnAttributeRef(ruleDescriptor,attr) ::= <%
1266<if(ruleDescriptor.hasMultipleReturnValues)>
1267retval.<attr.name>
1268<else>
1269<attr.name>
1270<endif>
1271%>
1272
1273returnSetAttributeRef(ruleDescriptor,attr,expr) ::= <%
1274<if(ruleDescriptor.hasMultipleReturnValues)>
1275retval.<attr.name> =<expr>
1276<else>
1277<attr.name> =<expr>
1278<endif>
1279%>
1280
1281/** How to translate $tokenLabel */
1282tokenLabelRef(label) ::= "<label>"
1283
1284/** ids+=ID {$ids} or e+=expr {$e} */
1285listLabelRef(label) ::= "list_<label>"
1286
1287
1288// not sure the next are the right approach
1289
1290tokenLabelPropertyRef_text(scope,attr) ::= "(if (<scope>!=null) <scope>.getText() else null)"
1291tokenLabelPropertyRef_type(scope,attr) ::= "(if (<scope>!=null) <scope>.getType() else 0)"
1292tokenLabelPropertyRef_line(scope,attr) ::= "(if (<scope>!=null) <scope>.getLine() else 0)"
1293tokenLabelPropertyRef_pos(scope,attr) ::= "(if (<scope>!=null) <scope>.getCharPositionInLine() else 0)"
1294tokenLabelPropertyRef_channel(scope,attr) ::= "(if (<scope>!=null) <scope>.getChannel() else 0)"
1295tokenLabelPropertyRef_index(scope,attr) ::= "(if (<scope>!=null) <scope>.getTokenIndex() else 0)"
1296tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree"
1297tokenLabelPropertyRef_int(scope,attr) ::= "(if (<scope>!=null) Integer.valueOf(<scope>.getText()) else 0)"
1298
1299ruleLabelPropertyRef_start(scope,attr) ::= "(if (<scope>!=null) <scope>.start.asInstanceOf[<labelType>] else null)"
1300ruleLabelPropertyRef_stop(scope,attr) ::= "(if (<scope>!=null) <scope>.stop.asInstanceOf[<labelType>] else null)"
1301ruleLabelPropertyRef_tree(scope,attr) ::= "(if (<scope>!=null) <scope>.tree.asInstanceOf[<ASTLabelType>] else null)"
1302ruleLabelPropertyRef_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
1312ruleLabelPropertyRef_st(scope,attr) ::= "(if (<scope>!=null) <scope>.st else null)"
1313
1314/** Isolated $RULE ref ok in lexer as it's a Token */
1315lexerRuleLabel(label) ::= "<label>"
1316
1317lexerRuleLabelPropertyRef_type(scope,attr) ::=
1318    "(if (<scope>!=null) <scope>.getType() else 0)"
1319lexerRuleLabelPropertyRef_line(scope,attr) ::=
1320    "(if (<scope>!=null) <scope>.getLine() else 0)"
1321lexerRuleLabelPropertyRef_pos(scope,attr) ::=
1322    "(if (<scope>!=null) <scope>.getCharPositionInLine() else -1)"
1323lexerRuleLabelPropertyRef_channel(scope,attr) ::=
1324    "(if (<scope>!=null) <scope>.getChannel() else 0)"
1325lexerRuleLabelPropertyRef_index(scope,attr) ::=
1326    "(if (<scope>!=null) <scope>.getTokenIndex() else 0)"
1327lexerRuleLabelPropertyRef_text(scope,attr) ::=
1328    "(if (<scope>!=null) <scope>.getText() else null)"
1329lexerRuleLabelPropertyRef_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:
1333rulePropertyRef_start(scope,attr) ::= "(retval.start.asInstanceOf[<labelType>])"
1334rulePropertyRef_stop(scope,attr) ::= "(retval.stop.asInstanceOf[<labelType>])"
1335rulePropertyRef_tree(scope,attr) ::= "(retval.tree.asInstanceOf[<ASTLabelType>])"
1336rulePropertyRef_text(scope,attr) ::= <<
1337<if(TREE_PARSER)>
1338input.getTokenStream().toString(
1339  input.getTreeAdaptor().getTokenStartIndex(retval.start),
1340  input.getTreeAdaptor().getTokenStopIndex(retval.start))
1341<else>
1342input.toString(retval.start,input.LT(-1))
1343<endif>
1344>>
1345rulePropertyRef_st(scope,attr) ::= "retval.st"
1346
1347lexerRulePropertyRef_text(scope,attr) ::= "getText()"
1348lexerRulePropertyRef_type(scope,attr) ::= "_type"
1349lexerRulePropertyRef_line(scope,attr) ::= "state.tokenStartLine"
1350lexerRulePropertyRef_pos(scope,attr) ::= "state.tokenStartCharPositionInLine"
1351lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer
1352lexerRulePropertyRef_channel(scope,attr) ::= "_channel"
1353lexerRulePropertyRef_start(scope,attr) ::= "state.tokenStartCharIndex"
1354lexerRulePropertyRef_stop(scope,attr) ::= "(getCharIndex()-1)"
1355lexerRulePropertyRef_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
1359ruleSetPropertyRef_tree(scope,attr,expr) ::= "retval.tree =<expr>"
1360ruleSetPropertyRef_st(scope,attr,expr) ::= "retval.st =<expr>"
1361
1362/** How to execute an action (only when not backtracking) */
1363execAction(action) ::= <<
1364<if(backtracking)>
1365if ( <actions.(actionScope).synpredgate> ) {
1366  <action>
1367}
1368<else>
1369<action>
1370<endif>
1371>>
1372
1373/** How to always execute an action even when backtracking */
1374execForcedAction(action) ::= "<action>"
1375
1376// M I S C (properties, etc...)
1377
1378bitset(name, words64) ::= <<
1379val <name> = new BitSet(Array[Long](<words64:{it | <it>L};separator=",">))<\n>
1380>>
1381
1382codeFileExtension() ::= ".scala"
1383
1384true_value() ::= "true"
1385false_value() ::= "false"
1386