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