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