1/* [The "BSD license"]
2 Copyright (c) 2008 Erik van Bilsen
3 Copyright (c) 2007-2008 Johannes Luber
4 Copyright (c) 2005-2007 Kunle Odutola
5 Copyright (c) 2005-2006 Terence Parr
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12    notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16 3. The name of the author may not be used to endorse or promote products
17    derived from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
30group Delphi;
31
32csharpTypeInitMap ::= [
33  "int":"0",
34  "uint":"0",
35  "long":"0",
36  "ulong":"0",
37  "float":"0.0",
38  "double":"0.0",
39  "bool":"False",
40  "byte":"0",
41  "sbyte":"0",
42  "short":"0",
43  "ushort":"0",
44  "char":"#0",
45  "string":"''",
46  "String":"''",
47  default:"nil" // anything other than an atomic type
48]
49
50/** The overall file structure of a recognizer; stores methods for rules
51 *  and cyclic DFAs plus support code.
52 *  LEXER (Boolean): should we generate lexer code?
53 *  PARSER (Boolean): should we generate parser code?
54 *  TREE_PARSER (Boolean): should we generate tree parser code?
55 *  actionScope (String): 'lexer', 'parser', 'tree_parser' or custom scope
56 *  actions (HashMap):
57 *  docComment (String): document comment
58 *  recognizer (Object): recognizer class generator
59 *  name (String): name of grammar
60 *  tokens (HashMap<name: String, type: Integer>):
61 *  tokenNames:
62 *  rules:
63 *  cyclicDFAs:
64 *  bitsets:
65 *  buildTemplate (Boolean): should we generate a string template?
66 *  buildAST (Boolean): should we generate an AST?
67 *  rewriteMode (Boolean): are we rewriteing nodes?
68 *  profile (Boolean):
69 *  backtracking (Boolean): backtracking mode?
70 *  synpreds (): syntactic predicates
71 *  memoize (Boolean): should we memoize?
72 *  numRules (Integer): number of rules
73 *  fileName (String): fully qualified name of original .g file
74 *  ANTLRVersion (String): ANTLR version in Major.Minor.Build format
75 *  generatedTimestamp (String): date/time when the file is generated
76 *  trace (Boolean): should we trace input/output?
77 *  scopes:
78 *  superClass (String): name of base class, or empty string
79 *  literals:
80 */
81outputFile(LEXER,PARSER,TREE_PARSER, actionScope, actions,
82           docComment, recognizer,
83           name, tokens, tokenNames, rules, cyclicDFAs,
84     bitsets, buildTemplate, buildAST, rewriteMode, profile,
85     backtracking, synpreds, memoize, numRules,
86     fileName, ANTLRVersion, generatedTimestamp, trace,
87     scopes, superClass, literals) ::=
88<<
89unit <name>;
90
91{$HINTS OFF}
92
93// $ANTLR <ANTLRVersion> <fileName> <generatedTimestamp>
94
95<actions.(actionScope).header>
96
97interface
98
99<@imports>
100uses<\n>
101<@end>
102  <actions.(actionScope).usesInterface>
103<if(TREE_PARSER)>
104  Antlr.Runtime.Tree,<\n>
105<endif>
106  Antlr.Runtime,
107  Antlr.Runtime.Collections,
108  Antlr.Runtime.Tools;
109
110<docComment>
111<recognizer>
112>>
113
114/** Generates source code for the lexer class
115 * grammar (Grammar object)
116 */
117lexer(grammar, name, tokens, scopes, rules, numRules, labelType="Token",
118      filterMode, superClass="Lexer") ::= <<
119type
120  I<grammar.recognizerName> = interface(I<@superClassName><superClass><@end>)
121  end;
122
123  T<grammar.recognizerName> = class(T<@superClassName><superClass><@end>, I<grammar.recognizerName>)
124  strict private
125    FCnt: array [0..<grammar.numberOfDecisions>] of Byte;
126    FLA: array [0..<grammar.numberOfDecisions>, 0..255] of Integer;
127    FException: ERecognitionException;
128    procedure InitializeCyclicDFAs;
129  <cyclicDFAs:cyclicDFADeclaration()>
130  public
131    const
132      <tokens:{<it.name> = <it.type>;}; separator="\n">
133    <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}>
134  strict private
135    <actions.(actionScope).memberDeclarations>
136  public
137    // delegates
138    <grammar.delegates: {g|<g:delegateName()>: I<superClass>; {<g.recognizerName>}}; separator="\n">
139  public
140    // delegators
141    <grammar.delegators: {g|<g:delegateName()>: Pointer; {<g.recognizerName>}}; separator="\n">
142    <last(grammar.delegators):{g|gParent: Pointer; {<g.recognizerName>}}>
143  protected
144    { IBaseRecognizer }
145    function GetGrammarFileName: String; override;
146<if(filterMode)>
147    function AlreadyParsedRule(const Input: IIntStream;
148      const RuleIndex: Integer): Boolean; override;
149    procedure Memoize(const Input: IIntStream; const RuleIndex,
150      RuleStartIndex: Integer); override;
151  protected
152    { ILexer }
153    function NextToken: IToken; override;<\n>
154<endif>
155  protected
156    { ILexer }
157    procedure DoTokens; override;
158  public
159    constructor Create; overload;
160    constructor Create(const AInput: ICharStream<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload;
161    constructor Create(const AInput: ICharStream; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload;
162
163    <rules: {r | <if(!r.ruleDescriptor.isSynPred)><lexerRuleDeclaration(r)><endif>}>
164    <synpreds:{p | <lexerSynpredDeclaration(p)>}; separator="\n">
165  end;
166
167implementation
168
169uses
170  <grammar.delegates: {g|<g.recognizerName>,}; separator="\n">
171  <grammar.delegators: {g|<g.recognizerName>,}; separator="\n">
172  <actions.(actionScope).usesImplementation>
173  SysUtils,
174  StrUtils,
175  Math;
176
177{ T<grammar.recognizerName> }
178
179constructor T<grammar.recognizerName>.Create;
180begin
181  InitializeCyclicDFAs;
182end;
183
184constructor T<grammar.recognizerName>.Create(const AInput: ICharStream<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>);
185begin
186  Create(AInput, nil<grammar.delegators:{g|, A<g:delegateName()>}>);
187end;
188
189constructor T<grammar.recognizerName>.Create(const AInput: ICharStream; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>);
190begin
191  inherited Create(AInput, AState);
192  InitializeCyclicDFAs; { TODO: Necessary in Delphi??? Not removed yet. }
193  <if(memoize)>
194  <if(grammar.grammarIsRoot)>
195  State.RuleMemoCount := <numRules>+1;<\n> <! index from 1..n !>
196  <endif>
197  <endif>
198  <grammar.directDelegates:
199   {g|<g:delegateName()> := T<g.recognizerName>.Create(AInput, State<trunc(g.delegators):{p|, <p:delegateName()>}>, Self);}; separator="\n">
200  <grammar.delegators:
201   {g|<g:delegateName()> := Pointer(A<g:delegateName()>);}; separator="\n">
202  <last(grammar.delegators):{g|gParent := Pointer(A<g:delegateName()>);}>
203  <actions.(actionScope).memberInitializations>
204end;
205<actions.(actionScope).memberImplementations>
206function T<grammar.recognizerName>.GetGrammarFileName: String;
207begin
208  Result := '<fileName>';
209end;
210
211<if(filterMode)>
212<filteringNextToken()>
213<endif>
214
215<rules; separator="\n\n">
216<synpreds:{p | <lexerSynpred(p)>}>
217
218procedure T<grammar.recognizerName>.InitializeCyclicDFAs;
219begin
220  <cyclicDFAs:{dfa | FDFA<dfa.decisionNumber> := TDFA<dfa.decisionNumber>.Create(Self<@debugAddition()>);}; separator="\n">
221  <cyclicDFAs:{dfa | <if(dfa.specialStateSTs)>FDFA<dfa.decisionNumber>.SpecialStateTransitionHandler := DFA<dfa.decisionNumber>_SpecialStateTransition;<endif>}; separator="\n">
222end;
223
224<cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !>
225end.>>
226
227lexerRuleDeclaration(rule) ::= <<
228procedure m<rule.ruleName>(<rule.ruleDescriptor.parameterScope:parameterScope(scope=rule)>);<\n>
229>>
230
231/** A override of Lexer.nextToken() that backtracks over mTokens() looking
232 *  for matches.  No error can be generated upon error; just rewind, consume
233 *  a token and then try again.  backtracking needs to be set as well.
234 *
235 *  Make rule memoization happen only at levels above 1 as we start mTokens
236 *  at backtracking==1.
237 */
238filteringNextToken() ::= <<
239function T<grammar.recognizerName>.NextToken: IToken;
240var
241  M: Integer;
242begin
243  while (True) do
244  begin
245    if (Input.LA(1) = Integer(cscEOF)) then
246      Exit(TToken.EOF_TOKEN);
247
248    State.Token := nil;
249    State.Channel := TToken.DEFAULT_CHANNEL;
250    State.TokenStartCharIndex := Input.Index;
251    State.TokenStartCharPositionInLine := Input.CharPositionInLine;
252    State.TokenStartLine := Input.Line;
253    State.Text := '';
254    try
255      M := Input.Mark();
256      State.Backtracking := 1; <! means we won't throw slow exception !>
257      State.Failed := False;
258      mTokens();
259      State.Backtracking := 0;
260<!
261      mTokens backtracks with synpred at backtracking==2
262            and we set the synpredgate to allow actions at level 1.
263!>
264      if (State.Failed) then
265      begin
266        Input.Rewind(M);
267        Input.Consume; <! // advance one char and try again !>
268      end
269      else
270      begin
271        Emit;
272        Exit(State.Token);
273      end;
274    except
275      on RE: ERecognitionException do
276      begin
277        // shouldn't happen in backtracking mode, but...
278        ReportError(RE);
279        Recover(RE);
280      end;
281    end;
282  end;
283end;
284
285function T<grammar.recognizerName>.AlreadyParsedRule(const Input: IIntStream;
286  const RuleIndex: Integer): Boolean;
287begin
288  if (State.Backtracking > 1) then
289    Result := inherited AlreadyParsedRule(Input, RuleIndex)
290  else
291    Result := False;
292end;
293
294procedure T<grammar.recognizerName>.Memoize(const Input: IIntStream; const RuleIndex,
295  RuleStartIndex: Integer);
296begin
297  if (State.Backtracking > 1) then
298    inherited Memoize(Input, RuleIndex, RuleStartIndex);
299end;
300
301>>
302
303filteringActionGate() ::= "(State.Backtracking = 1)"
304
305/** How to generate a parser */
306genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules,
307              bitsets, inputStreamType, superClass, filterMode,
308              ASTLabelType="ANTLRInterface", labelType, members, rewriteElementType) ::= <<
309type
310  <rules: {r | <genericParserRuleReturnType(rule=r, ruleDescriptor=r.ruleDescriptor)>}>
311  I<grammar.recognizerName> = interface(I<@superClassName><superClass><@end>)
312    <rules: {r | <genericParserRuleInterface(rule=r, ruleDescriptor=r.ruleDescriptor)>}>
313  end;
314
315  T<grammar.recognizerName> = class(T<@superClassName><superClass><@end>, I<grammar.recognizerName>)
316<if(grammar.grammarIsRoot)>
317  public
318    const
319      TOKEN_NAMES: array [0..<length(tokenNames)>+3] of String = (
320        '\<invalid>',
321        '\<EOR>',
322        '\<DOWN>',
323        '\<UP>',
324        <tokenNames; separator=",\n">);<\n>
325<endif>
326  public
327    const
328      <tokens:{<it.name> = <it.type>;}; separator="\n">
329  public
330    // delegates
331    <grammar.delegates: {g|<g:delegateName()>: I<superClass>; {<g.recognizerName>}}; separator="\n">
332  public
333    // delegators
334    <grammar.delegators: {g|<g:delegateName()>: Pointer; {<g.recognizerName>}}; separator="\n">
335    <last(grammar.delegators):{g|gParent: Pointer; {<g.recognizerName>}}>
336
337    <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScopeDeclaration(scope=it)><endif>}>
338<@members>
339    <! WARNING. bug in ST: this is cut-n-paste into Dbg.stg !>
340  public
341    constructor Create(const AInput: <inputStreamType><grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload;
342    constructor Create(const AInput: <inputStreamType>; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload;
343<@end>
344  protected
345    { IBaseRecognizer }
346    function GetTokenNames: TStringArray; override;
347    function GetGrammarFileName: String; override;
348  strict private
349    <actions.(actionScope).memberDeclarations>
350  <rules: {r | <genericParserRuleDeclaration(rule=r, ruleDescriptor=r.ruleDescriptor)>}>
351
352<! generate rule/method definitions for imported rules so they
353   appear to be defined in this recognizer. !>
354    // Delegated rules
355    <grammar.delegatedRules:{ruleDescriptor| <delegatedRuleDeclaration(ruleDescriptor)>}>
356
357    <synpreds:{p | <synpredDeclaration(p)>}; separator="\n">
358  <cyclicDFAs:cyclicDFADeclaration()>
359  strict private
360    FException: ERecognitionException;
361    FLA: array [0..<grammar.numberOfDecisions>, 0..255] of Integer;
362    FCnt: array [0..<grammar.numberOfDecisions>] of Byte;
363    procedure InitializeCyclicDFAs;
364<if(bitsets)>
365  public
366    class var
367      <bitsets:bitsetDecl(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>})>
368  public
369    class procedure InitializeBitsets; static;<\n>
370<endif>
371  end;
372
373implementation
374
375uses
376  <grammar.delegates: {g|<g.recognizerName>,}; separator="\n">
377  <grammar.delegators: {g|<g.recognizerName>,}; separator="\n">
378  <actions.(actionScope).usesImplementation>
379  SysUtils,
380  StrUtils,
381  Math;
382
383{ T<grammar.recognizerName> }
384
385constructor T<grammar.recognizerName>.Create(const AInput: <inputStreamType><grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>);
386begin
387  Create(AInput, TRecognizerSharedState.Create<grammar.delegators:{g|, A<g:delegateName()>}>);
388end;
389
390constructor T<grammar.recognizerName>.Create(const AInput: <inputStreamType>;
391  const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>);
392begin
393  inherited Create(AInput, AState);
394  <@membersConstructor>
395  <@end>
396  <parserCtorBody()>
397  <grammar.directDelegates:{g|<g:delegateName()> := T<g.recognizerName>.Create(Input, State<trunc(g.delegators):{p|, <p:delegateName()>}>, Self);}; separator="\n">
398  <grammar.indirectDelegates:{g | <g:delegateName()> := <g.delegator:delegateName()>.<g:delegateName()>;}; separator="\n">
399  <last(grammar.delegators):{g|gParent := Pointer(A<g:delegateName()>);}>
400  <rules: {r | <ruleAttributeScopeInit(scope=r.ruleDescriptor.ruleScope)>}>
401  <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}>
402  <actions.(actionScope).memberInitializations>
403end;
404<actions.(actionScope).memberImplementations>
405
406<grammar.delegatedRules:{ruleDescriptor| <delegatedRuleImplementation(ruleDescriptor)>}; separator="\n">
407procedure T<grammar.recognizerName>.InitializeCyclicDFAs;
408begin
409  <cyclicDFAs:{dfa | FDFA<dfa.decisionNumber> := TDFA<dfa.decisionNumber>.Create(Self);}; separator="\n">
410  <cyclicDFAs:{dfa | <if(dfa.specialStateSTs)>FDFA<dfa.decisionNumber>.SpecialStateTransitionHandler := DFA<dfa.decisionNumber>_SpecialStateTransition;<endif>}; separator="\n">
411end;
412
413<if(bitsets)>
414class procedure T<grammar.recognizerName>.InitializeBitsets;
415begin
416  <bitsets:bitset(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>}, words64=it.bits)>
417end;
418<endif>
419
420<@membersImplementation>
421 <@end>
422
423function T<grammar.recognizerName>.GetTokenNames: TStringArray;
424var
425  I: Integer;
426begin
427  SetLength(Result,Length(T<grammar.composite.rootGrammar.recognizerName>.TOKEN_NAMES));
428  for I := 0 to Length(T<grammar.composite.rootGrammar.recognizerName>.TOKEN_NAMES) - 1 do
429    Result[I] := T<grammar.composite.rootGrammar.recognizerName>.TOKEN_NAMES[I];
430end;
431
432function T<grammar.recognizerName>.GetGrammarFileName: String;
433begin
434  Result := '<fileName>';
435end;
436
437<rules; separator="\n\n">
438<synpreds:{p | <synpred(p)>}>
439
440<cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !>
441<if(bitsets)>
442initialization
443  T<grammar.recognizerName>.InitializeBitsets;<\n>
444<endif>
445end.>>
446
447delegatedRuleDeclaration(ruleDescriptor) ::= <<
448<if(ruleDescriptor.hasMultipleReturnValues)>
449function <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;<\n>
450<else>
451<if(ruleDescriptor.hasSingleReturnValue)>
452function <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;<\n>
453<else>
454procedure <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);<\n>
455<endif>
456<endif>
457>>
458
459delegatedRuleImplementation(ruleDescriptor) ::= <<
460<if(ruleDescriptor.hasMultipleReturnValues)>
461function T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;<\n>
462<else>
463<if(ruleDescriptor.hasSingleReturnValue)>
464function T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;<\n>
465<else>
466procedure T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);<\n>
467<endif>
468<endif>
469begin
470  <if(ruleDescriptor.hasReturnValue)>Result :=<endif> T<ruleDescriptor.grammar.recognizerName>(<ruleDescriptor.grammar:delegateName()>.Implementor).<ruleDescriptor.name>(<ruleDescriptor.parameterScope.attributes:{a|<a.name>}; separator=", ">);
471end;
472
473>>
474
475parserCtorBody() ::= <<
476InitializeCyclicDFAs;
477<if(memoize)>
478<if(grammar.grammarIsRoot)>
479State.RuleMemoCount := <length(grammar.allImportedRules)>+1;<\n> <! index from 1..n !>
480<endif>
481<endif>
482<grammar.delegators: {g|<g:delegateName()> := Pointer(A<g:delegateName()>);}; separator="\n">
483>>
484
485parser(grammar, name, scopes, tokens, tokenNames, rules, numRules, bitsets, ASTLabelType, superClass="Parser", labelType="Token", members={<actions.parser.members>}) ::= <<
486<genericParser(inputStreamType="ITokenStream", rewriteElementType="Token", ...)>
487>>
488
489/** How to generate a tree parser; same as parser except the input
490 *  stream is a different type.
491 */
492treeParser(grammar, name, scopes, tokens, tokenNames, globalAction, rules, numRules, bitsets, labelType={<ASTLabelType>}, ASTLabelType="object", superClass="TreeParser", members={<actions.treeparser.members>}, filterMode) ::= <<
493<genericParser(inputStreamType="ITreeNodeStream", rewriteElementType="Node", ...)>
494>>
495
496/** A simpler version of a rule template that is specific to the imaginary
497 *  rules created for syntactic predicates.  As they never have return values
498 *  nor parameters etc..., just give simplest possible method.  Don't do
499 *  any of the normal memoization stuff in here either; it's a waste.
500 *  As predicates cannot be inlined into the invoking rule, they need to
501 *  be in a rule by themselves.
502 */
503synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::=
504<<
505// $ANTLR start "<ruleName>"
506procedure T<grammar.recognizerName>.<ruleName>_fragment(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);
507var
508  Alt: array [0..<grammar.numberOfDecisions>] of Integer;
509  <ruleLabelDefVars()>
510begin
511  <ruleLabelDefs()>
512<if(trace)>
513  TraceIn('<ruleName>_fragment', <ruleDescriptor.index>);
514  try
515    <block>
516  finally
517    TraceOut('<ruleName>_fragment', <ruleDescriptor.index>);
518  end;
519<else>
520  <block>
521<endif>
522end;
523// $ANTLR end "<ruleName>"
524>>
525
526synpredDecls(name) ::= <<
527SynPredPointer <name>;<\n>
528>>
529
530synpred(name) ::= <<
531
532function T<grammar.recognizerName>.<name>: Boolean;
533var
534  Start: Integer;
535  Success: Boolean;
536begin
537  State.Backtracking := State.Backtracking + 1;
538  <@start()>
539  Start := Input.Mark;
540  try
541    <name>_fragment(); // can never throw exception
542  except
543    on RE: ERecognitionException do
544      WriteLn('Impossible: ' + RE.ToString);
545  end;
546  Success := not State.Failed;
547  Input.Rewind(Start);
548  <@stop()>
549  State.Backtracking := State.Backtracking - 1;
550  State.Failed := False;
551  Result := Success;
552end;<\n>
553>>
554
555lexerSynpred(name) ::= <<
556<synpred(name)>
557>>
558
559lexerSynpredDeclaration(name) ::= <<
560function <name>: Boolean;
561procedure <name>_fragment;
562>>
563
564synpredDeclaration(name) ::= <<
565function <name>: Boolean;
566procedure <name>_fragment;
567>>
568
569ruleMemoization(name) ::= <<
570<if(memoize)>
571if ((State.Backtracking > 0) and AlreadyParsedRule(Input, <ruleDescriptor.index>)) then
572  Exit(<ruleReturnValue()>);
573<endif>
574>>
575
576/** How to test for failure and return from rule */
577checkRuleBacktrackFailure() ::= <<
578<if(backtracking)><\n>if (State.Failed) then Exit(<ruleReturnValue()>);<\n><endif>
579>>
580
581/** This rule has failed, exit indicating failure during backtrack */
582ruleBacktrackFailure() ::= <<
583<if(backtracking)>if (State.Backtracking > 0) then
584begin
585  State.Failed := True;
586  Exit(<ruleReturnValue()>);
587end;<endif>
588>>
589
590genericParserRuleDeclaration(rule, ruleDescriptor) ::= <<
591<if(ruleDescriptor.isSynPred)>
592<else>
593<ruleAttributeScopeDeclaration(scope=ruleDescriptor.ruleScope)>
594<returnScopeDeclaration(scope=ruleDescriptor.returnScope)>
595public
596<if(ruleDescriptor.hasMultipleReturnValues)>
597  function <rule.ruleName>: I<returnType()>;<\n>
598<else>
599<if(ruleDescriptor.hasSingleReturnValue)>
600  function <rule.ruleName>: <returnType()>;<\n>
601<else>
602  procedure <rule.ruleName>;<\n>
603<endif>
604<endif>
605<endif>
606>>
607
608genericParserRuleInterface(rule, ruleDescriptor) ::= <<
609<if(ruleDescriptor.isSynPred)>
610<else>
611<if(ruleDescriptor.hasMultipleReturnValues)>
612function <rule.ruleName>: I<returnType()>;<\n>
613<else>
614<if(ruleDescriptor.hasSingleReturnValue)>
615function <rule.ruleName>: <returnType()>;<\n>
616<else>
617procedure <rule.ruleName>;<\n>
618<endif>
619<endif>
620<endif>
621>>
622
623genericParserRuleReturnType(rule, ruleDescriptor) ::= <<
624<if(ruleDescriptor.hasMultipleReturnValues)>
625<if(ruleDescriptor.isSynPred)>
626<else>
627I<returnType()> = interface(I<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope)
628end;<\n>
629<endif>
630<endif>
631>>
632
633/** How to generate code for a rule.  This includes any return type
634 *  data aggregates required for multiple return values.
635 */
636rule(ruleName,ruleDescriptor,block,emptyRule,description,exceptions,finally,memoize) ::= <<
637<ruleAttributeScope(scope=ruleDescriptor.ruleScope)>
638<returnScope(scope=ruleDescriptor.returnScope)>
639
640// $ANTLR start "<ruleName>"
641(* <fileName>:<description> *)
642<if(ruleDescriptor.hasMultipleReturnValues)>
643function T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;
644<else>
645<if(ruleDescriptor.hasSingleReturnValue)>
646function T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;
647<else>
648procedure T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);
649<endif>
650<endif>
651
652var
653<ruleDescriptor.actions.vars>
654  Locals: TLocalStorage;
655<if(ruleDescriptor.hasMultipleReturnValues)>
656  RetVal: I<returnType()>;<\n>
657<else>
658<if(ruleDescriptor.hasSingleReturnValue)>
659  RetVal: <returnType()>;<\n>
660<else>
661<endif>
662<endif>
663  Alt: array [0..<grammar.numberOfDecisions>] of Integer;
664  <ruleDeclarationVars()>
665  <ruleLabelDefVars()>
666begin
667  Locals.Initialize;
668  try
669    <if(trace)>TraceIn('<ruleName>', <ruleDescriptor.index>);<endif>
670    <ruleScopeSetUp()>
671    <ruleDeclarations()>
672    <ruleLabelDefs()>
673    <ruleDescriptor.actions.init>
674    <@preamble()>
675    try
676      try
677        <ruleMemoization(name=ruleName)>
678        <block>
679        <ruleCleanUp()>
680        <(ruleDescriptor.actions.after):execAction()>
681<if(exceptions)>
682        <exceptions:{e|<catch(decl=e.decl,action=e.action)><\n>}>
683<else>
684<if(!emptyRule)>
685<if(actions.(actionScope).rulecatch)>
686        <actions.(actionScope).rulecatch>
687<else>
688      except
689        on RE: ERecognitionException do
690        begin
691          ReportError(RE);
692          Recover(Input,RE);
693          <@setErrorReturnValue()>
694        end;<\n>
695<endif>
696<endif>
697<endif>
698      end;
699    finally
700      <if(trace)>TraceOut("<ruleName>", <ruleDescriptor.index>);<endif>
701      <memoize()>
702      <ruleScopeCleanUp()>
703      <finally>
704    end;
705    <@postamble()>
706  finally
707    Locals.Finalize;
708  end;
709  Exit(<ruleReturnValue()>);
710end;
711// $ANTLR end "<ruleName>"
712>>
713
714catch(decl,action) ::= <<
715catch (<e.decl>)
716{
717    <e.action>
718}
719>>
720
721ruleDeclarations() ::= <<
722<if(ruleDescriptor.hasMultipleReturnValues)>
723RetVal := T<returnType()>.Create;
724RetVal.Start := Input.LT(1);<\n>
725<else>
726<ruleDescriptor.returnScope.attributes:{ a |
727<a.name> := <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>;
728}>
729<endif>
730<if(memoize)>
731<ruleDescriptor.name>_StartIndex := Input.Index();
732<endif>
733>>
734
735ruleDeclarationVars() ::= <<
736<if(ruleDescriptor.hasMultipleReturnValues)>
737<else>
738<ruleDescriptor.returnScope.attributes:{ a |
739<a.name>: <a.type>;
740}>
741<endif>
742<if(memoize)>
743<ruleDescriptor.name>_StartIndex: Integer;
744<endif>
745>>
746
747ruleScopeSetUp() ::= <<
748<ruleDescriptor.useScopes:{<it>Stack.Push(T<it>Scope.Create);}; separator="\n">
749<ruleDescriptor.ruleScope:{<it.name>Stack.Push(T<it.name>Scope.Create);}; separator="\n">
750>>
751
752ruleScopeCleanUp() ::= <<
753<ruleDescriptor.useScopes:{<it>Stack.Pop();}; separator="\n">
754<ruleDescriptor.ruleScope:{<it.name>Stack.Pop;}; separator="\n">
755>>
756
757ruleLabelDefs() ::= <<
758<[ruleDescriptor.tokenLabels,ruleDescriptor.tokenListLabels]:{<it.label.text> := nil;}; separator="\n">
759<[ruleDescriptor.tokenListLabels,ruleDescriptor.ruleListLabels]:{list_<it.label.text> := nil;}; separator="\n">
760<ruleDescriptor.ruleLabels:ruleLabelDef(label=it); separator="\n">
761<ruleDescriptor.ruleListLabels:{ll|<ll.label.text> := nil;}; separator="\n">
762>>
763
764ruleLabelDefVars() ::= <<
765<[ruleDescriptor.tokenLabels,ruleDescriptor.tokenListLabels]:{<it.label.text>: I<labelType>;}; separator="\n">
766<[ruleDescriptor.tokenListLabels,ruleDescriptor.ruleListLabels]:{list_<it.label.text>: IList\<IANTLRInterface\>;}; separator="\n">
767<ruleDescriptor.ruleLabels:ruleLabelDefVar(label=it); separator="\n">
768<ruleDescriptor.ruleListLabels:{ll|<ll.label.text>: <ruleLabelType(referencedRule=ll.referencedRule)>;}; separator="\n">
769>>
770
771lexerRuleLabelDefs() ::= <<
772<[ruleDescriptor.tokenLabels,
773  ruleDescriptor.tokenListLabels,
774  ruleDescriptor.ruleLabels]
775    :{<it.label.text> := nil;}; separator="\n"
776>
777<ruleDescriptor.charLabels:{int <it.label.text>;}; separator="\n">
778<[ruleDescriptor.tokenListLabels,
779  ruleDescriptor.ruleListLabels,
780  ruleDescriptor.ruleListLabels]
781    :{List_<it.label.text> := nil;}; separator="\n"
782>
783>>
784
785lexerRuleLabelDefDeclarations() ::= <<
786<[ruleDescriptor.tokenLabels,
787  ruleDescriptor.tokenListLabels,
788  ruleDescriptor.ruleLabels]
789    :{<it.label.text>: I<labelType>;}; separator="\n"
790>
791<ruleDescriptor.charLabels:{int <it.label.text>;}; separator="\n">
792<[ruleDescriptor.tokenListLabels,
793  ruleDescriptor.ruleListLabels,
794  ruleDescriptor.ruleListLabels]
795    :{List_<it.label.text>: IList;}; separator="\n"
796>
797>>
798
799ruleReturnValue() ::= <<
800<if(!ruleDescriptor.isSynPred)>
801<if(ruleDescriptor.hasReturnValue)>
802<if(ruleDescriptor.hasSingleReturnValue)>
803<ruleDescriptor.singleValueReturnName>
804<else>
805RetVal
806<endif>
807<else>
808<! nil !>
809<endif>
810<endif>
811>>
812
813ruleCleanUp() ::= <<
814<if(ruleDescriptor.hasMultipleReturnValues)>
815<if(!TREE_PARSER)>
816RetVal.Stop := Input.LT(-1);
817<endif>
818<endif>
819>>
820
821memoize() ::= <<
822<if(memoize)>
823<if(backtracking)>
824if (State.Backtracking > 0) then
825  Memoize(Input, <ruleDescriptor.index>, <ruleDescriptor.name>_StartIndex);
826<endif>
827<endif>
828>>
829
830/** How to generate a rule in the lexer; naked blocks are used for
831 *  fragment rules.
832 */
833lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= <<
834// $ANTLR start "<ruleName>"
835<ruleDescriptor.parameterScope>
836procedure T<grammar.recognizerName>.m<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);
837var
838  <ruleDescriptor.actions.vars>
839  Locals: TLocalStorage;
840  TokenType, Channel: Integer;
841  Alt: array [0..<grammar.numberOfDecisions>] of Integer;
842  <lexerRuleLabelDefDeclarations()>
843begin
844  Locals.Initialize;
845  try
846    <ruleAttributeScope(scope=ruleDescriptor.ruleScope)>
847    <if(trace)>TraceIn("<ruleName>", <ruleDescriptor.index>);<endif>
848    <ruleScopeSetUp()>
849    <ruleDeclarations()>
850    try
851<if(nakedBlock)>
852      <ruleMemoization(name=ruleName)>
853      <lexerRuleLabelDefs()>
854      <ruleDescriptor.actions.init>
855      <block><\n>
856<else>
857      TokenType := <ruleName>;
858      Channel := DEFAULT_TOKEN_CHANNEL;
859      <ruleMemoization(name=ruleName)>
860      <lexerRuleLabelDefs()>
861      <ruleDescriptor.actions.init>
862      <block>
863      <ruleCleanUp()>
864      State.TokenType := TokenType;
865      State.Channel := Channel;
866      <(ruleDescriptor.actions.after):execAction()>
867<endif>
868    finally
869      <if(trace)>TraceOut("<ruleName>", <ruleDescriptor.index>);<endif>
870      <ruleScopeCleanUp()>
871      <memoize()>
872    end;
873  finally
874    Locals.Finalize;
875  end;
876end;
877// $ANTLR end "<ruleName>"
878>>
879
880/** How to generate code for the implicitly-defined lexer grammar rule
881 *  that chooses between lexer rules.
882 */
883tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= <<
884procedure T<grammar.recognizerName>.mTokens;
885var
886  Alt: array [0..<grammar.numberOfDecisions>] of Integer;
887begin
888  <block>
889end;
890
891procedure T<grammar.recognizerName>.DoTokens;
892begin
893  mTokens;
894end;
895>>
896
897// S U B R U L E S
898
899/** A (...) subrule with multiple alternatives */
900block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
901(* <fileName>:<description> *)
902Alt[<decisionNumber>] := <maxAlt>;
903<decls>
904<@predecision()>
905<decision>
906<@postdecision()>
907<@prebranch()>
908case Alt[<decisionNumber>] of
909  <alts:altSwitchCase()>
910end;
911<@postbranch()>
912>>
913
914/** A rule block with multiple alternatives */
915ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
916(* <fileName>:<description> *)
917Alt[<decisionNumber>] := <maxAlt>;
918<decls>
919<@predecision()>
920<decision>
921<@postdecision()>
922case Alt[<decisionNumber>] of
923  <alts:altSwitchCase()>
924end;
925>>
926
927ruleBlockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= <<
928(* <fileName>:<description> *)
929<decls>
930<@prealt()>
931<alts>
932<@postalt()>
933>>
934
935/** A special case of a (...) subrule with a single alternative */
936blockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= <<
937(* <fileName>:<description> *)
938<decls>
939<@prealt()>
940<alts>
941<@postalt()>
942>>
943
944/** A (..)+ block with 1 or more alternatives */
945positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
946(* <fileName>:<description> *)
947FCnt[<decisionNumber>] := 0;
948<decls>
949<@preloop()>
950while (True) do
951begin
952  Alt[<decisionNumber>] := <maxAlt>;
953  <@predecision()>
954  <decision>
955  <@postdecision()>
956  case Alt[<decisionNumber>] of
957    <alts:altSwitchCase()>
958  else
959    begin
960      if (FCnt[<decisionNumber>] >= 1) then
961        Break;
962      <ruleBacktrackFailure()>
963      raise EEarlyExitException.Create(<decisionNumber>, Input);
964      <@earlyExitException()>
965    end;
966  end;
967  Inc(FCnt[<decisionNumber>]);
968end;
969<@postloop()>
970>>
971
972positiveClosureBlockSingleAlt ::= positiveClosureBlock
973
974/** A (..)* block with 1 or more alternatives */
975closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= <<
976(* <fileName>:<description> *)
977<decls>
978<@preloop()>
979while (True) do
980begin
981  Alt[<decisionNumber>] := <maxAlt>;
982  <@predecision()>
983  <decision>
984  <@postdecision()>
985  case Alt[<decisionNumber>] of
986    <alts:altSwitchCase()>
987  else
988    Break;
989  end;
990end;
991<@postloop()>
992>>
993
994closureBlockSingleAlt ::= closureBlock
995
996/** Optional blocks (x)? are translated to (x|) by before code generation
997 *  so we can just use the normal block template
998 */
999optionalBlock ::= block
1000
1001optionalBlockSingleAlt ::= block
1002
1003/** A case in a switch that jumps to an alternative given the alternative
1004 *  number.  A DFA predicts the alternative and then a simple switch
1005 *  does the jump to the code that actually matches that alternative.
1006 */
1007altSwitchCase() ::= <<
1008<i>:
1009  <@prealt()>
1010  <it><\n>
1011>>
1012
1013/** An alternative is just a list of elements; at outermost level */
1014alt(elements,altNum,description,autoAST,outerAlt,treeLevel,rew) ::= <<
1015(* <fileName>:<description> *)
1016begin
1017  <@declarations()>
1018  <elements:element()>
1019  <rew>
1020  <@cleanup()>
1021end;
1022>>
1023
1024/** What to emit when there is no rewrite.  For auto build
1025 *  mode, does nothing.
1026 */
1027noRewrite(rewriteBlockLevel, treeLevel) ::= ""
1028
1029// E L E M E N T S
1030
1031/** Dump the elements one per line */
1032element() ::= <<
1033<@prematch()>
1034<it.el>
1035>>
1036
1037/** match a token optionally with a label in front */
1038tokenRef(token,label,elementIndex,terminalOptions) ::= <<
1039<if(label)><label> := <endif>Match(Input, <token>, FOLLOW_<token>_in_<ruleName><elementIndex>)<if(label)> as I<labelType><endif>;<\n><checkRuleBacktrackFailure()>
1040>>
1041
1042/** ids+=ID */
1043tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
1044<tokenRef(...)>
1045<listLabel(elem=label,...)>
1046>>
1047
1048listLabel(label,elem) ::= <<
1049if (list_<label> = nil) then list_<label> := TList\<IANTLRInterface\>.Create;
1050list_<label>.Add(<elem>);<\n>
1051>>
1052
1053/** match a character */
1054charRef(char,label) ::= <<
1055<if(label)>
1056<label> := Input.LA(1);<\n>
1057<endif>
1058Match(<char>); <checkRuleBacktrackFailure()>
1059>>
1060
1061/** match a character range */
1062charRangeRef(a,b,label) ::= <<
1063<if(label)>
1064<label> := Input.LA(1);<\n>
1065<endif>
1066MatchRange(<a>, <b>); <checkRuleBacktrackFailure()>
1067>>
1068
1069/** For now, sets are interval tests and must be tested inline */
1070matchSet(s,label,elementIndex,postmatchCode="") ::= <<
1071<if(label)>
1072<if(LEXER)>
1073<label> := Input.LA(1);<\n>
1074<else>
1075<label> := Input.LT(1) as I<labelType>;<\n>
1076<endif>
1077<endif>
1078if (<s>) then
1079begin
1080  Input.Consume;
1081  <postmatchCode>
1082  <if(!LEXER)>
1083  State.ErrorRecovery := False;<endif>
1084  <if(backtracking)>State.Failed := False;<endif>
1085end
1086else
1087begin
1088  <ruleBacktrackFailure()>
1089  FException := EMismatchedSetException.Create(nil, Input);
1090  <@mismatchedSetException()>
1091<if(LEXER)>
1092  Recover(FException);
1093  raise FException;<\n>
1094<else>
1095  raise FException;
1096  <! use following code to make it recover inline; remove throw mse;
1097  RecoverFromMismatchedSet(input,mse,FOLLOW_set_in_<ruleName><elementIndex>);
1098  !>
1099<endif>
1100end;<\n>
1101>>
1102
1103matchRuleBlockSet ::= matchSet
1104
1105matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= <<
1106<matchSet(...)>
1107<listLabel(elem=label,...)>
1108>>
1109
1110/** Match a string literal */
1111lexerStringRef(string,label,elementIndex) ::= <<
1112<if(label)>
1113Locals.AsInteger['<label>Start'] := CharIndex;
1114Match(<string>); <checkRuleBacktrackFailure()>
1115<label> := TCommonToken.Create(Input, TToken.INVALID_TOKEN_TYPE, TToken.DEFAULT_CHANNEL, Locals.AsInteger['<label>Start'], CharIndex-1);
1116<else>
1117Match(<string>); <checkRuleBacktrackFailure()>
1118<endif>
1119>>
1120
1121wildcard(label,elementIndex) ::= <<
1122<if(label)>
1123<label> := Input.LT(1) as I<labelType>;<\n>
1124<endif>
1125MatchAny(input); <checkRuleBacktrackFailure()>
1126>>
1127
1128wildcardAndListLabel(label,elementIndex) ::= <<
1129<wildcard(...)>
1130<listLabel(elem=label,...)>
1131>>
1132
1133/** Match . wildcard in lexer */
1134wildcardChar(label, elementIndex) ::= <<
1135<if(label)>
1136<label> := Input.LA(1);<\n>
1137<endif>
1138MatchAny(); <checkRuleBacktrackFailure()>
1139>>
1140
1141wildcardCharListLabel(label, elementIndex) ::= <<
1142<wildcardChar(...)>
1143<listLabel(elem=label,...)>
1144>>
1145
1146/** Match a rule reference by invoking it possibly with arguments
1147 *  and a return value or values.  The 'rule' argument was the
1148 *  target rule name, but now is type Rule, whose toString is
1149 *  same: the rule name.  Now though you can access full rule
1150 *  descriptor stuff.
1151 */
1152ruleRef(rule,label,elementIndex,args,scope) ::= <<
1153PushFollow(FOLLOW_<rule.name>_in_<ruleName><elementIndex>);
1154<if(label)>
1155<label> := <if(scope)><scope:delegateName()>.<endif><rule.name>(<args; separator=", ">);<\n>
1156<else>
1157<if(scope)>T<scope.recognizerName>(IANTLRObject(<scope:delegateName()>).Implementor).<endif><rule.name>(<args; separator=", ">);<\n>
1158<endif>
1159State.FollowingStackPointer := State.FollowingStackPointer - 1;
1160<checkRuleBacktrackFailure()>
1161>>
1162
1163/** ids+=r */
1164ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= <<
1165<ruleRef(...)>
1166<listLabel(elem=label,...)>
1167>>
1168
1169/** A lexer rule reference.
1170 *
1171 *  The 'rule' argument was the target rule name, but now
1172 *  is type Rule, whose toString is same: the rule name.
1173 *  Now though you can access full rule descriptor stuff.
1174 */
1175lexerRuleRef(rule,label,args,elementIndex,scope) ::= <<
1176<if(label)>
1177Locals.AsInteger['<label>Start<elementIndex>'] := CharIndex;
1178<if(scope)><scope:delegateName()>.<endif>m<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()>
1179<label> := TCommonToken.Create(Input, TToken.INVALID_TOKEN_TYPE, TToken.DEFAULT_CHANNEL,
1180  Locals.AsInteger['<label>Start<elementIndex>'], CharIndex - 1);
1181<else>
1182<if(scope)>(<scope:delegateName()>.Implementor as T<scope.recognizerName>).<endif>m<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()>
1183<endif>
1184>>
1185
1186/** i+=INT in lexer */
1187lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= <<
1188<lexerRuleRef(...)>
1189<listLabel(elem=label,...)>
1190>>
1191
1192/** EOF in the lexer */
1193lexerMatchEOF(label,elementIndex) ::= <<
1194<if(label)>
1195Locals.AsInteger['<label>Start<elementIndex>'] := CharIndex;
1196Match(EOF); <checkRuleBacktrackFailure()>
1197Locals['<label>'] := TCommonToken.Create(Input, EOF, TToken.DEFAULT_CHANNEL, Locals.AsInteger['<label>Start<elementIndex>'], CharIndex-1);
1198<else>
1199Match(EOF); <checkRuleBacktrackFailure()>
1200<endif>
1201>>
1202
1203/** match ^(root children) in tree parser */
1204tree(root, actionsAfterRoot, children, nullableChildList,
1205     enclosingTreeLevel, treeLevel) ::= <<
1206<root:element()>
1207<actionsAfterRoot:element()>
1208<if(nullableChildList)>
1209if (Input.LA(1) = TToken.DOWN) then
1210begin
1211  Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()>
1212  <children:element()>
1213  Match(Input, TToken.UP, nil); <checkRuleBacktrackFailure()>
1214end;
1215<else>
1216Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()>
1217<children:element()>
1218Match(Input, TToken.UP, nil);<\n><checkRuleBacktrackFailure()>
1219<endif>
1220>>
1221
1222/** Every predicate is used as a validating predicate (even when it is
1223 *  also hoisted into a prediction expression).
1224 */
1225validateSemanticPredicate(pred,description) ::= <<
1226if (not (<evalPredicate(...)>)) then
1227begin
1228  <ruleBacktrackFailure()>
1229  raise EFailedPredicateException.Create(Input, '<ruleName>', '<description>');
1230end;<\n>
1231>>
1232
1233// F i x e d  D F A  (if-then-else)
1234
1235dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
1236FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>);<\n>
1237<edges; separator="\nelse ">
1238else
1239begin
1240<if(eotPredictsAlt)>
1241  Alt[<decisionNumber>] := <eotPredictsAlt>;<\n>
1242<else>
1243  <ruleBacktrackFailure()>
1244  raise ENoViableAltException.Create('<description>', <decisionNumber>, <stateNumber>, Input);<\n>
1245<endif>
1246end;
1247>>
1248
1249/** Same as a normal DFA state except that we don't examine lookahead
1250 *  for the bypass alternative.  It delays error detection but this
1251 *  is faster, smaller, and more what people expect.  For (X)? people
1252 *  expect "if ( LA(1)==X ) match(X);" and that's it.
1253 */
1254dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
1255FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>);<\n>
1256<edges; separator="\nelse ">;
1257>>
1258
1259/** A DFA state that is actually the loopback decision of a closure
1260 *  loop.  If end-of-token (EOT) predicts any of the targets then it
1261 *  should act like a default clause (i.e., no error can be generated).
1262 *  This is used only in the lexer so that for ('a')* on the end of a rule
1263 *  anything other than 'a' predicts exiting.
1264 */
1265dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
1266FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>);
1267<edges; separator="\nelse ">;<\n>
1268<if(eotPredictsAlt)>
1269<if(!edges)>
1270Alt[<decisionNumber>] := <eotPredictsAlt>; <! if no edges, don't gen ELSE !>
1271<else>
1272else
1273begin
1274  Alt[<decisionNumber>] := <eotPredictsAlt>;
1275end;<\n>
1276<endif>
1277<endif>
1278>>
1279
1280/** An accept state indicates a unique alternative has been predicted */
1281dfaAcceptState(alt) ::= "Alt[<decisionNumber>] := <alt>;"
1282
1283/** A simple edge with an expression.  If the expression is satisfied,
1284 *  enter to the target state.  To handle gated productions, we may
1285 *  have to evaluate some predicates for this edge.
1286 */
1287dfaEdge(labelExpr, targetState, predicates) ::= <<
1288if ((<labelExpr>)<if(predicates)> and (<predicates>)<endif>) then
1289begin
1290  <targetState>
1291end <! no ; here !>
1292>>
1293
1294// F i x e d  D F A  (switch case)
1295
1296/** A DFA state where a SWITCH may be generated.  The code generator
1297 *  decides if this is possible: CodeGenerator.canGenerateSwitch().
1298 */
1299dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
1300case Input.LA(<k>) of
1301  <edges; separator="\n">
1302else
1303  begin
1304<if(eotPredictsAlt)>
1305    Alt[<decisionNumber>] := <eotPredictsAlt>;
1306<else>
1307    <ruleBacktrackFailure()>
1308    <@noViableAltException()>
1309    raise ENoViableAltException.Create('<description>', <decisionNumber>, <stateNumber>, Input);<\n>
1310<endif>
1311  end;
1312end;<\n>
1313>>
1314
1315dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
1316case Input.LA(<k>) of
1317  <edges; separator="\n">
1318end;<\n>
1319>>
1320
1321dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= <<
1322case Input.LA(<k>) of
1323  <edges; separator="\n"><\n>
1324<if(eotPredictsAlt)>
1325else
1326  Alt[<decisionNumber>] := <eotPredictsAlt>;<\n>
1327<endif>
1328end;<\n>
1329>>
1330
1331dfaEdgeSwitch(labels, targetState) ::= <<
1332<labels:{<it>}; separator=",\n">:
1333  begin
1334    <targetState>
1335  end;
1336>>
1337
1338// C y c l i c  D F A
1339
1340/** The code to initiate execution of a cyclic DFA; this is used
1341 *  in the rule to predict an alt just like the fixed DFA case.
1342 *  The <name> attribute is inherited via the parser, lexer, ...
1343 */
1344dfaDecision(decisionNumber,description) ::= <<
1345Alt[<decisionNumber>] := FDFA<decisionNumber>.Predict(Input);
1346>>
1347
1348/* Dump DFA tables.
1349 */
1350cyclicDFADeclaration(dfa) ::= <<
1351strict protected
1352  type
1353    TDFA<dfa.decisionNumber> = class(TDFA)
1354    protected
1355      { IDFA }
1356      function Description: String; override;
1357    public
1358      constructor Create(const ARecognizer: IBaseRecognizer);
1359    end;
1360  var
1361    FDFA<dfa.decisionNumber>: IDFA;
1362<if(dfa.specialStateSTs)>
1363strict protected
1364  function DFA<dfa.decisionNumber>_SpecialStateTransition(const DFA: IDFA; S: Integer;
1365    const AInput: IIntStream): Integer;<endif>
1366>>
1367
1368cyclicDFA(dfa) ::= <<
1369{ T<grammar.recognizerName>.TDFA<dfa.decisionNumber> }
1370
1371constructor T<grammar.recognizerName>.TDFA<dfa.decisionNumber>.Create(const ARecognizer: IBaseRecognizer);
1372const
1373  DFA<dfa.decisionNumber>_EOT = '<dfa.javaCompressedEOT; wrap="'+\n    '">';
1374  DFA<dfa.decisionNumber>_EOF = '<dfa.javaCompressedEOF; wrap="'+\n    '">';
1375  DFA<dfa.decisionNumber>_MIN = '<dfa.javaCompressedMin; wrap="'+\n    '">';
1376  DFA<dfa.decisionNumber>_MAX = '<dfa.javaCompressedMax; wrap="'+\n    '">';
1377  DFA<dfa.decisionNumber>_ACCEPT = '<dfa.javaCompressedAccept; wrap="'+\n    '">';
1378  DFA<dfa.decisionNumber>_SPECIAL = '<dfa.javaCompressedSpecial; wrap="'+\n    '">';
1379  DFA<dfa.decisionNumber>_TRANSITION: array [0..<length(dfa.javaCompressedTransition)>-1] of String = (
1380    <dfa.javaCompressedTransition:{s|'<s; wrap="'+\n'">'}; separator=",\n">);
1381begin
1382  inherited Create;
1383  Recognizer := ARecognizer;
1384  DecisionNumber := <dfa.decisionNumber>;
1385  EOT := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_EOT);
1386  EOF := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_EOF);
1387  Min := TDFA.UnpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_MIN);
1388  Max := TDFA.UnpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_MAX);
1389  Accept := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_ACCEPT);
1390  Special := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_SPECIAL);
1391  Transition := TDFA.UnpackEncodedStringArray(DFA<dfa.decisionNumber>_TRANSITION);
1392end;
1393
1394function T<grammar.recognizerName>.TDFA<dfa.decisionNumber>.Description: String;
1395begin
1396  Result := '<dfa.description>';
1397end;<\n>
1398<if(dfa.specialStateSTs)>
1399function T<grammar.recognizerName>.DFA<dfa.decisionNumber>_SpecialStateTransition(const DFA: IDFA; S: Integer;
1400  const AInput: IIntStream): Integer;
1401var
1402  Locals: TLocalStorage;
1403  <if(LEXER)>
1404  Input: IIntStream;
1405  <endif>
1406  <if(PARSER)>
1407  Input: ITokenStream;
1408  <endif>
1409  <if(TREE_PARSER)>
1410  Input: ITreeNodeStream;
1411  <endif>
1412  _S: Integer;
1413  NVAE: ENoViableAltException;
1414begin
1415  Result := -1;
1416  Locals.Initialize;
1417  try
1418    <if(LEXER)>
1419    Input := AInput;
1420    <endif>
1421    <if(PARSER)>
1422    Input := AInput as ITokenStream;
1423    <endif>
1424    <if(TREE_PARSER)>
1425    Input := AInput as ITreeNodeStream;
1426    <endif>
1427    _S := S;
1428    case S of
1429      <dfa.specialStateSTs:{state | <i0>: begin<! compressed special state numbers 0..n-1 !>
1430     <state> <\n>   end;}; separator="\n">
1431    end;
1432<if(backtracking)>
1433    if (State.Backtracking > 0) then
1434    begin
1435      State.Failed := True;
1436      Exit(-1);
1437    end;<\n>
1438<endif>
1439    NVAE := ENoViableAltException.Create(DFA.Description, <dfa.decisionNumber>, _S, Input);
1440    DFA.Error(NVAE);
1441    raise NVAE;
1442  finally
1443    Locals.Finalize;
1444  end;
1445end;<\n>
1446<endif>
1447>>
1448
1449/** A state in a cyclic DFA; it's a special state and part of a big switch on
1450 *  state.
1451 */
1452cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= <<
1453FLA[<decisionNumber>,<stateNumber>] := Input.LA(1);<\n>
1454<if(semPredState)> <! get next lookahead symbol to test edges, then rewind !>
1455Locals.AsInteger['index<decisionNumber>_<stateNumber>'] := Input.Index;
1456Input.Rewind;<\n>
1457<endif>
1458S := -1;
1459<edges; separator="\nelse ">;
1460<if(semPredState)> <! return input cursor to state before we rewound !>
1461Input.Seek(Locals.AsInteger['index<decisionNumber>_<stateNumber>']);<\n>
1462<endif>
1463if (S >= 0) then
1464  Exit(S);
1465>>
1466
1467/** Just like a fixed DFA edge, test the lookahead and indicate what
1468 *  state to jump to next if successful.
1469 */
1470cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= <<
1471if ((<labelExpr>)<if(predicates)> and (<predicates>)<endif>) then
1472  S := <targetStateNumber>
1473>>
1474
1475/** An edge pointing at end-of-token; essentially matches any char;
1476 *  always jump to the target.
1477 */
1478eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= <<
1479S := <targetStateNumber>;<\n>
1480>>
1481
1482
1483// D F A  E X P R E S S I O N S
1484
1485andPredicates(left,right) ::= "((<left>) and (<right>))"
1486
1487orPredicates(operands) ::= "((<first(operands)>)<rest(operands):{o | or (<o>)}>)"
1488
1489notPredicate(pred) ::= "!(<evalPredicate(...)>)"
1490
1491evalPredicate(pred,description) ::= "(<pred>)"
1492
1493evalSynPredicate(pred,description) ::= "<pred>()"
1494
1495lookaheadTest(atom,k,atomAsInt) ::= "FLA[<decisionNumber>,<stateNumber>] = <atomAsInt>"
1496
1497/** Sometimes a lookahead test cannot assume that LA(k) is in a temp variable
1498 *  somewhere.  Must ask for the lookahead directly.
1499 */
1500isolatedLookaheadTest(atom,k,atomAsInt) ::= "Input.LA(<k>) = <atomAsInt>"
1501
1502lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= <<
1503((FLA[<decisionNumber>,<stateNumber>] \>= <lowerAsInt>) and (FLA[<decisionNumber>,<stateNumber>] \<= <upperAsInt>))
1504>>
1505
1506isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "(Input.LA(<k>) \>= <lowerAsInt>) and (Input.LA(<k>) \<= <upperAsInt>)"
1507
1508setTest(ranges) ::= "<ranges; separator=\") or (\">"
1509
1510// A T T R I B U T E S
1511
1512globalAttributeScope(scope) ::= <<
1513<scope.name>Stack := TStackList\<I<scope.name>Scope\>.Create;<\n>
1514<endif>
1515>>
1516
1517globalAttributeScopeDeclaration(scope) ::= <<
1518<if(scope.attributes)>
1519strict protected
1520  type
1521    I<scope.name>Scope = interface(IANTLRObject)
1522    end;
1523    T<scope.name>Scope = class(TANTLRObject, I<scope.name>Scope)
1524    protected
1525      <scope.attributes:{<it.name>: <it.type>;}; separator="\n">
1526    end;
1527strict protected
1528  <scope.name>Stack: IStackList\<I<scope.name>Scope\>;
1529<endif>
1530>>
1531
1532ruleAttributeScopeDeclaration(scope) ::= <<
1533<if(scope.attributes)>
1534strict protected
1535  type
1536    I<scope.name>Scope = interface(IANTLRObject)
1537    end;
1538    T<scope.name>Scope = class(TANTLRObject, I<scope.name>Scope)
1539    protected
1540      <scope.attributes:{<it.name>: <it.type>;}; separator="\n">
1541    end;
1542strict protected
1543  <scope.name>Stack: IStackList\<I<scope.name>Scope\>;
1544<endif>
1545>>
1546
1547ruleAttributeScope(scope) ::= <<
1548<! protected Stack <scope.name>Stack = new Stack();<\n> !>
1549>>
1550
1551ruleAttributeScopeInit(scope) ::= <<
1552<if(scope)>
1553<scope.name>Stack := TStackList\<I<scope.name>Scope\>.Create;<\n>
1554<endif>
1555>>
1556
1557returnStructName() ::= "<it.name>_return"
1558
1559returnType() ::= <<
1560<if(ruleDescriptor.hasMultipleReturnValues)>
1561<ruleDescriptor:returnStructName()>
1562<! I<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope !>
1563<else>
1564<if(ruleDescriptor.hasSingleReturnValue)>
1565<ruleDescriptor.singleValueReturnType>
1566<else>
1567<! Pointer/void !>
1568<endif>
1569<endif>
1570>>
1571
1572/** Generate the C# type associated with a single or multiple return
1573 *  values.
1574 */
1575ruleLabelType(referencedRule) ::= <<
1576<if(referencedRule.hasMultipleReturnValues)>
1577I<referencedRule.name>_return
1578<else>
1579<if(referencedRule.hasSingleReturnValue)>
1580<referencedRule.singleValueReturnType>
1581<else>
1582void
1583<endif>
1584<endif>
1585>>
1586
1587delegateName() ::= <<
1588<if(it.label)><it.label><else>g<it.name><endif>
1589>>
1590
1591/** Using a type to init value map, try to init a type; if not in table
1592 *  must be an object, default value is "null".
1593 */
1594initValue(typeName) ::= <<
1595<csharpTypeInitMap.(typeName)>
1596>>
1597
1598/** Define a rule label including default value */
1599ruleLabelDef(label) ::= <<
1600<label.label.text> := <initValue(typeName=ruleLabelType(referencedRule=label.referencedRule))>;<\n>
1601>>
1602
1603ruleLabelDefVar(label) ::= <<
1604<label.label.text>: <ruleLabelType(referencedRule=label.referencedRule)>;
1605>>
1606
1607/** Define a return struct for a rule if the code needs to access its
1608 *  start/stop tokens, tree stuff, attributes, ...  Leave a hole for
1609 *  subgroups to stick in members.
1610 */
1611returnScope(scope) ::= <<
1612<if(ruleDescriptor.hasMultipleReturnValues)>
1613{ T<ruleDescriptor:returnStructName()> }
1614
1615<scope.attributes:{public <it.decl>;}; separator="\n">
1616<@ruleReturnMembers()>
1617<endif>
1618>>
1619
1620returnScopeDeclaration(scope) ::= <<
1621<if(ruleDescriptor.hasMultipleReturnValues)>
1622public
1623  type
1624    T<ruleDescriptor:returnStructName()> = class(T<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope, I<ruleDescriptor:returnStructName()>)
1625    <scope.attributes:{public <it.decl>;}; separator="\n">
1626    <@ruleReturnMembers()>
1627    end;
1628<endif>
1629>>
1630
1631parameterScope(scope) ::= <<
1632<scope.attributes:{<it.decl>}; separator=", ">
1633>>
1634
1635parameterAttributeRef(attr) ::= "<attr.name>"
1636parameterSetAttributeRef(attr,expr) ::= "<attr.name> := <expr>;"
1637
1638scopeAttributeRef(scope,attr,index,negIndex) ::= <<
1639<if(negIndex)>
1640(<scope>Stack[<scope>Stack.Count-<negIndex>-1] as T<scope>Scope).<attr.name>
1641<else>
1642<if(index)>
1643(<scope>Stack[<index>] as T<scope>Scope).<attr.name>
1644((<scope>_scope)<scope>_stack[<index>]).<attr.name>
1645<else>
1646(<scope>Stack.Peek.Implementor as T<scope>Scope).<attr.name>
1647<endif>
1648<endif>
1649>>
1650
1651scopeSetAttributeRef(scope,attr,expr,index,negIndex) ::= <<
1652<if(negIndex)>
1653(<scope>Stack[<scope>Stack.Count-<negIndex>-1] as T<scope>Scope).<attr.name> := <expr>;<\n>
1654<else>
1655<if(index)>
1656(<scope>Stack[<index>] as T<scope>Scope).<attr.name> := <expr>;<\n>
1657<else>
1658(<scope>Stack.Peek.Implementor as T<scope>Scope).<attr.name> := <expr>;<\n>
1659<endif>
1660<endif>
1661>>
1662
1663/** $x is either global scope or x is rule with dynamic scope; refers
1664 *  to stack itself not top of stack.  This is useful for predicates
1665 *  like {$function.size()>0 && $function::name.equals("foo")}?
1666 */
1667isolatedDynamicScopeRef(scope) ::= "<scope>Stack"
1668
1669/** reference an attribute of rule; might only have single return value */
1670ruleLabelRef(referencedRule,scope,attr) ::= <<
1671<if(referencedRule.hasMultipleReturnValues)>
1672(IfThen(Assigned(<scope>),Def(<scope>).<attr.name>,<initValue(attr.type)>))
1673<else>
1674<scope>
1675<endif>
1676>>
1677
1678returnAttributeRef(ruleDescriptor,attr) ::= <<
1679<if(ruleDescriptor.hasMultipleReturnValues)>
1680RetVal.<attr.name>
1681<else>
1682<attr.name>
1683<endif>
1684>>
1685
1686returnSetAttributeRef(ruleDescriptor,attr,expr) ::= <<
1687<if(ruleDescriptor.hasMultipleReturnValues)>
1688RetVal.<attr.name> := <expr>;
1689<else>
1690<attr.name> := <expr>;
1691<endif>
1692>>
1693
1694/** How to translate $tokenLabel */
1695tokenLabelRef(label) ::= "<label>"
1696
1697/** ids+=ID {$ids} or e+=expr {$e} */
1698listLabelRef(label) ::= "list_<label>"
1699
1700
1701// not sure the next are the right approach
1702
1703tokenLabelPropertyRef_text(scope,attr) ::= "(Def(<scope>).Text)"
1704tokenLabelPropertyRef_type(scope,attr) ::= "(Def(<scope>).TokenType)"
1705tokenLabelPropertyRef_line(scope,attr) ::= "(Def(<scope>).Line)"
1706tokenLabelPropertyRef_pos(scope,attr) ::= "(Def(<scope>).CharPositionInLine)"
1707tokenLabelPropertyRef_channel(scope,attr) ::= "(Def(<scope>).Channel)"
1708tokenLabelPropertyRef_index(scope,attr) ::= "(Def(<scope>).TokenIndex)"
1709tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree"
1710tokenLabelPropertyRef_int(scope,attr) ::= "(StrToIntDef(Def(<scope>).Text,0))"
1711
1712ruleLabelPropertyRef_start(scope,attr) ::= "(IfThen(Assigned(<scope>), Def(<scope>).Start, nil) as I<labelType>)"
1713ruleLabelPropertyRef_stop(scope,attr) ::= "(Def(<scope>).Stop as I<labelType>)"
1714ruleLabelPropertyRef_tree(scope,attr) ::= "(Def(Def(<scope>).Tree as I<ASTLabelType>))"
1715ruleLabelPropertyRef_text(scope,attr) ::= <<
1716<if(TREE_PARSER)>
1717IfThen(Assigned(<scope>), Input.TokenStream.ToString(
1718  Input.TreeAdaptor.GetTokenStartIndex(Def(<scope>).Start),
1719  Input.TreeAdaptor.GetTokenStopIndex(Def(<scope>).Start)), '')
1720<else>
1721IfThen(Assigned(<scope>), Input.ToString(
1722  (Def(<scope>).Start) as IToken,(Def(<scope>).Stop) as IToken), '')
1723<endif>
1724>>
1725ruleLabelPropertyRef_st(scope,attr) ::= "((<scope> != null) ? <scope>.ST : null)"
1726
1727/** Isolated $RULE ref ok in lexer as it's a Token */
1728lexerRuleLabel(label) ::= "<label>"
1729
1730lexerRuleLabelPropertyRef_type(scope,attr) ::= "(Def(<scope>).TokenType)"
1731lexerRuleLabelPropertyRef_line(scope,attr) ::= "(Def(<scope>).Line)"
1732lexerRuleLabelPropertyRef_pos(scope,attr) ::= "(IfThen(Assigned(<scope>),Def(<scope>).CharPositionInLine,-1))"
1733lexerRuleLabelPropertyRef_channel(scope,attr) ::= "(Def(<scope>).Channel)"
1734lexerRuleLabelPropertyRef_index(scope,attr) ::= "(Def(<scope>).TokenIndex)"
1735lexerRuleLabelPropertyRef_text(scope,attr) ::= "(Def(<scope>).Text)"
1736lexerRuleLabelPropertyRef_int(scope,attr) ::= "(StrToIntDef(Def(<scope>).Text,0))"
1737
1738// Somebody may ref $template or $tree or $stop within a rule:
1739rulePropertyRef_start(scope,attr) ::= "(RetVal.Start as I<labelType>)"
1740rulePropertyRef_stop(scope,attr) ::= "(RetVal.Stop as I<labelType>)"
1741rulePropertyRef_tree(scope,attr) ::= "(RetVal.Tree as I<ASTLabelType>)"
1742rulePropertyRef_text(scope,attr) ::= <<
1743<if(TREE_PARSER)>
1744Input.TokenStream.ToString(
1745  Input.TreeAdaptor.GetTokenStartIndex(RetVal.Start),
1746  Input.TreeAdaptor.GetTokenStopIndex(RetVal.Start))
1747<else>
1748Input.ToString(RetVal.Start as IToken,Input.LT(-1))
1749<endif>
1750>>
1751rulePropertyRef_st(scope,attr) ::= "RetVal.ST"
1752
1753lexerRulePropertyRef_text(scope,attr) ::= "Text"
1754lexerRulePropertyRef_type(scope,attr) ::= "TokenType"
1755lexerRulePropertyRef_line(scope,attr) ::= "State.TokenStartLine"
1756lexerRulePropertyRef_pos(scope,attr) ::= "State.TokenStartCharPositionInLine"
1757lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer
1758lexerRulePropertyRef_channel(scope,attr) ::= "Channel"
1759lexerRulePropertyRef_start(scope,attr) ::= "State.TokenStartCharIndex"
1760lexerRulePropertyRef_stop(scope,attr) ::= "(CharIndex-1)"
1761lexerRulePropertyRef_int(scope,attr) ::= "StrToInt(<scope>.Text)"
1762
1763// setting $st and $tree is allowed in local rule. everything else
1764// is flagged as error
1765ruleSetPropertyRef_tree(scope,attr,expr) ::= "RetVal.Tree := <expr>;"
1766ruleSetPropertyRef_st(scope,attr,expr) ::= "RetVal.ST := <expr>;"
1767
1768
1769/** How to execute an action (only when not backtracking) */
1770execAction(action) ::= <<
1771<if(backtracking)>
1772<if(actions.(actionScope).synpredgate)>
1773if (<actions.(actionScope).synpredgate>) then
1774begin
1775  <action>
1776end;
1777<else>
1778if (State.Backtracking = 0) then
1779begin
1780  <action>
1781end;<\n>
1782<endif>
1783<else>
1784<action>
1785<endif>
1786>>
1787
1788
1789/** How to always execute an action even when backtracking */
1790execForcedAction(action) ::= "<action>"
1791
1792// M I S C (properties, etc...)
1793
1794bitset(name, words64) ::= <<
1795<name> := TBitSet.Create([<words64:{<it>};separator=",">]);<\n>
1796>>
1797
1798bitsetDecl(name) ::= <<
1799<name>: IBitSet;<\n>
1800>>
1801
1802codeFileExtension() ::= ".pas"
1803
1804true() ::= "True"
1805false() ::= "False"
1806