1 unit Antlr.Runtime;
2 (*
3 [The "BSD licence"]
4 Copyright (c) 2008 Erik van Bilsen
5 Copyright (c) 2005-2007 Kunle Odutola
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
15    the documentation and/or other materials provided with the
16    distribution.
17 3. The name of the author may not be used to endorse or promote products
18    derived from this software without specific prior WRITTEN permission.
19 4. Unless explicitly state otherwise, any contribution intentionally
20    submitted for inclusion in this work to the copyright owner or licensor
21    shall be under the terms and conditions of this license, without any
22    additional terms or conditions.
23 
24 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *)
35 
36 interface
37 
38 {$IF CompilerVersion < 20}
39 {$MESSAGE ERROR 'You need Delphi 2009 or higher to use the Antlr runtime'}
40 {$IFEND}
41 
42 uses
43   SysUtils,
44   Classes,
45   Generics.Defaults,
46   Generics.Collections,
47   Antlr.Runtime.Tools,
48   Antlr.Runtime.Collections;
49 
50 type
51   TCharStreamConstants = (cscEOF = -1);
52 
53 type
54   ERecognitionException = class;
55   ENoViableAltException = class;
56 
57   /// <summary>
58   /// A simple stream of integers. This is useful when all we care about is the char
59   /// or token type sequence (such as for interpretation).
60   /// </summary>
61   IIntStream = interface(IANTLRInterface)
62   ['{6B851BDB-DD9C-422B-AD1E-567E52D2654F}']
63     { Property accessors }
GetSourceName()64     function GetSourceName: String;
65 
66     { Methods }
67     /// <summary>
68     /// Advances the read position of the stream. Updates line and column state
69     /// </summary>
70     procedure Consume;
71 
72     /// <summary>
73     /// Get int at current input pointer + I ahead (where I=1 is next int)
74     /// Negative indexes are allowed.  LA(-1) is previous token (token just matched).
75     /// LA(-i) where i is before first token should yield -1, invalid char or EOF.
76     /// </summary>
LA(I: Integer)77     function LA(I: Integer): Integer;
LAChar(I: Integer)78     function LAChar(I: Integer): Char;
79 
80     /// <summary>Tell the stream to start buffering if it hasn't already.</summary>
81     /// <remarks>
82     /// Executing Rewind(Mark()) on a stream should not affect the input position.
83     /// The Lexer tracks line/col info as well as input index so its markers are
84     /// not pure input indexes.  Same for tree node streams.                          */
85     /// </remarks>
86     /// <returns>Return a marker that can be passed to
87     /// <see cref="IIntStream.Rewind(Integer)"/> to return to the current position.
88     /// This could be the current input position, a value return from
89     /// <see cref="IIntStream.Index"/>, or some other marker.</returns>
Mark()90     function Mark: Integer;
91 
92     /// <summary>
93     /// Return the current input symbol index 0..N where N indicates the
94     /// last symbol has been read. The index is the symbol about to be
95     /// read not the most recently read symbol.
96     /// </summary>
Index()97     function Index: Integer;
98 
99     /// <summary>
100     /// Resets the stream so that the next call to
101     /// <see cref="IIntStream.Index"/> would  return marker.
102     /// </summary>
103     /// <remarks>
104     /// The marker will usually be <see cref="IIntStream.Index"/> but
105     /// it doesn't have to be.  It's just a marker to indicate what
106     /// state the stream was in.  This is essentially calling
107     /// <see cref="IIntStream.Release"/> and <see cref="IIntStream.Seek"/>.
108     /// If there are other markers created after the specified marker,
109     /// this routine must unroll them like a stack.  Assumes the state the
110     /// stream was in when this marker was created.
111     /// </remarks>
112     procedure Rewind(const Marker: Integer); overload;
113 
114     /// <summary>
115     /// Rewind to the input position of the last marker.
116     /// </summary>
117     /// <remarks>
118     /// Used currently only after a cyclic DFA and just before starting
119     /// a sem/syn predicate to get the input position back to the start
120     /// of the decision. Do not "pop" the marker off the state.  Mark(I)
121     /// and Rewind(I) should balance still. It is like invoking
122     /// Rewind(last marker) but it should not "pop" the marker off.
123     /// It's like Seek(last marker's input position).
124     /// </remarks>
125     procedure Rewind; overload;
126 
127     /// <summary>
128     /// You may want to commit to a backtrack but don't want to force the
129     /// stream to keep bookkeeping objects around for a marker that is
130     /// no longer necessary.  This will have the same behavior as
131     /// <see cref="IIntStream.Rewind(Integer)"/> except it releases resources without
132     /// the backward seek.
133     /// </summary>
134     /// <remarks>
135     /// This must throw away resources for all markers back to the marker
136     /// argument. So if you're nested 5 levels of Mark(), and then Release(2)
137     /// you have to release resources for depths 2..5.
138     /// </remarks>
139     procedure Release(const Marker: Integer);
140 
141     /// <summary>
142     /// Set the input cursor to the position indicated by index.  This is
143     /// normally used to seek ahead in the input stream.
144     /// </summary>
145     /// <remarks>
146     /// No buffering is required to do this unless you know your stream
147     /// will use seek to move backwards such as when backtracking.
148     ///
149     /// This is different from rewind in its multi-directional requirement
150     /// and in that its argument is strictly an input cursor (index).
151     ///
152     /// For char streams, seeking forward must update the stream state such
153     /// as line number.  For seeking backwards, you will be presumably
154     /// backtracking using the
155     /// <see cref="IIntStream.Mark"/>/<see cref="IIntStream.Rewind(Integer)"/>
156     /// mechanism that restores state and so this method does not need to
157     /// update state when seeking backwards.
158     ///
159     /// Currently, this method is only used for efficient backtracking using
160     /// memoization, but in the future it may be used for incremental parsing.
161     ///
162     /// The index is 0..N-1. A seek to position i means that LA(1) will return
163     /// the ith symbol.  So, seeking to 0 means LA(1) will return the first
164     /// element in the stream.
165     /// </remarks>
166     procedure Seek(const Index: Integer);
167 
168     /// <summary>Returns the size of the entire stream.</summary>
169     /// <remarks>
170     /// Only makes sense for streams that buffer everything up probably,
171     /// but might be useful to display the entire stream or for testing.
172     /// This value includes a single EOF.
173     /// </remarks>
Size()174     function Size: Integer;
175 
176     { Properties }
177 
178     /// <summary>
179     /// Where are you getting symbols from?  Normally, implementations will
180     /// pass the buck all the way to the lexer who can ask its input stream
181     /// for the file name or whatever.
182     /// </summary>
183     property SourceName: String read GetSourceName;
184   end;
185 
186   /// <summary>A source of characters for an ANTLR lexer </summary>
187   ICharStream = interface(IIntStream)
188   ['{C30EF0DB-F4BD-4CBC-8C8F-828DABB6FF36}']
189     { Property accessors }
GetLine()190     function GetLine: Integer;
191     procedure SetLine(const Value: Integer);
GetCharPositionInLine()192     function GetCharPositionInLine: Integer;
193     procedure SetCharPositionInLine(const Value: Integer);
194 
195     { Methods }
196 
197     /// <summary>
198     /// Get the ith character of lookahead.  This is usually the same as
199     /// LA(I).  This will be used for labels in the generated lexer code.
200     /// I'd prefer to return a char here type-wise, but it's probably
201     /// better to be 32-bit clean and be consistent with LA.
202     /// </summary>
LT(const I: Integer)203     function LT(const I: Integer): Integer;
204 
205     /// <summary>
206     /// This primarily a useful interface for action code (just make sure
207     /// actions don't use this on streams that don't support it).
208     /// For infinite streams, you don't need this.
209     /// </summary>
Substring(const Start, Stop: Integer)210     function Substring(const Start, Stop: Integer): String;
211 
212     { Properties }
213 
214     /// <summary>
215     /// The current line in the character stream (ANTLR tracks the
216     /// line information automatically. To support rewinding character
217     /// streams, we are able to [re-]set the line.
218     /// </summary>
219     property Line: Integer read GetLine write SetLine;
220 
221     /// <summary>
222     /// The index of the character relative to the beginning of the
223     /// line (0..N-1). To support rewinding character streams, we are
224     /// able to [re-]set the character position.
225     /// </summary>
226     property CharPositionInLine: Integer read GetCharPositionInLine write SetCharPositionInLine;
227   end;
228 
229   IToken = interface(IANTLRInterface)
230   ['{73BF129C-2F45-4C68-838E-BF5D3536AC6D}']
231     { Property accessors }
GetTokenType()232     function GetTokenType: Integer;
233     procedure SetTokenType(const Value: Integer);
GetLine()234     function GetLine: Integer;
235     procedure SetLine(const Value: Integer);
GetCharPositionInLine()236     function GetCharPositionInLine: Integer;
237     procedure SetCharPositionInLine(const Value: Integer);
GetChannel()238     function GetChannel: Integer;
239     procedure SetChannel(const Value: Integer);
GetTokenIndex()240     function GetTokenIndex: Integer;
241     procedure SetTokenIndex(const Value: Integer);
GetText()242     function GetText: String;
243     procedure SetText(const Value: String);
244 
245     { Properties }
246     property TokenType: Integer read GetTokenType write SetTokenType;
247 
248     /// <summary>The line number on which this token was matched; line=1..N</summary>
249     property Line: Integer read GetLine write SetLine;
250 
251     /// <summary>
252     /// The index of the first character relative to the beginning of the line 0..N-1
253     /// </summary>
254     property CharPositionInLine: Integer read GetCharPositionInLine write SetCharPositionInLine;
255 
256     /// <summary>The line number on which this token was matched; line=1..N</summary>
257     property Channel: Integer read GetChannel write SetChannel;
258 
259     /// <summary>
260     /// An index from 0..N-1 of the token object in the input stream
261     /// </summary>
262     /// <remarks>
263     /// This must be valid in order to use the ANTLRWorks debugger.
264     /// </remarks>
265     property TokenIndex: Integer read GetTokenIndex write SetTokenIndex;
266 
267     /// <summary>The text of the token</summary>
268     /// <remarks>
269     /// When setting the text, it might be a NOP such as for the CommonToken,
270     /// which doesn't have string pointers, just indexes into a char buffer.
271     /// </remarks>
272     property Text: String read GetText write SetText;
273   end;
274 
275   /// <summary>
276   /// A source of tokens must provide a sequence of tokens via NextToken()
277   /// and also must reveal it's source of characters; CommonToken's text is
278   /// computed from a CharStream; it only store indices into the char stream.
279   ///
280   /// Errors from the lexer are never passed to the parser.  Either you want
281   /// to keep going or you do not upon token recognition error.  If you do not
282   /// want to continue lexing then you do not want to continue parsing.  Just
283   /// throw an exception not under RecognitionException and Delphi will naturally
284   /// toss you all the way out of the recognizers.  If you want to continue
285   /// lexing then you should not throw an exception to the parser--it has already
286   /// requested a token.  Keep lexing until you get a valid one.  Just report
287   /// errors and keep going, looking for a valid token.
288   /// </summary>
289   ITokenSource = interface(IANTLRInterface)
290   ['{2C71FAD0-AEEE-417D-B576-4059F7C4CEB4}']
291     { Property accessors }
GetSourceName()292     function GetSourceName: String;
293 
294     { Methods }
295 
296     /// <summary>
297     /// Returns a Token object from the input stream (usually a CharStream).
298     /// Does not fail/return upon lexing error; just keeps chewing on the
299     /// characters until it gets a good one; errors are not passed through
300     /// to the parser.
301     /// </summary>
NextToken()302     function NextToken: IToken;
303 
304     { Properties }
305 
306     /// <summary>
307     /// Where are you getting tokens from? normally the implication will simply
308     /// ask lexers input stream.
309     /// </summary>
310     property SourceName: String read GetSourceName;
311   end;
312 
313   /// <summary>A stream of tokens accessing tokens from a TokenSource </summary>
314   ITokenStream = interface(IIntStream)
315   ['{59E5B39D-31A6-496D-9FA9-AC75CC584B68}']
316     { Property accessors }
GetTokenSource()317     function GetTokenSource: ITokenSource;
318     procedure SetTokenSource(const Value: ITokenSource);
319 
320     { Methods }
321 
322     /// <summary>
323     /// Get Token at current input pointer + I ahead (where I=1 is next
324     /// Token).
325     /// I &lt; 0 indicates tokens in the past.  So -1 is previous token and -2 is
326     /// two tokens ago. LT(0) is undefined.  For I>=N, return Token.EOFToken.
327     /// Return null for LT(0) and any index that results in an absolute address
328     /// that is negative.
329     /// </summary>
LT(const K: Integer)330     function LT(const K: Integer): IToken;
331 
332     /// <summary>
333     /// Get a token at an absolute index I; 0..N-1.  This is really only
334     /// needed for profiling and debugging and token stream rewriting.
335     /// If you don't want to buffer up tokens, then this method makes no
336     /// sense for you.  Naturally you can't use the rewrite stream feature.
337     /// I believe DebugTokenStream can easily be altered to not use
338     /// this method, removing the dependency.
339     /// </summary>
Get(const I: Integer)340     function Get(const I: Integer): IToken;
341 
342     /// <summary>Return the text of all tokens from start to stop, inclusive.
343     /// If the stream does not buffer all the tokens then it can just
344     /// return '';  Users should not access $ruleLabel.text in
345     /// an action of course in that case.
346     /// </summary>
ToString(const Start, Stop: Integer)347     function ToString(const Start, Stop: Integer): String; overload;
348 
349     /// <summary>Because the user is not required to use a token with an index stored
350     /// in it, we must provide a means for two token objects themselves to
351     /// indicate the start/end location.  Most often this will just delegate
352     /// to the other ToString(Integer,Integer).  This is also parallel with
353     /// the TreeNodeStream.ToString(Object,Object).
354     /// </summary>
ToString(const Start, Stop: IToken)355     function ToString(const Start, Stop: IToken): String; overload;
356 
357     { Properties }
358     property TokenSource: ITokenSource read GetTokenSource write SetTokenSource;
359   end;
360 
361   /// <summary>
362   /// This is the complete state of a stream.
363   ///
364   /// When walking ahead with cyclic DFA for syntactic predicates, we
365   /// need to record the state of the input stream (char index, line,
366   /// etc...) so that we can rewind the state after scanning ahead.
367   /// </summary>
368   ICharStreamState = interface(IANTLRInterface)
369   ['{62D2A1CD-ED3A-4C95-A366-AB8F2E54060B}']
370     { Property accessors }
GetP()371     function GetP: Integer;
372     procedure SetP(const Value: Integer);
GetLine()373     function GetLine: Integer;
374     procedure SetLine(const Value: Integer);
GetCharPositionInLine()375     function GetCharPositionInLine: Integer;
376     procedure SetCharPositionInLine(const Value: Integer);
377 
378     { Properties }
379     /// <summary>Index into the char stream of next lookahead char </summary>
380     property P: Integer read GetP write SetP;
381 
382     /// <summary>What line number is the scanner at before processing buffer[P]? </summary>
383     property Line: Integer read GetLine write SetLine;
384 
385     /// <summary>What char position 0..N-1 in line is scanner before processing buffer[P]? </summary>
386     property CharPositionInLine: Integer read GetCharPositionInLine write SetCharPositionInLine;
387   end;
388 
389   /// <summary>
390   /// A pretty quick <see cref="ICharStream"/> that uses a character array
391   /// directly as it's underlying source.
392   /// </summary>
393   IANTLRStringStream = interface(ICharStream)
394   ['{2FA24299-FF97-4AB6-8CA6-5D3DA13C4AB2}']
395     { Methods }
396 
397     /// <summary>
398     /// Resets the stream so that it is in the same state it was
399     /// when the object was created *except* the data array is not
400     /// touched.
401     /// </summary>
402     procedure Reset;
403 
404   end;
405 
406   /// <summary>
407   /// A character stream - an <see cref="ICharStream"/> - that loads
408   /// and caches the contents of it's underlying file fully during
409   /// object construction
410   /// </summary>
411   /// <remarks>
412   /// This looks very much like an ANTLReaderStream or an ANTLRInputStream
413   /// but, it is a special case. Since we know the exact size of the file to
414   /// load, we can avoid lots of data copying and buffer resizing.
415   /// </remarks>
416   IANTLRFileStream = interface(IANTLRStringStream)
417   ['{2B0145DB-2DAA-48A0-8316-B47A69EDDD1A}']
418     { Methods }
419 
420     /// <summary>
421     /// Loads and buffers the specified file to be used as this
422     /// ANTLRFileStream's source
423     /// </summary>
424     /// <param name="FileName">File to load</param>
425     /// <param name="Encoding">Encoding to apply to file</param>
426     procedure Load(const FileName: String; const Encoding: TEncoding);
427   end;
428 
429   /// <summary>
430   /// A stripped-down version of org.antlr.misc.BitSet that is just
431   /// good enough to handle runtime requirements such as FOLLOW sets
432   /// for automatic error recovery.
433   /// </summary>
434   IBitSet = interface(IANTLRInterface)
435   ['{F2045045-FC46-4779-A65D-56C65D257A8E}']
436     { Property accessors }
GetIsNil()437     function GetIsNil: Boolean;
438 
439     { Methods }
440 
441     /// <summary>return "this or a" in a new set </summary>
BitSetOr(const A: IBitSet)442     function BitSetOr(const A: IBitSet): IBitSet;
443 
444     /// <summary>Or this element into this set (grow as necessary to accommodate)</summary>
445     procedure Add(const El: Integer);
446 
447     /// <summary> Grows the set to a larger number of bits.</summary>
448     /// <param name="bit">element that must fit in set
449     /// </param>
450     procedure GrowToInclude(const Bit: Integer);
451 
452     procedure OrInPlace(const A: IBitSet);
Size()453     function Size: Integer;
Member(const El: Integer)454     function Member(const El: Integer): Boolean;
455 
456     // remove this element from this set
457     procedure Remove(const El: Integer);
458 
NumBits()459     function NumBits: Integer;
460 
461     /// <summary>return how much space is being used by the bits array not
462     /// how many actually have member bits on.
463     /// </summary>
LengthInLongWords()464     function LengthInLongWords: Integer;
465 
ToArray()466     function ToArray: TIntegerArray;
ToPackedArray()467     function ToPackedArray: TUInt64Array;
468 
ToString()469     function ToString: String; overload;
ToString(const TokenNames: TStringArray)470     function ToString(const TokenNames: TStringArray): String; overload;
Equals(Obj: TObject)471     function Equals(Obj: TObject): Boolean;
472 
473     { Properties }
474     property IsNil: Boolean read GetIsNil;
475   end;
476   TBitSetArray = array of IBitSet;
477 
478   /// <summary>
479   /// The set of fields needed by an abstract recognizer to recognize input
480   /// and recover from errors
481   /// </summary>
482   /// <remarks>
483   /// As a separate state object, it can be shared among multiple grammars;
484   /// e.g., when one grammar imports another.
485   /// These fields are publicly visible but the actual state pointer per
486   /// parser is protected.
487   /// </remarks>
488   IRecognizerSharedState = interface(IANTLRInterface)
489   ['{6CB6E17A-0B01-4AA7-8D49-5742A3CB8901}']
490     { Property accessors }
GetFollowing()491     function GetFollowing: TBitSetArray;
492     procedure SetFollowing(const Value: TBitSetArray);
GetFollowingStackPointer()493     function GetFollowingStackPointer: Integer;
494     procedure SetFollowingStackPointer(const Value: Integer);
GetErrorRecovery()495     function GetErrorRecovery: Boolean;
496     procedure SetErrorRecovery(const Value: Boolean);
GetLastErrorIndex()497     function GetLastErrorIndex: Integer;
498     procedure SetLastErrorIndex(const Value: Integer);
GetFailed()499     function GetFailed: Boolean;
500     procedure SetFailed(const Value: Boolean);
GetSyntaxErrors()501     function GetSyntaxErrors: Integer;
502     procedure SetSyntaxErrors(const Value: Integer);
GetBacktracking()503     function GetBacktracking: Integer;
504     procedure SetBacktracking(const Value: Integer);
GetRuleMemo()505     function GetRuleMemo: TDictionaryArray<Integer, Integer>;
GetRuleMemoCount()506     function GetRuleMemoCount: Integer;
507     procedure SetRuleMemoCount(const Value: Integer);
GetToken()508     function GetToken: IToken;
509     procedure SetToken(const Value: IToken);
GetTokenStartCharIndex()510     function GetTokenStartCharIndex: Integer;
511     procedure SetTokenStartCharIndex(const Value: Integer);
GetTokenStartLine()512     function GetTokenStartLine: Integer;
513     procedure SetTokenStartLine(const Value: Integer);
GetTokenStartCharPositionInLine()514     function GetTokenStartCharPositionInLine: Integer;
515     procedure SetTokenStartCharPositionInLine(const Value: Integer);
GetChannel()516     function GetChannel: Integer;
517     procedure SetChannel(const Value: Integer);
GetTokenType()518     function GetTokenType: Integer;
519     procedure SetTokenType(const Value: Integer);
GetText()520     function GetText: String;
521     procedure SetText(const Value: String);
522 
523     { Properties }
524 
525     /// <summary>
526     /// Tracks the set of token types that can follow any rule invocation.
527     /// Stack grows upwards.  When it hits the max, it grows 2x in size
528     /// and keeps going.
529     /// </summary>
530     property Following: TBitSetArray read GetFollowing write SetFollowing;
531     property FollowingStackPointer: Integer read GetFollowingStackPointer write SetFollowingStackPointer;
532 
533     /// <summary>
534     /// This is true when we see an error and before having successfully
535     /// matched a token.  Prevents generation of more than one error message
536     /// per error.
537     /// </summary>
538     property ErrorRecovery: Boolean read GetErrorRecovery write SetErrorRecovery;
539 
540     /// <summary>
541     /// The index into the input stream where the last error occurred.
542     /// </summary>
543     /// <remarks>
544     /// This is used to prevent infinite loops where an error is found
545     /// but no token is consumed during recovery...another error is found,
546     /// ad naseum.  This is a failsafe mechanism to guarantee that at least
547     /// one token/tree node is consumed for two errors.
548     /// </remarks>
549     property LastErrorIndex: Integer read GetLastErrorIndex write SetLastErrorIndex;
550 
551     /// <summary>
552     /// In lieu of a return value, this indicates that a rule or token
553     /// has failed to match.  Reset to false upon valid token match.
554     /// </summary>
555     property Failed: Boolean read GetFailed write SetFailed;
556 
557     /// <summary>
558     /// Did the recognizer encounter a syntax error?  Track how many.
559     /// </summary>
560     property SyntaxErrors: Integer read GetSyntaxErrors write SetSyntaxErrors;
561 
562     /// <summary>
563     /// If 0, no backtracking is going on.  Safe to exec actions etc...
564     /// If >0 then it's the level of backtracking.
565     /// </summary>
566     property Backtracking: Integer read GetBacktracking write SetBacktracking;
567 
568     /// <summary>
569     /// An array[size num rules] of Map&lt;Integer,Integer&gt; that tracks
570     /// the stop token index for each rule.
571     /// </summary>
572     /// <remarks>
573     ///  RuleMemo[RuleIndex] is the memoization table for RuleIndex.
574     ///  For key RuleStartIndex, you get back the stop token for
575     ///  associated rule or MEMO_RULE_FAILED.
576     ///
577     ///  This is only used if rule memoization is on (which it is by default).
578     ///  </remarks>
579     property RuleMemo: TDictionaryArray<Integer, Integer> read GetRuleMemo;
580     property RuleMemoCount: Integer read GetRuleMemoCount write SetRuleMemoCount;
581 
582     // Lexer Specific Members
583     // LEXER FIELDS (must be in same state object to avoid casting
584     //               constantly in generated code and Lexer object) :(
585 
586     /// <summary>
587     /// Token object normally returned by NextToken() after matching lexer rules.
588     /// </summary>
589     /// <remarks>
590     /// The goal of all lexer rules/methods is to create a token object.
591     /// This is an instance variable as multiple rules may collaborate to
592     /// create a single token.  NextToken will return this object after
593     /// matching lexer rule(s).  If you subclass to allow multiple token
594     /// emissions, then set this to the last token to be matched or
595     /// something nonnull so that the auto token emit mechanism will not
596     /// emit another token.
597     /// </remarks>
598     property Token: IToken read GetToken write SetToken;
599 
600     /// <summary>
601     /// What character index in the stream did the current token start at?
602     /// </summary>
603     /// <remarks>
604     /// Needed, for example, to get the text for current token.  Set at
605     /// the start of nextToken.
606     /// </remarks>
607     property TokenStartCharIndex: Integer read GetTokenStartCharIndex write SetTokenStartCharIndex;
608 
609     /// <summary>
610     /// The line on which the first character of the token resides
611     /// </summary>
612     property TokenStartLine: Integer read GetTokenStartLine write SetTokenStartLine;
613 
614     /// <summary>The character position of first character within the line</summary>
615     property TokenStartCharPositionInLine: Integer read GetTokenStartCharPositionInLine write SetTokenStartCharPositionInLine;
616 
617     /// <summary>The channel number for the current token</summary>
618     property Channel: Integer read GetChannel write SetChannel;
619 
620     /// <summary>The token type for the current token</summary>
621     property TokenType: Integer read GetTokenType write SetTokenType;
622 
623     /// <summary>
624     /// You can set the text for the current token to override what is in
625     /// the input char buffer.  Use setText() or can set this instance var.
626     /// </summary>
627     property Text: String read GetText write SetText;
628   end;
629 
630   ICommonToken = interface(IToken)
631   ['{06B1B0C3-2A0D-477A-AE30-414F51ACE8A0}']
632     { Property accessors }
GetStartIndex()633     function GetStartIndex: Integer;
634     procedure SetStartIndex(const Value: Integer);
GetStopIndex()635     function GetStopIndex: Integer;
636     procedure SetStopIndex(const Value: Integer);
GetInputStream()637     function GetInputStream: ICharStream;
638     procedure SetInputStream(const Value: ICharStream);
639 
640     { Methods }
ToString()641     function ToString: String;
642 
643     { Properties }
644     property StartIndex: Integer read GetStartIndex write SetStartIndex;
645     property StopIndex: Integer read GetStopIndex write SetStopIndex;
646     property InputStream: ICharStream read GetInputStream write SetInputStream;
647   end;
648 
649   /// <summary>
650   /// A Token object like we'd use in ANTLR 2.x; has an actual string created
651   /// and associated with this object.  These objects are needed for imaginary
652   /// tree nodes that have payload objects.  We need to create a Token object
653   /// that has a string; the tree node will point at this token.  CommonToken
654   /// has indexes into a char stream and hence cannot be used to introduce
655   /// new strings.
656   /// </summary>
657   IClassicToken = interface(IToken)
658     { Property accessors }
GetTokenType()659     function GetTokenType: Integer;
660     procedure SetTokenType(const Value: Integer);
GetLine()661     function GetLine: Integer;
662     procedure SetLine(const Value: Integer);
GetCharPositionInLine()663     function GetCharPositionInLine: Integer;
664     procedure SetCharPositionInLine(const Value: Integer);
GetChannel()665     function GetChannel: Integer;
666     procedure SetChannel(const Value: Integer);
GetTokenIndex()667     function GetTokenIndex: Integer;
668     procedure SetTokenIndex(const Value: Integer);
GetText()669     function GetText: String;
670     procedure SetText(const Value: String);
GetInputStream()671     function GetInputStream: ICharStream;
672     procedure SetInputStream(const Value: ICharStream);
673 
674     { Properties }
675     property TokenType: Integer read GetTokenType write SetTokenType;
676     property Line: Integer read GetLine write SetLine;
677     property CharPositionInLine: Integer read GetCharPositionInLine write SetCharPositionInLine;
678     property Channel: Integer read GetChannel write SetChannel;
679     property TokenIndex: Integer read GetTokenIndex write SetTokenIndex;
680     property Text: String read GetText write SetText;
681     property InputStream: ICharStream read GetInputStream write SetInputStream;
682   end;
683 
684   /// <summary>
685   /// A generic recognizer that can handle recognizers generated from
686   /// lexer, parser, and tree grammars.  This is all the parsing
687   /// support code essentially; most of it is error recovery stuff and
688   /// backtracking.
689   /// </summary>
690   IBaseRecognizer = interface(IANTLRObject)
691   ['{90813CE2-614B-4773-A26E-936E7DE7E9E9}']
692     { Property accessors }
GetInput()693     function GetInput: IIntStream;
GetBacktrackingLevel()694     function GetBacktrackingLevel: Integer;
GetState()695     function GetState: IRecognizerSharedState;
GetNumberOfSyntaxErrors()696     function GetNumberOfSyntaxErrors: Integer;
GetGrammarFileName()697     function GetGrammarFileName: String;
GetSourceName()698     function GetSourceName: String;
GetTokenNames()699     function GetTokenNames: TStringArray;
700 
701     { Methods }
702     procedure BeginBacktrack(const Level: Integer);
703     procedure EndBacktrack(const Level: Integer; const Successful: Boolean);
704 
705     /// <summary>Reset the parser's state. Subclasses must rewind the input stream.</summary>
706     procedure Reset;
707 
708     /// <summary>
709     /// Match current input symbol against ttype.  Attempt
710     /// single token insertion or deletion error recovery.  If
711     /// that fails, throw EMismatchedTokenException.
712     /// </summary>
713     /// <remarks>
714     /// To turn off single token insertion or deletion error
715     /// recovery, override MismatchRecover() and have it call
716     /// plain Mismatch(), which does not recover. Then any error
717     /// in a rule will cause an exception and immediate exit from
718     /// rule. Rule would recover by resynchronizing to the set of
719     /// symbols that can follow rule ref.
720     /// </remarks>
Match(const Input: IIntStream; const TokenType: Integer;721     function Match(const Input: IIntStream; const TokenType: Integer;
722       const Follow: IBitSet): IANTLRInterface;
723 
MismatchIsUnwantedToken(const Input: IIntStream;724     function MismatchIsUnwantedToken(const Input: IIntStream;
725       const TokenType: Integer): Boolean;
726 
MismatchIsMissingToken(const Input: IIntStream;727     function MismatchIsMissingToken(const Input: IIntStream;
728       const Follow: IBitSet): Boolean;
729 
730     /// <summary>A hook to listen in on the token consumption during error recovery.
731     /// The DebugParser subclasses this to fire events to the listenter.
732     /// </summary>
733     procedure BeginResync;
734     procedure EndResync;
735 
736     /// <summary>
737     /// Report a recognition problem.
738     /// </summary>
739     /// <remarks>
740     /// This method sets errorRecovery to indicate the parser is recovering
741     /// not parsing.  Once in recovery mode, no errors are generated.
742     /// To get out of recovery mode, the parser must successfully Match
743     /// a token (after a resync).  So it will go:
744     ///
745     /// 1. error occurs
746     /// 2. enter recovery mode, report error
747     /// 3. consume until token found in resynch set
748     /// 4. try to resume parsing
749     /// 5. next Match() will reset errorRecovery mode
750     ///
751     /// If you override, make sure to update syntaxErrors if you care about that.
752     /// </remarks>
753     procedure ReportError(const E: ERecognitionException);
754 
755     /// <summary> Match the wildcard: in a symbol</summary>
756     procedure MatchAny(const Input: IIntStream);
757 
758     procedure DisplayRecognitionError(const TokenNames: TStringArray;
759       const E: ERecognitionException);
760 
761     /// <summary>
762     /// What error message should be generated for the various exception types?
763     ///
764     /// Not very object-oriented code, but I like having all error message generation
765     /// within one method rather than spread among all of the exception classes. This
766     /// also makes it much easier for the exception handling because the exception
767     /// classes do not have to have pointers back to this object to access utility
768     /// routines and so on. Also, changing the message for an exception type would be
769     /// difficult because you would have to subclassing exception, but then somehow get
770     /// ANTLR to make those kinds of exception objects instead of the default.
771     ///
772     /// This looks weird, but trust me--it makes the most sense in terms of flexibility.
773     ///
774     /// For grammar debugging, you will want to override this to add more information
775     /// such as the stack frame with GetRuleInvocationStack(e, this.GetType().Fullname)
776     /// and, for no viable alts, the decision description and state etc...
777     ///
778     /// Override this to change the message generated for one or more exception types.
779     /// </summary>
GetErrorMessage(const E: ERecognitionException;780     function GetErrorMessage(const E: ERecognitionException;
781       const TokenNames: TStringArray): String;
782 
783     /// <summary>
784     /// What is the error header, normally line/character position information?
785     /// </summary>
GetErrorHeader(const E: ERecognitionException)786     function GetErrorHeader(const E: ERecognitionException): String;
787 
788     /// <summary>
789     /// How should a token be displayed in an error message? The default
790     /// is to display just the text, but during development you might
791     /// want to have a lot of information spit out.  Override in that case
792     /// to use t.ToString() (which, for CommonToken, dumps everything about
793     /// the token). This is better than forcing you to override a method in
794     /// your token objects because you don't have to go modify your lexer
795     /// so that it creates a new type.
796     /// </summary>
GetTokenErrorDisplay(const T: IToken)797     function GetTokenErrorDisplay(const T: IToken): String;
798 
799     /// <summary>
800     /// Override this method to change where error messages go
801     /// </summary>
802     procedure EmitErrorMessage(const Msg: String);
803 
804     /// <summary>
805     /// Recover from an error found on the input stream.  This is
806     /// for NoViableAlt and mismatched symbol exceptions.  If you enable
807     /// single token insertion and deletion, this will usually not
808     /// handle mismatched symbol exceptions but there could be a mismatched
809     /// token that the Match() routine could not recover from.
810     /// </summary>
811     procedure Recover(const Input: IIntStream; const RE: ERecognitionException);
812 
813     // Not currently used
RecoverFromMismatchedSet(const Input: IIntStream;814     function RecoverFromMismatchedSet(const Input: IIntStream;
815       const E: ERecognitionException; const Follow: IBitSet): IANTLRInterface;
816 
817     procedure ConsumeUntil(const Input: IIntStream; const TokenType: Integer); overload;
818 
819     /// <summary>Consume tokens until one matches the given token set </summary>
820     procedure ConsumeUntil(const Input: IIntStream; const BitSet: IBitSet); overload;
821 
822     /// <summary>
823     /// Returns List &lt;String&gt; of the rules in your parser instance
824     /// leading up to a call to this method.  You could override if
825     /// you want more details such as the file/line info of where
826     /// in the parser source code a rule is invoked.
827     /// </summary>
828     /// <remarks>
829     /// NOT IMPLEMENTED IN THE DELPHI VERSION YET
830     /// This is very useful for error messages and for context-sensitive
831     /// error recovery.
832     /// </remarks>
833     //function GetRuleInvocationStack: IList<IANTLRInterface>; overload;
834 
835     /// <summary>
836     /// A more general version of GetRuleInvocationStack where you can
837     /// pass in, for example, a RecognitionException to get it's rule
838     /// stack trace.  This routine is shared with all recognizers, hence,
839     /// static.
840     ///
841     /// TODO: move to a utility class or something; weird having lexer call this
842     /// </summary>
843     /// <remarks>
844     /// NOT IMPLEMENTED IN THE DELPHI VERSION YET
845     /// </remarks>
846     //function GetRuleInvocationStack(const E: Exception;
847     //  const RecognizerClassName: String): IList<IANTLRInterface>; overload;
848 
849     /// <summary>A convenience method for use most often with template rewrites.
850     /// Convert a List&lt;Token&gt; to List&lt;String&gt;
851     /// </summary>
ToStrings(const Tokens: IList<IToken>)852     function ToStrings(const Tokens: IList<IToken>): IList<String>;
853 
854     /// <summary>
855     /// Given a rule number and a start token index number, return
856     /// MEMO_RULE_UNKNOWN if the rule has not parsed input starting from
857     /// start index.  If this rule has parsed input starting from the
858     /// start index before, then return where the rule stopped parsing.
859     /// It returns the index of the last token matched by the rule.
860     /// </summary>
861     /// <remarks>
862     /// For now we use a hashtable and just the slow Object-based one.
863     /// Later, we can make a special one for ints and also one that
864     /// tosses out data after we commit past input position i.
865     /// </remarks>
GetRuleMemoization(const RuleIndex, RuleStartIndex: Integer)866     function GetRuleMemoization(const RuleIndex, RuleStartIndex: Integer): Integer;
867 
868     /// <summary>
869     /// Has this rule already parsed input at the current index in the
870     /// input stream?  Return the stop token index or MEMO_RULE_UNKNOWN.
871     /// If we attempted but failed to parse properly before, return
872     /// MEMO_RULE_FAILED.
873     ///
874     /// This method has a side-effect: if we have seen this input for
875     /// this rule and successfully parsed before, then seek ahead to
876     /// 1 past the stop token matched for this rule last time.
877     /// </summary>
AlreadyParsedRule(const Input: IIntStream;878     function AlreadyParsedRule(const Input: IIntStream;
879       const RuleIndex: Integer): Boolean;
880 
881     /// <summary>
882     /// Record whether or not this rule parsed the input at this position
883     /// successfully.  Use a standard hashtable for now.
884     /// </summary>
885     procedure Memoize(const Input: IIntStream; const RuleIndex,
886       RuleStartIndex: Integer);
887 
888     /// <summary>
889     /// Return how many rule/input-index pairs there are in total.
890     ///  TODO: this includes synpreds. :(
891     /// </summary>
892     /// <returns></returns>
GetRuleMemoizationChaceSize()893     function GetRuleMemoizationChaceSize: Integer;
894 
895     procedure TraceIn(const RuleName: String; const RuleIndex: Integer;
896       const InputSymbol: String);
897     procedure TraceOut(const RuleName: String; const RuleIndex: Integer;
898       const InputSymbol: String);
899 
900     { Properties }
901     property Input: IIntStream read GetInput;
902     property BacktrackingLevel: Integer read GetBacktrackingLevel;
903     property State: IRecognizerSharedState read GetState;
904 
905     /// <summary>
906     /// Get number of recognition errors (lexer, parser, tree parser).  Each
907     /// recognizer tracks its own number.  So parser and lexer each have
908     /// separate count.  Does not count the spurious errors found between
909     /// an error and next valid token match
910     ///
911     /// See also ReportError()
912     /// </summary>
913     property NumberOfSyntaxErrors: Integer read GetNumberOfSyntaxErrors;
914 
915     /// <summary>
916     /// For debugging and other purposes, might want the grammar name.
917     /// Have ANTLR generate an implementation for this property.
918     /// </summary>
919     /// <returns></returns>
920     property GrammarFileName: String read GetGrammarFileName;
921 
922     /// <summary>
923     /// For debugging and other purposes, might want the source name.
924     /// Have ANTLR provide a hook for this property.
925     /// </summary>
926     /// <returns>The source name</returns>
927     property SourceName: String read GetSourceName;
928 
929     /// <summary>
930     /// Used to print out token names like ID during debugging and
931     /// error reporting.  The generated parsers implement a method
932     /// that overrides this to point to their string[] tokenNames.
933     /// </summary>
934     property TokenNames: TStringArray read GetTokenNames;
935   end;
936 
937   /// <summary>
938   /// The most common stream of tokens is one where every token is buffered up
939   /// and tokens are prefiltered for a certain channel (the parser will only
940   /// see these tokens and cannot change the filter channel number during the
941   /// parse).
942   ///
943   /// TODO: how to access the full token stream?  How to track all tokens matched per rule?
944   /// </summary>
945   ICommonTokenStream = interface(ITokenStream)
946     { Methods }
947 
948     /// <summary>
949     /// A simple filter mechanism whereby you can tell this token stream
950     /// to force all tokens of type TType to be on Channel.
951     /// </summary>
952     ///
953     /// <remarks>
954     /// For example,
955     /// when interpreting, we cannot exec actions so we need to tell
956     /// the stream to force all WS and NEWLINE to be a different, ignored
957     /// channel.
958     /// </remarks>
959     procedure SetTokenTypeChannel(const TType, Channel: Integer);
960 
961     procedure DiscardTokenType(const TType: Integer);
962 
963     procedure DiscardOffChannelTokens(const Discard: Boolean);
964 
GetTokens()965     function GetTokens: IList<IToken>; overload;
GetTokens(const Start, Stop: Integer)966     function GetTokens(const Start, Stop: Integer): IList<IToken>; overload;
967 
968     /// <summary>Given a start and stop index, return a List of all tokens in
969     /// the token type BitSet.  Return null if no tokens were found.  This
970     /// method looks at both on and off channel tokens.
971     /// </summary>
GetTokens(const Start, Stop: Integer;972     function GetTokens(const Start, Stop: Integer;
973       const Types: IBitSet): IList<IToken>; overload;
974 
GetTokens(const Start, Stop: Integer;975     function GetTokens(const Start, Stop: Integer;
976       const Types: IList<Integer>): IList<IToken>; overload;
977 
GetTokens(const Start, Stop,978     function GetTokens(const Start, Stop,
979       TokenType: Integer): IList<IToken>; overload;
980 
981     procedure Reset;
982   end;
983 
984   IDFA = interface;
985 
onst()986   TSpecialStateTransitionHandler = function(const DFA: IDFA; S: Integer;
987     const Input: IIntStream): Integer of Object;
988 
989   /// <summary>
990   ///  A DFA implemented as a set of transition tables.
991   /// </summary>
992   /// <remarks>
993   /// <para>
994   /// Any state that has a semantic predicate edge is special; those states are
995   /// generated with if-then-else structures in a SpecialStateTransition()
996   /// which is generated by cyclicDFA template.
997   /// </para>
998   /// <para>
999   /// There are at most 32767 states (16-bit signed short). Could get away with byte
1000   /// sometimes but would have to generate different types and the simulation code too.
1001   /// </para>
1002   /// <para>
1003   /// As a point of reference, the Tokens rule DFA for the lexer in the Java grammar
1004   /// sample has approximately 326 states.
1005   /// </para>
1006   /// </remarks>
1007   IDFA = interface(IANTLRInterface)
1008   ['{36312B59-B718-48EF-A0EC-4529DE70F4C2}']
1009     { Property accessors }
GetSpecialStateTransitionHandler()1010     function GetSpecialStateTransitionHandler: TSpecialStateTransitionHandler;
1011     procedure SetSpecialStateTransitionHandler(const Value: TSpecialStateTransitionHandler);
1012 
1013     { Methods }
1014 
1015     /// <summary>
1016     /// From the input stream, predict what alternative will succeed using this
1017     /// DFA (representing the covering regular approximation to the underlying CFL).
1018     /// </summary>
1019     /// <param name="Input">Input stream</param>
1020     /// <returns>Return an alternative number 1..N.  Throw an exception upon error.</returns>
Predict(const Input: IIntStream)1021     function Predict(const Input: IIntStream): Integer;
1022 
1023     /// <summary>
1024     /// A hook for debugging interface
1025     /// </summary>
1026     /// <param name="NVAE"></param>
1027     procedure Error(const NVAE: ENoViableAltException);
1028 
SpecialStateTransition(const S: Integer; const Input: IIntStream)1029     function SpecialStateTransition(const S: Integer; const Input: IIntStream): Integer;
1030 
Description()1031     function Description: String;
1032 
SpecialTransition(const State, Symbol: Integer)1033     function SpecialTransition(const State, Symbol: Integer): Integer;
1034 
1035     { Properties }
1036     property SpecialStateTransitionHandler: TSpecialStateTransitionHandler read GetSpecialStateTransitionHandler write SetSpecialStateTransitionHandler;
1037   end;
1038 
1039   /// <summary>
1040   /// A lexer is recognizer that draws input symbols from a character stream.
1041   /// lexer grammars result in a subclass of this object. A Lexer object
1042   /// uses simplified Match() and error recovery mechanisms in the interest
1043   /// of speed.
1044   /// </summary>
1045   ILexer = interface(IBaseRecognizer)
1046   ['{331AAB49-E7CD-40E7-AEF5-427F7D6577AD}']
1047     { Property accessors }
GetCharStream()1048     function GetCharStream: ICharStream;
1049     procedure SetCharStream(const Value: ICharStream);
GetLine()1050     function GetLine: Integer;
GetCharPositionInLine()1051     function GetCharPositionInLine: Integer;
GetCharIndex()1052     function GetCharIndex: Integer;
GetText()1053     function GetText: String;
1054     procedure SetText(const Value: String);
1055 
1056     { Methods }
1057 
1058     /// <summary>
1059     /// Return a token from this source; i.e., Match a token on the char stream.
1060     /// </summary>
NextToken()1061     function NextToken: IToken;
1062 
1063     /// <summary>
1064     /// Instruct the lexer to skip creating a token for current lexer rule and
1065     /// look for another token.  NextToken() knows to keep looking when a lexer
1066     /// rule finishes with token set to SKIP_TOKEN.  Recall that if token==null
1067     /// at end of any token rule, it creates one for you and emits it.
1068     /// </summary>
1069     procedure Skip;
1070 
1071     /// <summary>This is the lexer entry point that sets instance var 'token' </summary>
1072     procedure DoTokens;
1073 
1074     /// <summary>
1075     /// Currently does not support multiple emits per nextToken invocation
1076     /// for efficiency reasons.  Subclass and override this method and
1077     /// NextToken (to push tokens into a list and pull from that list rather
1078     /// than a single variable as this implementation does).
1079     /// </summary>
1080     procedure Emit(const Token: IToken); overload;
1081 
1082     /// <summary>
1083     /// The standard method called to automatically emit a token at the
1084     /// outermost lexical rule.  The token object should point into the
1085     /// char buffer start..stop.  If there is a text override in 'text',
1086     /// use that to set the token's text.
1087     /// </summary>
1088     /// <remarks><para>Override this method to emit custom Token objects.</para>
1089     /// <para>If you are building trees, then you should also override
1090     /// Parser or TreeParser.GetMissingSymbol().</para>
1091     ///</remarks>
Emit()1092     function Emit: IToken; overload;
1093 
1094     procedure Match(const S: String); overload;
1095     procedure Match(const C: Integer); overload;
1096     procedure MatchAny;
1097     procedure MatchRange(const A, B: Integer);
1098 
1099     /// <summary>
1100     /// Lexers can normally Match any char in it's vocabulary after matching
1101     /// a token, so do the easy thing and just kill a character and hope
1102     /// it all works out.  You can instead use the rule invocation stack
1103     /// to do sophisticated error recovery if you are in a Fragment rule.
1104     /// </summary>
1105     procedure Recover(const RE: ERecognitionException);
1106 
GetCharErrorDisplay(const C: Integer)1107     function GetCharErrorDisplay(const C: Integer): String;
1108 
1109     procedure TraceIn(const RuleName: String; const RuleIndex: Integer);
1110     procedure TraceOut(const RuleName: String; const RuleIndex: Integer);
1111 
1112     { Properties }
1113 
1114     /// <summary>Set the char stream and reset the lexer </summary>
1115     property CharStream: ICharStream read GetCharStream write SetCharStream;
1116     property Line: Integer read GetLine;
1117     property CharPositionInLine: Integer read GetCharPositionInLine;
1118 
1119     /// <summary>What is the index of the current character of lookahead? </summary>
1120     property CharIndex: Integer read GetCharIndex;
1121 
1122     /// <summary>
1123     /// Gets or sets the 'lexeme' for the current token.
1124     /// </summary>
1125     /// <remarks>
1126     /// <para>
1127     /// The getter returns the text matched so far for the current token or any
1128     /// text override.
1129     /// </para>
1130     /// <para>
1131     /// The setter sets the complete text of this token. It overrides/wipes any
1132     /// previous changes to the text.
1133     /// </para>
1134     /// </remarks>
1135     property Text: String read GetText write SetText;
1136   end;
1137 
1138   /// <summary>A parser for TokenStreams.  Parser grammars result in a subclass
1139   /// of this.
1140   /// </summary>
1141   IParser = interface(IBaseRecognizer)
1142   ['{7420879A-5D1F-43CA-BD49-2264D7514501}']
1143     { Property accessors }
GetTokenStream()1144     function GetTokenStream: ITokenStream;
1145     procedure SetTokenStream(const Value: ITokenStream);
1146 
1147     { Methods }
1148     procedure TraceIn(const RuleName: String; const RuleIndex: Integer);
1149     procedure TraceOut(const RuleName: String; const RuleIndex: Integer);
1150 
1151     { Properties }
1152 
1153     /// <summary>Set the token stream and reset the parser </summary>
1154     property TokenStream: ITokenStream read GetTokenStream write SetTokenStream;
1155   end;
1156 
1157   /// <summary>
1158   /// Rules can return start/stop info as well as possible trees and templates
1159   /// </summary>
1160   IRuleReturnScope = interface(IANTLRInterface)
1161   ['{E9870056-BF6D-4CB2-B71C-10B80797C0B4}']
1162     { Property accessors }
GetStart()1163     function GetStart: IANTLRInterface;
1164     procedure SetStart(const Value: IANTLRInterface);
GetStop()1165     function GetStop: IANTLRInterface;
1166     procedure SetStop(const Value: IANTLRInterface);
GetTree()1167     function GetTree: IANTLRInterface;
1168     procedure SetTree(const Value: IANTLRInterface);
GetTemplate()1169     function GetTemplate: IANTLRInterface;
1170 
1171     { Properties }
1172 
1173     /// <summary>Return the start token or tree </summary>
1174     property Start: IANTLRInterface read GetStart write SetStart;
1175 
1176     /// <summary>Return the stop token or tree </summary>
1177     property Stop: IANTLRInterface read GetStop write SetStop;
1178 
1179     /// <summary>Has a value potentially if output=AST; </summary>
1180     property Tree: IANTLRInterface read GetTree write SetTree;
1181 
1182     /// <summary>
1183     /// Has a value potentially if output=template;
1184     /// Don't use StringTemplate type to avoid dependency on ST assembly
1185     /// </summary>
1186     property Template: IANTLRInterface read GetTemplate;
1187   end;
1188 
1189   /// <summary>
1190   /// Rules that return more than a single value must return an object
1191   /// containing all the values.  Besides the properties defined in
1192   /// RuleLabelScope.PredefinedRulePropertiesScope there may be user-defined
1193   /// return values.  This class simply defines the minimum properties that
1194   /// are always defined and methods to access the others that might be
1195   /// available depending on output option such as template and tree.
1196   ///
1197   /// Note text is not an actual property of the return value, it is computed
1198   /// from start and stop using the input stream's ToString() method.  I
1199   /// could add a ctor to this so that we can pass in and store the input
1200   /// stream, but I'm not sure we want to do that.  It would seem to be undefined
1201   /// to get the .text property anyway if the rule matches tokens from multiple
1202   /// input streams.
1203   ///
1204   /// I do not use getters for fields of objects that are used simply to
1205   /// group values such as this aggregate.
1206   /// </summary>
1207   IParserRuleReturnScope = interface(IRuleReturnScope)
1208   ['{9FB62050-E23B-4FE4-87D5-2C1EE67AEC3E}']
1209   end;
1210 
1211   /// <summary>Useful for dumping out the input stream after doing some
1212   /// augmentation or other manipulations.
1213   /// </summary>
1214   ///
1215   /// <remarks>
1216   /// You can insert stuff, Replace, and delete chunks.  Note that the
1217   /// operations are done lazily--only if you convert the buffer to a
1218   /// String.  This is very efficient because you are not moving data around
1219   /// all the time.  As the buffer of tokens is converted to strings, the
1220   /// ToString() method(s) check to see if there is an operation at the
1221   /// current index.  If so, the operation is done and then normal String
1222   /// rendering continues on the buffer.  This is like having multiple Turing
1223   /// machine instruction streams (programs) operating on a single input tape. :)
1224   ///
1225   /// Since the operations are done lazily at ToString-time, operations do not
1226   /// screw up the token index values.  That is, an insert operation at token
1227   /// index I does not change the index values for tokens I+1..N-1.
1228   ///
1229   /// Because operations never actually alter the buffer, you may always get
1230   /// the original token stream back without undoing anything.  Since
1231   /// the instructions are queued up, you can easily simulate transactions and
1232   /// roll back any changes if there is an error just by removing instructions.
1233   /// For example,
1234   ///
1235   /// var
1236   ///   Input: ICharStream;
1237   ///   Lex: ILexer;
1238   ///   Tokens: ITokenRewriteStream;
1239   ///   Parser: IParser;
1240   /// Input := TANTLRFileStream.Create('input');
1241   /// Lex := TLexer.Create(Input);
1242   /// Tokens := TTokenRewriteStream.Create(Lex);
1243   /// Parser := TParser.Create(tokens);
1244   /// Parser.startRule();
1245   ///
1246   /// Then in the rules, you can execute
1247   /// var
1248   ///   t,u: IToken;
1249   /// ...
1250   /// Input.InsertAfter(t, 'text to put after t');
1251   /// Input.InsertAfter(u, 'text after u');
1252   /// WriteLn(Tokens.ToString());
1253   ///
1254   /// Actually, you have to cast the 'input' to a TokenRewriteStream. :(
1255   ///
1256   /// You can also have multiple "instruction streams" and get multiple
1257   /// rewrites from a single pass over the input.  Just name the instruction
1258   /// streams and use that name again when printing the buffer.  This could be
1259   /// useful for generating a C file and also its header file--all from the
1260   /// same buffer:
1261   ///
1262   /// Tokens.InsertAfter('pass1', t, 'text to put after t');
1263   /// Tokens.InsertAfter('pass2', u, 'text after u');
1264   /// WriteLn(Tokens.ToString('pass1'));
1265   /// WriteLn(Tokens.ToString('pass2'));
1266   ///
1267   /// If you don't use named rewrite streams, a "default" stream is used as
1268   /// the first example shows.
1269   /// </remarks>
1270   ITokenRewriteStream = interface(ICommonTokenStream)
1271   ['{7B49CBB6-9395-4781-B616-F201889EEA13}']
1272     { Methods }
1273     procedure Rollback(const InstructionIndex: Integer); overload;
1274 
1275     /// <summary>Rollback the instruction stream for a program so that
1276     /// the indicated instruction (via instructionIndex) is no
1277     /// longer in the stream.  UNTESTED!
1278     /// </summary>
1279     procedure Rollback(const ProgramName: String;
1280       const InstructionIndex: Integer); overload;
1281 
1282     procedure DeleteProgram; overload;
1283 
1284     /// <summary>Reset the program so that no instructions exist </summary>
1285     procedure DeleteProgram(const ProgramName: String); overload;
1286 
1287     procedure InsertAfter(const T: IToken; const Text: IANTLRInterface); overload;
1288     procedure InsertAfter(const Index: Integer; const Text: IANTLRInterface); overload;
1289     procedure InsertAfter(const ProgramName: String; const T: IToken;
1290       const Text: IANTLRInterface); overload;
1291     procedure InsertAfter(const ProgramName: String; const Index: Integer;
1292       const Text: IANTLRInterface); overload;
1293     procedure InsertAfter(const T: IToken; const Text: String); overload;
1294     procedure InsertAfter(const Index: Integer; const Text: String); overload;
1295     procedure InsertAfter(const ProgramName: String; const T: IToken;
1296       const Text: String); overload;
1297     procedure InsertAfter(const ProgramName: String; const Index: Integer;
1298       const Text: String); overload;
1299 
1300     procedure InsertBefore(const T: IToken; const Text: IANTLRInterface); overload;
1301     procedure InsertBefore(const Index: Integer; const Text: IANTLRInterface); overload;
1302     procedure InsertBefore(const ProgramName: String; const T: IToken;
1303       const Text: IANTLRInterface); overload;
1304     procedure InsertBefore(const ProgramName: String; const Index: Integer;
1305       const Text: IANTLRInterface); overload;
1306     procedure InsertBefore(const T: IToken; const Text: String); overload;
1307     procedure InsertBefore(const Index: Integer; const Text: String); overload;
1308     procedure InsertBefore(const ProgramName: String; const T: IToken;
1309       const Text: String); overload;
1310     procedure InsertBefore(const ProgramName: String; const Index: Integer;
1311       const Text: String); overload;
1312 
1313     procedure Replace(const Index: Integer; const Text: IANTLRInterface); overload;
1314     procedure Replace(const Start, Stop: Integer; const Text: IANTLRInterface); overload;
1315     procedure Replace(const IndexT: IToken; const Text: IANTLRInterface); overload;
1316     procedure Replace(const Start, Stop: IToken; const Text: IANTLRInterface); overload;
1317     procedure Replace(const ProgramName: String; const Start, Stop: Integer;
1318       const Text: IANTLRInterface); overload;
1319     procedure Replace(const ProgramName: String; const Start, Stop: IToken;
1320       const Text: IANTLRInterface); overload;
1321     procedure Replace(const Index: Integer; const Text: String); overload;
1322     procedure Replace(const Start, Stop: Integer; const Text: String); overload;
1323     procedure Replace(const IndexT: IToken; const Text: String); overload;
1324     procedure Replace(const Start, Stop: IToken; const Text: String); overload;
1325     procedure Replace(const ProgramName: String; const Start, Stop: Integer;
1326       const Text: String); overload;
1327     procedure Replace(const ProgramName: String; const Start, Stop: IToken;
1328       const Text: String); overload;
1329 
1330     procedure Delete(const Index: Integer); overload;
1331     procedure Delete(const Start, Stop: Integer); overload;
1332     procedure Delete(const IndexT: IToken); overload;
1333     procedure Delete(const Start, Stop: IToken); overload;
1334     procedure Delete(const ProgramName: String; const Start, Stop: Integer); overload;
1335     procedure Delete(const ProgramName: String; const Start, Stop: IToken); overload;
1336 
GetLastRewriteTokenIndex()1337     function GetLastRewriteTokenIndex: Integer;
1338 
ToOriginalString()1339     function ToOriginalString: String; overload;
ToOriginalString(const Start, Stop: Integer)1340     function ToOriginalString(const Start, Stop: Integer): String; overload;
1341 
ToString(const ProgramName: String)1342     function ToString(const ProgramName: String): String; overload;
ToString(const ProgramName: String;1343     function ToString(const ProgramName: String;
1344       const Start, Stop: Integer): String; overload;
1345 
ToDebugString()1346     function ToDebugString: String; overload;
ToDebugString(const Start, Stop: Integer)1347     function ToDebugString(const Start, Stop: Integer): String; overload;
1348   end;
1349 
1350   /// <summary>The root of the ANTLR exception hierarchy.</summary>
1351   /// <remarks>
1352   /// To avoid English-only error messages and to generally make things
1353   /// as flexible as possible, these exceptions are not created with strings,
1354   /// but rather the information necessary to generate an error.  Then
1355   /// the various reporting methods in Parser and Lexer can be overridden
1356   /// to generate a localized error message.  For example, MismatchedToken
1357   /// exceptions are built with the expected token type.
1358   /// So, don't expect getMessage() to return anything.
1359   ///
1360   /// You can access the stack trace, which means that you can compute the
1361   /// complete trace of rules from the start symbol. This gives you considerable
1362   /// context information with which to generate useful error messages.
1363   ///
1364   /// ANTLR generates code that throws exceptions upon recognition error and
1365   /// also generates code to catch these exceptions in each rule.  If you
1366   /// want to quit upon first error, you can turn off the automatic error
1367   /// handling mechanism using rulecatch action, but you still need to
1368   /// override methods mismatch and recoverFromMismatchSet.
1369   ///
1370   /// In general, the recognition exceptions can track where in a grammar a
1371   /// problem occurred and/or what was the expected input.  While the parser
1372   /// knows its state (such as current input symbol and line info) that
1373   /// state can change before the exception is reported so current token index
1374   /// is computed and stored at exception time.  From this info, you can
1375   /// perhaps print an entire line of input not just a single token, for example.
1376   /// Better to just say the recognizer had a problem and then let the parser
1377   /// figure out a fancy report.
1378   /// </remarks>
1379   ERecognitionException = class(Exception)
1380   strict private
1381     FApproximateLineInfo: Boolean;
1382   strict protected
1383     /// <summary>What input stream did the error occur in? </summary>
1384     FInput: IIntStream;
1385 
1386     /// <summary>
1387     /// What is index of token/char were we looking at when the error occurred?
1388     /// </summary>
1389     FIndex: Integer;
1390 
1391     /// <summary>
1392     /// The current Token when an error occurred.  Since not all streams
1393     /// can retrieve the ith Token, we have to track the Token object.
1394     /// </summary>
1395     FToken: IToken;
1396 
1397     /// <summary>[Tree parser] Node with the problem.</summary>
1398     FNode: IANTLRInterface;
1399 
1400     /// <summary>The current char when an error occurred. For lexers. </summary>
1401     FC: Integer;
1402 
1403     /// <summary>Track the line at which the error occurred in case this is
1404     /// generated from a lexer.  We need to track this since the
1405     /// unexpected char doesn't carry the line info.
1406     /// </summary>
1407     FLine: Integer;
1408     FCharPositionInLine: Integer;
1409   strict protected
1410     procedure ExtractInformationFromTreeNodeStream(const Input: IIntStream);
GetUnexpectedType()1411     function GetUnexpectedType: Integer; virtual;
1412   public
1413     /// <summary>Used for remote debugger deserialization </summary>
1414     constructor Create; overload;
1415     constructor Create(const AMessage: String); overload;
1416     constructor Create(const AInput: IIntStream); overload;
1417     constructor Create(const AMessage: String; const AInput: IIntStream); overload;
1418 
1419     /// <summary>
1420     /// If you are parsing a tree node stream, you will encounter some
1421     /// imaginary nodes w/o line/col info.  We now search backwards looking
1422     /// for most recent token with line/col info, but notify getErrorHeader()
1423     /// that info is approximate.
1424     /// </summary>
1425     property ApproximateLineInfo: Boolean read FApproximateLineInfo write FApproximateLineInfo;
1426 
1427     /// <summary>
1428     /// Returns the current Token when the error occurred (for parsers
1429     /// although a tree parser might also set the token)
1430     /// </summary>
1431     property Token: IToken read FToken write FToken;
1432 
1433     /// <summary>
1434     /// Returns the [tree parser] node where the error occured (for tree parsers).
1435     /// </summary>
1436     property Node: IANTLRInterface read FNode write FNode;
1437 
1438     /// <summary>
1439     /// Returns the line at which the error occurred (for lexers)
1440     /// </summary>
1441     property Line: Integer read FLine write FLine;
1442 
1443     /// <summary>
1444     /// Returns the character position in the line when the error
1445     /// occurred (for lexers)
1446     /// </summary>
1447     property CharPositionInLine: Integer read FCharPositionInLine write FCharPositionInLine;
1448 
1449     /// <summary>Returns the input stream in which the error occurred</summary>
1450     property Input: IIntStream read FInput write FInput;
1451 
1452     /// <summary>
1453     /// Returns the token type or char of the unexpected input element
1454     /// </summary>
1455     property UnexpectedType: Integer read GetUnexpectedType;
1456 
1457     /// <summary>
1458     /// Returns the current char when the error occurred (for lexers)
1459     /// </summary>
1460     property Character: Integer read FC write FC;
1461 
1462     /// <summary>
1463     /// Returns the token/char index in the stream when the error occurred
1464     /// </summary>
1465     property Index: Integer read FIndex write FIndex;
1466   end;
1467 
1468   /// <summary>
1469   /// A mismatched char or Token or tree node.
1470   /// </summary>
1471   EMismatchedTokenException = class(ERecognitionException)
1472   strict private
1473     FExpecting: Integer;
1474   public
1475     constructor Create(const AExpecting: Integer; const AInput: IIntStream);
1476 
ToString()1477     function ToString: String; override;
1478 
1479     property Expecting: Integer read FExpecting write FExpecting;
1480   end;
1481 
1482   EUnwantedTokenException = class(EMismatchedTokenException)
1483   strict private
GetUnexpectedToken()1484     function GetUnexpectedToken: IToken;
1485   public
1486     property UnexpectedToken: IToken read GetUnexpectedToken;
1487 
ToString()1488     function ToString: String; override;
1489   end;
1490 
1491   /// <summary>
1492   /// We were expecting a token but it's not found. The current token
1493   /// is actually what we wanted next. Used for tree node errors too.
1494   /// </summary>
1495   EMissingTokenException = class(EMismatchedTokenException)
1496   strict private
1497     FInserted: IANTLRInterface;
GetMissingType()1498     function GetMissingType: Integer;
1499   public
1500     constructor Create(const AExpecting: Integer; const AInput: IIntStream;
1501       const AInserted: IANTLRInterface);
1502 
ToString()1503     function ToString: String; override;
1504 
1505     property MissingType: Integer read GetMissingType;
1506     property Inserted: IANTLRInterface read FInserted write FInserted;
1507   end;
1508 
1509   EMismatchedTreeNodeException = class(ERecognitionException)
1510   strict private
1511     FExpecting: Integer;
1512   public
1513     constructor Create(const AExpecting: Integer; const AInput: IIntStream);
1514 
ToString()1515     function ToString: String; override;
1516 
1517     property Expecting: Integer read FExpecting write FExpecting;
1518   end;
1519 
1520   ENoViableAltException = class(ERecognitionException)
1521   strict private
1522     FGrammarDecisionDescription: String;
1523     FDecisionNumber: Integer;
1524     FStateNumber: Integer;
1525   public
1526     constructor Create(const AGrammarDecisionDescription: String;
1527       const ADecisionNumber, AStateNumber: Integer; const AInput: IIntStream);
1528 
ToString()1529     function ToString: String; override;
1530 
1531     property GrammarDecisionDescription: String read FGrammarDecisionDescription;
1532     property DecisionNumber: Integer read FDecisionNumber;
1533     property StateNumber: Integer read FStateNumber;
1534   end;
1535 
1536   EEarlyExitException = class(ERecognitionException)
1537   strict private
1538     FDecisionNumber: Integer;
1539   public
1540     constructor Create(const ADecisionNumber: Integer; const AInput: IIntStream);
1541 
1542     property DecisionNumber: Integer read FDecisionNumber;
1543   end;
1544 
1545   EMismatchedSetException = class(ERecognitionException)
1546   strict private
1547     FExpecting: IBitSet;
1548   public
1549     constructor Create(const AExpecting: IBitSet; const AInput: IIntStream);
1550 
ToString()1551     function ToString: String; override;
1552 
1553     property Expecting: IBitSet read FExpecting write FExpecting;
1554   end;
1555 
1556   EMismatchedNotSetException = class(EMismatchedSetException)
1557 
1558   public
ToString()1559     function ToString: String; override;
1560   end;
1561 
1562   EFailedPredicateException = class(ERecognitionException)
1563   strict private
1564     FRuleName: String;
1565     FPredicateText: String;
1566   public
1567     constructor Create(const AInput: IIntStream; const ARuleName,
1568       APredicateText: String);
1569 
ToString()1570     function ToString: String; override;
1571 
1572     property RuleName: String read FRuleName write FRuleName;
1573     property PredicateText: String read FPredicateText write FPredicateText;
1574   end;
1575 
1576   EMismatchedRangeException = class(ERecognitionException)
1577   strict private
1578     FA: Integer;
1579     FB: Integer;
1580   public
1581     constructor Create(const AA, AB: Integer; const AInput: IIntStream);
1582 
ToString()1583     function ToString: String; override;
1584 
1585     property A: Integer read FA write FA;
1586     property B: Integer read FB write FB;
1587   end;
1588 
1589 type
1590   TCharStreamState = class(TANTLRObject, ICharStreamState)
1591   strict private
1592     FP: Integer;
1593     FLine: Integer;
1594     FCharPositionInLine: Integer;
1595   protected
1596     { ICharStreamState }
GetP()1597     function GetP: Integer;
1598     procedure SetP(const Value: Integer);
GetLine()1599     function GetLine: Integer;
1600     procedure SetLine(const Value: Integer);
GetCharPositionInLine()1601     function GetCharPositionInLine: Integer;
1602     procedure SetCharPositionInLine(const Value: Integer);
1603   end;
1604 
1605 type
1606   TANTLRStringStream = class(TANTLRObject, IANTLRStringStream, ICharStream)
1607   private
1608     FData: PChar;
1609     FOwnsData: Boolean;
1610 
1611     /// <summary>How many characters are actually in the buffer?</summary>
1612     FN: Integer;
1613 
1614     /// <summary>Current line number within the input (1..n )</summary>
1615     FLine: Integer;
1616 
1617     /// <summary>Index in our array for the next char (0..n-1)</summary>
1618     FP: Integer;
1619 
1620     /// <summary>
1621     /// The index of the character relative to the beginning of the
1622     /// line (0..n-1)
1623     /// </summary>
1624     FCharPositionInLine: Integer;
1625 
1626     /// <summary>
1627     /// Tracks the depth of nested <see cref="IIntStream.Mark"/> calls
1628     /// </summary>
1629     FMarkDepth: Integer;
1630 
1631     /// <summary>
1632     /// A list of CharStreamState objects that tracks the stream state
1633     /// (i.e. line, charPositionInLine, and p) that can change as you
1634     /// move through the input stream.  Indexed from 1..markDepth.
1635     /// A null is kept @ index 0.  Create upon first call to Mark().
1636     /// </summary>
1637     FMarkers: IList<ICharStreamState>;
1638 
1639     /// <summary>
1640     /// Track the last Mark() call result value for use in Rewind().
1641     /// </summary>
1642     FLastMarker: Integer;
1643     /// <summary>
1644     /// What is name or source of this char stream?
1645     /// </summary>
1646     FName: String;
1647   protected
1648     { IIntStream }
GetSourceName()1649     function GetSourceName: String; virtual;
1650 
1651     procedure Consume; virtual;
LA(I: Integer)1652     function LA(I: Integer): Integer; virtual;
LAChar(I: Integer)1653     function LAChar(I: Integer): Char;
Index()1654     function Index: Integer;
Size()1655     function Size: Integer;
Mark()1656     function Mark: Integer; virtual;
1657     procedure Rewind(const Marker: Integer); overload; virtual;
1658     procedure Rewind; overload; virtual;
1659     procedure Release(const Marker: Integer); virtual;
1660     procedure Seek(const Index: Integer); virtual;
1661 
1662     property SourceName: String read GetSourceName write FName;
1663   protected
1664     { ICharStream }
GetLine()1665     function GetLine: Integer; virtual;
1666     procedure SetLine(const Value: Integer); virtual;
GetCharPositionInLine()1667     function GetCharPositionInLine: Integer; virtual;
1668     procedure SetCharPositionInLine(const Value: Integer); virtual;
LT(const I: Integer)1669     function LT(const I: Integer): Integer; virtual;
Substring(const Start, Stop: Integer)1670     function Substring(const Start, Stop: Integer): String; virtual;
1671   protected
1672     { IANTLRStringStream }
1673     procedure Reset; virtual;
1674   public
1675     constructor Create; overload;
1676 
1677     /// <summary>
1678     /// Initializes a new instance of the ANTLRStringStream class for the
1679     /// specified string. This copies data from the string to a local
1680     /// character array
1681     /// </summary>
1682     constructor Create(const AInput: String); overload;
1683 
1684     /// <summary>
1685     /// Initializes a new instance of the ANTLRStringStream class for the
1686     /// specified character array. This is the preferred constructor as
1687     /// no data is copied
1688     /// </summary>
1689     constructor Create(const AData: PChar;
1690       const ANumberOfActualCharsInArray: Integer); overload;
1691 
1692     destructor Destroy; override;
1693   end;
1694 
1695   TANTLRFileStream = class(TANTLRStringStream, IANTLRFileStream)
1696   strict private
1697     /// <summary>Fully qualified name of the stream's underlying file</summary>
1698     FFileName: String;
1699   protected
1700     { IIntStream }
GetSourceName()1701     function GetSourceName: String; override;
1702   protected
1703     { IANTLRFileStream }
1704 
1705     procedure Load(const FileName: String; const Encoding: TEncoding); virtual;
1706   public
1707     /// <summary>
1708     /// Initializes a new instance of the ANTLRFileStream class for the
1709     /// specified file name
1710     /// </summary>
1711     constructor Create(const AFileName: String); overload;
1712 
1713     /// <summary>
1714     /// Initializes a new instance of the ANTLRFileStream class for the
1715     /// specified file name and encoding
1716     /// </summary>
1717     constructor Create(const AFileName: String; const AEncoding: TEncoding); overload;
1718   end;
1719 
1720   TBitSet = class(TANTLRObject, IBitSet, ICloneable)
1721   strict private
1722     const
1723       BITS = 64; // number of bits / ulong
1724       LOG_BITS = 6; // 2 shl 6 = 64
1725 
1726       ///<summary> We will often need to do a mod operator (i mod nbits).
1727       /// Its turns out that, for powers of two, this mod operation is
1728       ///  same as <![CDATA[(I and (nbits-1))]]>.  Since mod is slow, we use a precomputed
1729       /// mod mask to do the mod instead.
1730       /// </summary>
1731       MOD_MASK = BITS - 1;
1732   strict private
1733     /// <summary>The actual data bits </summary>
1734     FBits: TUInt64Array;
1735   strict private
WordNumber(const Bit: Integer)1736     class function WordNumber(const Bit: Integer): Integer; static;
BitMask(const BitNumber: Integer)1737     class function BitMask(const BitNumber: Integer): UInt64; static;
NumWordsToHold(const El: Integer)1738     class function NumWordsToHold(const El: Integer): Integer; static;
1739   protected
1740     { ICloneable }
Clone()1741     function Clone: IANTLRInterface; virtual;
1742   protected
1743     { IBitSet }
GetIsNil()1744     function GetIsNil: Boolean; virtual;
BitSetOr(const A: IBitSet)1745     function BitSetOr(const A: IBitSet): IBitSet; virtual;
1746     procedure Add(const El: Integer); virtual;
1747     procedure GrowToInclude(const Bit: Integer); virtual;
1748     procedure OrInPlace(const A: IBitSet); virtual;
Size()1749     function Size: Integer; virtual;
Member(const El: Integer)1750     function Member(const El: Integer): Boolean; virtual;
1751     procedure Remove(const El: Integer); virtual;
NumBits()1752     function NumBits: Integer; virtual;
LengthInLongWords()1753     function LengthInLongWords: Integer; virtual;
ToArray()1754     function ToArray: TIntegerArray; virtual;
ToPackedArray()1755     function ToPackedArray: TUInt64Array; virtual;
ToString(const TokenNames: TStringArray)1756     function ToString(const TokenNames: TStringArray): String; reintroduce; overload; virtual;
1757   public
1758     /// <summary>Construct a bitset of size one word (64 bits) </summary>
1759     constructor Create; overload;
1760 
1761     /// <summary>Construction from a static array of ulongs </summary>
1762     constructor Create(const ABits: array of UInt64); overload;
1763 
1764     /// <summary>Construction from a list of integers </summary>
1765     constructor Create(const AItems: IList<Integer>); overload;
1766 
1767     /// <summary>Construct a bitset given the size</summary>
1768     /// <param name="nbits">The size of the bitset in bits</param>
1769     constructor Create(const ANBits: Integer); overload;
1770 
BitSetOf(const El: Integer)1771     class function BitSetOf(const El: Integer): IBitSet; overload; static;
BitSetOf(const A, B: Integer)1772     class function BitSetOf(const A, B: Integer): IBitSet; overload; static;
BitSetOf(const A, B, C: Integer)1773     class function BitSetOf(const A, B, C: Integer): IBitSet; overload; static;
BitSetOf(const A, B, C, D: Integer)1774     class function BitSetOf(const A, B, C, D: Integer): IBitSet; overload; static;
1775 
ToString()1776     function ToString: String; overload; override;
Equals(Obj: TObject)1777     function Equals(Obj: TObject): Boolean; override;
1778   end;
1779 
1780   TRecognizerSharedState = class(TANTLRObject, IRecognizerSharedState)
1781   strict private
1782     FFollowing: TBitSetArray;
1783     FFollowingStackPointer: Integer;
1784     FErrorRecovery: Boolean;
1785     FLastErrorIndex: Integer;
1786     FFailed: Boolean;
1787     FSyntaxErrors: Integer;
1788     FBacktracking: Integer;
1789     FRuleMemo: TDictionaryArray<Integer, Integer>;
1790     FToken: IToken;
1791     FTokenStartCharIndex: Integer;
1792     FTokenStartLine: Integer;
1793     FTokenStartCharPositionInLine: Integer;
1794     FChannel: Integer;
1795     FTokenType: Integer;
1796     FText: String;
1797   protected
1798     { IRecognizerSharedState }
GetFollowing()1799     function GetFollowing: TBitSetArray;
1800     procedure SetFollowing(const Value: TBitSetArray);
GetFollowingStackPointer()1801     function GetFollowingStackPointer: Integer;
1802     procedure SetFollowingStackPointer(const Value: Integer);
GetErrorRecovery()1803     function GetErrorRecovery: Boolean;
1804     procedure SetErrorRecovery(const Value: Boolean);
GetLastErrorIndex()1805     function GetLastErrorIndex: Integer;
1806     procedure SetLastErrorIndex(const Value: Integer);
GetFailed()1807     function GetFailed: Boolean;
1808     procedure SetFailed(const Value: Boolean);
GetSyntaxErrors()1809     function GetSyntaxErrors: Integer;
1810     procedure SetSyntaxErrors(const Value: Integer);
GetBacktracking()1811     function GetBacktracking: Integer;
1812     procedure SetBacktracking(const Value: Integer);
GetRuleMemo()1813     function GetRuleMemo: TDictionaryArray<Integer, Integer>;
GetRuleMemoCount()1814     function GetRuleMemoCount: Integer;
1815     procedure SetRuleMemoCount(const Value: Integer);
GetToken()1816     function GetToken: IToken;
1817     procedure SetToken(const Value: IToken);
GetTokenStartCharIndex()1818     function GetTokenStartCharIndex: Integer;
1819     procedure SetTokenStartCharIndex(const Value: Integer);
GetTokenStartLine()1820     function GetTokenStartLine: Integer;
1821     procedure SetTokenStartLine(const Value: Integer);
GetTokenStartCharPositionInLine()1822     function GetTokenStartCharPositionInLine: Integer;
1823     procedure SetTokenStartCharPositionInLine(const Value: Integer);
GetChannel()1824     function GetChannel: Integer;
1825     procedure SetChannel(const Value: Integer);
GetTokenType()1826     function GetTokenType: Integer;
1827     procedure SetTokenType(const Value: Integer);
GetText()1828     function GetText: String;
1829     procedure SetText(const Value: String);
1830   public
1831     constructor Create;
1832   end;
1833 
1834   TCommonToken = class(TANTLRObject, ICommonToken, IToken)
1835   strict protected
1836     FTokenType: Integer;
1837     FLine: Integer;
1838     FCharPositionInLine: Integer;
1839     FChannel: Integer;
1840     FInput: ICharStream;
1841 
1842     /// <summary>We need to be able to change the text once in a while.  If
1843     /// this is non-null, then getText should return this.  Note that
1844     /// start/stop are not affected by changing this.
1845     /// </summary>
1846     FText: String;
1847 
1848     /// <summary>What token number is this from 0..n-1 tokens; &lt; 0 implies invalid index </summary>
1849     FIndex: Integer;
1850 
1851     /// <summary>The char position into the input buffer where this token starts </summary>
1852     FStart: Integer;
1853 
1854     /// <summary>The char position into the input buffer where this token stops </summary>
1855     FStop: Integer;
1856   protected
1857     { IToken }
GetTokenType()1858     function GetTokenType: Integer; virtual;
1859     procedure SetTokenType(const Value: Integer); virtual;
GetLine()1860     function GetLine: Integer; virtual;
1861     procedure SetLine(const Value: Integer); virtual;
GetCharPositionInLine()1862     function GetCharPositionInLine: Integer; virtual;
1863     procedure SetCharPositionInLine(const Value: Integer); virtual;
GetChannel()1864     function GetChannel: Integer; virtual;
1865     procedure SetChannel(const Value: Integer); virtual;
GetTokenIndex()1866     function GetTokenIndex: Integer; virtual;
1867     procedure SetTokenIndex(const Value: Integer); virtual;
GetText()1868     function GetText: String; virtual;
1869     procedure SetText(const Value: String); virtual;
1870   protected
1871     { ICommonToken }
GetStartIndex()1872     function GetStartIndex: Integer;
1873     procedure SetStartIndex(const Value: Integer);
GetStopIndex()1874     function GetStopIndex: Integer;
1875     procedure SetStopIndex(const Value: Integer);
GetInputStream()1876     function GetInputStream: ICharStream;
1877     procedure SetInputStream(const Value: ICharStream);
1878   protected
1879     constructor Create; overload;
1880   public
1881     constructor Create(const ATokenType: Integer); overload;
1882     constructor Create(const AInput: ICharStream; const ATokenType, AChannel,
1883       AStart, AStop: Integer); overload;
1884     constructor Create(const ATokenType: Integer; const AText: String); overload;
1885     constructor Create(const AOldToken: IToken); overload;
1886 
ToString()1887     function ToString: String; override;
1888   end;
1889 
1890   TClassicToken = class(TANTLRObject, IClassicToken, IToken)
1891   strict private
1892     FText: String;
1893     FTokenType: Integer;
1894     FLine: Integer;
1895     FCharPositionInLine: Integer;
1896     FChannel: Integer;
1897 
1898     /// <summary>What token number is this from 0..n-1 tokens </summary>
1899     FIndex: Integer;
1900   protected
1901     { IClassicToken }
GetTokenType()1902     function GetTokenType: Integer; virtual;
1903     procedure SetTokenType(const Value: Integer); virtual;
GetLine()1904     function GetLine: Integer; virtual;
1905     procedure SetLine(const Value: Integer); virtual;
GetCharPositionInLine()1906     function GetCharPositionInLine: Integer; virtual;
1907     procedure SetCharPositionInLine(const Value: Integer); virtual;
GetChannel()1908     function GetChannel: Integer; virtual;
1909     procedure SetChannel(const Value: Integer); virtual;
GetTokenIndex()1910     function GetTokenIndex: Integer; virtual;
1911     procedure SetTokenIndex(const Value: Integer); virtual;
GetText()1912     function GetText: String; virtual;
1913     procedure SetText(const Value: String); virtual;
GetInputStream()1914     function GetInputStream: ICharStream; virtual;
1915     procedure SetInputStream(const Value: ICharStream); virtual;
1916   public
1917     constructor Create(const ATokenType: Integer); overload;
1918     constructor Create(const AOldToken: IToken); overload;
1919     constructor Create(const ATokenType: Integer; const AText: String); overload;
1920     constructor Create(const ATokenType: Integer; const AText: String;
1921       const AChannel: Integer); overload;
1922 
ToString()1923     function ToString: String; override;
1924   end;
1925 
1926   TToken = class sealed
1927   public
1928     const
1929       EOR_TOKEN_TYPE = 1;
1930 
1931       /// <summary>imaginary tree navigation type; traverse "get child" link </summary>
1932       DOWN = 2;
1933 
1934       /// <summary>imaginary tree navigation type; finish with a child list </summary>
1935       UP = 3;
1936 
1937       MIN_TOKEN_TYPE = UP + 1;
1938       EOF = Integer(cscEOF);
1939       INVALID_TOKEN_TYPE = 0;
1940 
1941       /// <summary>
1942       /// All tokens go to the parser (unless skip() is called in that rule)
1943       /// on a particular "channel".  The parser tunes to a particular channel
1944       /// so that whitespace etc... can go to the parser on a "hidden" channel.
1945       /// </summary>
1946       DEFAULT_CHANNEL = 0;
1947 
1948       /// <summary>
1949       /// Anything on different channel than DEFAULT_CHANNEL is not parsed by parser.
1950       /// </summary>
1951       HIDDEN_CHANNEL = 99;
1952   public
1953     class var
1954       EOF_TOKEN: IToken;
1955       INVALID_TOKEN: IToken;
1956       /// <summary>
1957       /// In an action, a lexer rule can set token to this SKIP_TOKEN and ANTLR
1958       /// will avoid creating a token for this symbol and try to fetch another.
1959       /// </summary>
1960       SKIP_TOKEN: IToken;
1961   private
1962     class procedure Initialize; static;
1963   end;
1964 
1965   /// <summary>
1966     /// Global constants
1967   /// </summary>
1968   TConstants = class sealed
1969   public
1970     const
1971       VERSION = '3.1b1';
1972 
1973       // Moved to version 2 for v3.1: added grammar name to enter/exit Rule
1974       DEBUG_PROTOCOL_VERSION = '2';
1975 
1976       ANTLRWORKS_DIR = 'antlrworks';
1977   end;
1978 
1979   TBaseRecognizer = class abstract(TANTLRObject, IBaseRecognizer)
1980   public
1981     const
1982       MEMO_RULE_FAILED = -2;
1983       MEMO_RULE_UNKNOWN = -1;
1984       INITIAL_FOLLOW_STACK_SIZE = 100;
1985       NEXT_TOKEN_RULE_NAME = 'nextToken';
1986       // copies from Token object for convenience in actions
1987       DEFAULT_TOKEN_CHANNEL = TToken.DEFAULT_CHANNEL;
1988       HIDDEN = TToken.HIDDEN_CHANNEL;
1989   strict protected
1990     /// <summary>
1991     /// An externalized representation of the - shareable - internal state of
1992     /// this lexer, parser or tree parser.
1993     /// </summary>
1994     /// <remarks>
1995     /// The state of a lexer, parser, or tree parser are collected into
1996     /// external state objects so that the state can be shared. This sharing
1997     /// is needed to have one grammar import others and share same error
1998     /// variables and other state variables.  It's a kind of explicit multiple
1999     /// inheritance via delegation of methods and shared state.
2000     /// </remarks>
2001     FState: IRecognizerSharedState;
2002 
2003     property State: IRecognizerSharedState read FState;
2004   strict protected
2005     /// <summary>
2006     /// Match needs to return the current input symbol, which gets put
2007     /// into the label for the associated token ref; e.g., x=ID.  Token
2008     /// and tree parsers need to return different objects. Rather than test
2009     /// for input stream type or change the IntStream interface, I use
2010     /// a simple method to ask the recognizer to tell me what the current
2011     /// input symbol is.
2012     /// </summary>
2013     /// <remarks>This is ignored for lexers.</remarks>
GetCurrentInputSymbol(const Input: IIntStream)2014     function GetCurrentInputSymbol(const Input: IIntStream): IANTLRInterface; virtual;
2015 
2016     /// <summary>
2017     /// Factor out what to do upon token mismatch so tree parsers can behave
2018     /// differently.  Override and call MismatchRecover(input, ttype, follow)
2019     /// to get single token insertion and deletion. Use this to turn off
2020     /// single token insertion and deletion. Override mismatchRecover
2021     /// to call this instead.
2022     /// </summary>
2023     procedure Mismatch(const Input: IIntStream; const TokenType: Integer;
2024       const Follow: IBitSet); virtual;
2025 
2026     /// <summary>
2027     /// Attempt to Recover from a single missing or extra token.
2028     /// </summary>
2029     /// <remarks>
2030     /// EXTRA TOKEN
2031     ///
2032     /// LA(1) is not what we are looking for.  If LA(2) has the right token,
2033     /// however, then assume LA(1) is some extra spurious token.  Delete it
2034     /// and LA(2) as if we were doing a normal Match(), which advances the
2035     /// input.
2036     ///
2037     /// MISSING TOKEN
2038     ///
2039     /// If current token is consistent with what could come after
2040     /// ttype then it is ok to "insert" the missing token, else throw
2041     /// exception For example, Input "i=(3;" is clearly missing the
2042     /// ')'.  When the parser returns from the nested call to expr, it
2043     /// will have call chain:
2044     ///
2045     /// stat -> expr -> atom
2046     ///
2047     /// and it will be trying to Match the ')' at this point in the
2048     /// derivation:
2049     ///
2050     /// => ID '=' '(' INT ')' ('+' atom)* ';'
2051     /// ^
2052     /// Match() will see that ';' doesn't Match ')' and report a
2053     /// mismatched token error.  To Recover, it sees that LA(1)==';'
2054     /// is in the set of tokens that can follow the ')' token
2055     /// reference in rule atom.  It can assume that you forgot the ')'.
2056     /// </remarks>
RecoverFromMismatchedToken(const Input: IIntStream;2057     function RecoverFromMismatchedToken(const Input: IIntStream;
2058       const TokenType: Integer; const Follow: IBitSet): IANTLRInterface; virtual;
2059 
2060     /// <summary>
2061     /// Conjure up a missing token during error recovery.
2062     /// </summary>
2063     /// <remarks>
2064     /// The recognizer attempts to recover from single missing
2065     /// symbols. But, actions might refer to that missing symbol.
2066     /// For example, x=ID {f($x);}. The action clearly assumes
2067     /// that there has been an identifier matched previously and that
2068     /// $x points at that token. If that token is missing, but
2069     /// the next token in the stream is what we want we assume that
2070     /// this token is missing and we keep going. Because we
2071     /// have to return some token to replace the missing token,
2072     /// we have to conjure one up. This method gives the user control
2073     /// over the tokens returned for missing tokens. Mostly,
2074     /// you will want to create something special for identifier
2075     /// tokens. For literals such as '{' and ',', the default
2076     /// action in the parser or tree parser works. It simply creates
2077     /// a CommonToken of the appropriate type. The text will be the token.
2078     /// If you change what tokens must be created by the lexer,
2079     /// override this method to create the appropriate tokens.
2080     /// </remarks>
GetMissingSymbol(const Input: IIntStream;2081     function GetMissingSymbol(const Input: IIntStream;
2082       const E: ERecognitionException; const ExpectedTokenType: Integer;
2083       const Follow: IBitSet): IANTLRInterface; virtual;
2084 
2085     /// <summary>
2086     /// Push a rule's follow set using our own hardcoded stack
2087     /// </summary>
2088     /// <param name="fset"></param>
2089     procedure PushFollow(const FSet: IBitSet);
2090 
2091     /// <summary>Compute the context-sensitive FOLLOW set for current rule.
2092     /// This is set of token types that can follow a specific rule
2093     /// reference given a specific call chain.  You get the set of
2094     /// viable tokens that can possibly come next (lookahead depth 1)
2095     /// given the current call chain.  Contrast this with the
2096     /// definition of plain FOLLOW for rule r:
2097     ///
2098     /// FOLLOW(r)={x | S=>*alpha r beta in G and x in FIRST(beta)}
2099     ///
2100     /// where x in T* and alpha, beta in V*; T is set of terminals and
2101     /// V is the set of terminals and nonterminals.  In other words,
2102     /// FOLLOW(r) is the set of all tokens that can possibly follow
2103     /// references to r in *any* sentential form (context).  At
2104     /// runtime, however, we know precisely which context applies as
2105     /// we have the call chain.  We may compute the exact (rather
2106     /// than covering superset) set of following tokens.
2107     ///
2108     /// For example, consider grammar:
2109     ///
2110     /// stat : ID '=' expr ';'      // FOLLOW(stat)=={EOF}
2111     /// | "return" expr '.'
2112     /// ;
2113     /// expr : atom ('+' atom)* ;   // FOLLOW(expr)=={';','.',')'}
2114     /// atom : INT                  // FOLLOW(atom)=={'+',')',';','.'}
2115     /// | '(' expr ')'
2116     /// ;
2117     ///
2118     /// The FOLLOW sets are all inclusive whereas context-sensitive
2119     /// FOLLOW sets are precisely what could follow a rule reference.
2120     /// For input input "i=(3);", here is the derivation:
2121     ///
2122     /// stat => ID '=' expr ';'
2123     /// => ID '=' atom ('+' atom)* ';'
2124     /// => ID '=' '(' expr ')' ('+' atom)* ';'
2125     /// => ID '=' '(' atom ')' ('+' atom)* ';'
2126     /// => ID '=' '(' INT ')' ('+' atom)* ';'
2127     /// => ID '=' '(' INT ')' ';'
2128     ///
2129     /// At the "3" token, you'd have a call chain of
2130     ///
2131     /// stat -> expr -> atom -> expr -> atom
2132     ///
2133     /// What can follow that specific nested ref to atom?  Exactly ')'
2134     /// as you can see by looking at the derivation of this specific
2135     /// input.  Contrast this with the FOLLOW(atom)={'+',')',';','.'}.
2136     ///
2137     /// You want the exact viable token set when recovering from a
2138     /// token mismatch.  Upon token mismatch, if LA(1) is member of
2139     /// the viable next token set, then you know there is most likely
2140     /// a missing token in the input stream.  "Insert" one by just not
2141     /// throwing an exception.
2142     /// </summary>
ComputeContextSensitiveRuleFOLLOW()2143     function ComputeContextSensitiveRuleFOLLOW: IBitSet; virtual;
2144 
2145     (*  Compute the error recovery set for the current rule.  During
2146     *  rule invocation, the parser pushes the set of tokens that can
2147     *  follow that rule reference on the stack; this amounts to
2148     *  computing FIRST of what follows the rule reference in the
2149     *  enclosing rule. This local follow set only includes tokens
2150     *  from within the rule; i.e., the FIRST computation done by
2151     *  ANTLR stops at the end of a rule.
2152     *
2153     *  EXAMPLE
2154     *
2155     *  When you find a "no viable alt exception", the input is not
2156     *  consistent with any of the alternatives for rule r.  The best
2157     *  thing to do is to consume tokens until you see something that
2158     *  can legally follow a call to r *or* any rule that called r.
2159     *  You don't want the exact set of viable next tokens because the
2160     *  input might just be missing a token--you might consume the
2161     *  rest of the input looking for one of the missing tokens.
2162     *
2163     *  Consider grammar:
2164     *
2165     *  a : '[' b ']'
2166     *    | '(' b ')'
2167     *    ;
2168     *  b : c '^' INT ;
2169     *  c : ID
2170     *    | INT
2171     *    ;
2172     *
2173     *  At each rule invocation, the set of tokens that could follow
2174     *  that rule is pushed on a stack.  Here are the various "local"
2175     *  follow sets:
2176     *
2177     *  FOLLOW(b1_in_a) = FIRST(']') = ']'
2178     *  FOLLOW(b2_in_a) = FIRST(')') = ')'
2179     *  FOLLOW(c_in_b) = FIRST('^') = '^'
2180     *
2181     *  Upon erroneous input "[]", the call chain is
2182     *
2183     *  a -> b -> c
2184     *
2185     *  and, hence, the follow context stack is:
2186     *
2187     *  depth  local follow set     after call to rule
2188     *    0         <EOF>                    a (from main())
2189     *    1          ']'                     b
2190     *    3          '^'                     c
2191     *
2192     *  Notice that ')' is not included, because b would have to have
2193     *  been called from a different context in rule a for ')' to be
2194     *  included.
2195     *
2196     *  For error recovery, we cannot consider FOLLOW(c)
2197     *  (context-sensitive or otherwise).  We need the combined set of
2198     *  all context-sensitive FOLLOW sets--the set of all tokens that
2199     *  could follow any reference in the call chain.  We need to
2200     *  resync to one of those tokens.  Note that FOLLOW(c)='^' and if
2201     *  we resync'd to that token, we'd consume until EOF.  We need to
2202     *  sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
2203     *  In this case, for input "[]", LA(1) is in this set so we would
2204     *  not consume anything and after printing an error rule c would
2205     *  return normally.  It would not find the required '^' though.
2206     *  At this point, it gets a mismatched token error and throws an
2207     *  exception (since LA(1) is not in the viable following token
2208     *  set).  The rule exception handler tries to Recover, but finds
2209     *  the same recovery set and doesn't consume anything.  Rule b
2210     *  exits normally returning to rule a.  Now it finds the ']' (and
2211     *  with the successful Match exits errorRecovery mode).
2212     *
2213     *  So, you cna see that the parser walks up call chain looking
2214     *  for the token that was a member of the recovery set.
2215     *
2216     *  Errors are not generated in errorRecovery mode.
2217     *
2218     *  ANTLR's error recovery mechanism is based upon original ideas:
2219     *
2220     *  "Algorithms + Data Structures = Programs" by Niklaus Wirth
2221     *
2222     *  and
2223     *
2224     *  "A note on error recovery in recursive descent parsers":
2225     *  http://portal.acm.org/citation.cfm?id=947902.947905
2226     *
2227     *  Later, Josef Grosch had some good ideas:
2228     *
2229     *  "Efficient and Comfortable Error Recovery in Recursive Descent
2230     *  Parsers":
2231     *  ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
2232     *
2233     *  Like Grosch I implemented local FOLLOW sets that are combined
2234     *  at run-time upon error to avoid overhead during parsing.
2235     *)
ComputeErrorRecoverySet()2236     function ComputeErrorRecoverySet: IBitSet; virtual;
2237 
CombineFollows(const Exact: Boolean)2238     function CombineFollows(const Exact: Boolean): IBitSet;
2239   protected
2240     { IBaseRecognizer }
GetInput()2241     function GetInput: IIntStream; virtual; abstract;
GetBacktrackingLevel()2242     function GetBacktrackingLevel: Integer;
GetState()2243     function GetState: IRecognizerSharedState;
GetNumberOfSyntaxErrors()2244     function GetNumberOfSyntaxErrors: Integer;
GetGrammarFileName()2245     function GetGrammarFileName: String; virtual;
GetSourceName()2246     function GetSourceName: String; virtual; abstract;
GetTokenNames()2247     function GetTokenNames: TStringArray; virtual;
2248 
2249     procedure BeginBacktrack(const Level: Integer); virtual;
2250     procedure EndBacktrack(const Level: Integer; const Successful: Boolean); virtual;
2251     procedure Reset; virtual;
Match(const Input: IIntStream; const TokenType: Integer;2252     function Match(const Input: IIntStream; const TokenType: Integer;
2253       const Follow: IBitSet): IANTLRInterface; virtual;
MismatchIsUnwantedToken(const Input: IIntStream;2254     function MismatchIsUnwantedToken(const Input: IIntStream;
2255       const TokenType: Integer): Boolean;
MismatchIsMissingToken(const Input: IIntStream;2256     function MismatchIsMissingToken(const Input: IIntStream;
2257       const Follow: IBitSet): Boolean;
2258     procedure BeginResync; virtual;
2259     procedure EndResync; virtual;
2260     procedure ReportError(const E: ERecognitionException); virtual;
2261     procedure MatchAny(const Input: IIntStream); virtual;
2262     procedure DisplayRecognitionError(const TokenNames: TStringArray;
2263       const E: ERecognitionException); virtual;
GetErrorMessage(const E: ERecognitionException;2264     function GetErrorMessage(const E: ERecognitionException;
2265       const TokenNames: TStringArray): String; virtual;
GetErrorHeader(const E: ERecognitionException)2266     function GetErrorHeader(const E: ERecognitionException): String; virtual;
GetTokenErrorDisplay(const T: IToken)2267     function GetTokenErrorDisplay(const T: IToken): String; virtual;
2268     procedure EmitErrorMessage(const Msg: String); virtual;
2269     procedure Recover(const Input: IIntStream; const RE: ERecognitionException); virtual;
RecoverFromMismatchedSet(const Input: IIntStream;2270     function RecoverFromMismatchedSet(const Input: IIntStream;
2271       const E: ERecognitionException; const Follow: IBitSet): IANTLRInterface; virtual;
2272     procedure ConsumeUntil(const Input: IIntStream; const TokenType: Integer); overload; virtual;
2273     procedure ConsumeUntil(const Input: IIntStream; const BitSet: IBitSet); overload; virtual;
2274     //function GetRuleInvocationStack: IList<IANTLRInterface>; overload; virtual;
2275     //function GetRuleInvocationStack(const E: Exception;
2276     //  const RecognizerClassName: String): IList<IANTLRInterface>; overload;
ToStrings(const Tokens: IList<IToken>)2277     function ToStrings(const Tokens: IList<IToken>): IList<String>; virtual;
GetRuleMemoization(const RuleIndex, RuleStartIndex: Integer)2278     function GetRuleMemoization(const RuleIndex, RuleStartIndex: Integer): Integer; virtual;
AlreadyParsedRule(const Input: IIntStream;2279     function AlreadyParsedRule(const Input: IIntStream;
2280       const RuleIndex: Integer): Boolean; virtual;
2281     procedure Memoize(const Input: IIntStream; const RuleIndex,
2282       RuleStartIndex: Integer); virtual;
GetRuleMemoizationChaceSize()2283     function GetRuleMemoizationChaceSize: Integer;
2284 
2285     procedure TraceIn(const RuleName: String; const RuleIndex: Integer;
2286       const InputSymbol: String); virtual;
2287     procedure TraceOut(const RuleName: String; const RuleIndex: Integer;
2288       const InputSymbol: String); virtual;
2289 
2290     property Input: IIntStream read GetInput;
2291   public
2292     constructor Create; overload;
2293     constructor Create(const AState: IRecognizerSharedState); overload;
2294   end;
2295 
2296   TCommonTokenStream = class(TANTLRObject, ICommonTokenStream, ITokenStream)
2297   strict private
2298     FTokenSource: ITokenSource;
2299 
2300     /// <summary>Record every single token pulled from the source so we can reproduce
2301     /// chunks of it later.
2302     /// </summary>
2303     FTokens: IList<IToken>;
2304 
2305     /// <summary><![CDATA[Map<tokentype, channel>]]> to override some Tokens' channel numbers </summary>
2306     FChannelOverrideMap: IDictionary<Integer, Integer>;
2307 
2308     /// <summary><![CDATA[Set<tokentype>;]]> discard any tokens with this type </summary>
2309     FDiscardSet: IHashList<Integer, Integer>;
2310 
2311     /// <summary>Skip tokens on any channel but this one; this is how we skip whitespace... </summary>
2312     FChannel: Integer;
2313 
2314     /// <summary>By default, track all incoming tokens </summary>
2315     FDiscardOffChannelTokens: Boolean;
2316 
2317     /// <summary>Track the last Mark() call result value for use in Rewind().</summary>
2318     FLastMarker: Integer;
2319 
2320     /// <summary>
2321     /// The index into the tokens list of the current token (next token
2322     /// to consume).  p==-1 indicates that the tokens list is empty
2323     /// </summary>
2324     FP: Integer;
2325   strict protected
2326     /// <summary>Load all tokens from the token source and put in tokens.
2327     /// This is done upon first LT request because you might want to
2328     /// set some token type / channel overrides before filling buffer.
2329     /// </summary>
2330     procedure FillBuffer; virtual;
2331 
2332     /// <summary>Look backwards k tokens on-channel tokens </summary>
LB(const K: Integer)2333     function LB(const K: Integer): IToken; virtual;
2334 
2335     /// <summary>Given a starting index, return the index of the first on-channel
2336     /// token.
2337     /// </summary>
SkipOffTokenChannels(const I: Integer)2338     function SkipOffTokenChannels(const I: Integer): Integer; virtual;
SkipOffTokenChannelsReverse(const I: Integer)2339     function SkipOffTokenChannelsReverse(const I: Integer): Integer; virtual;
2340   protected
2341     { IIntStream }
GetSourceName()2342     function GetSourceName: String; virtual;
2343 
2344     procedure Consume; virtual;
LA(I: Integer)2345     function LA(I: Integer): Integer; virtual;
LAChar(I: Integer)2346     function LAChar(I: Integer): Char;
Mark()2347     function Mark: Integer; virtual;
Index()2348     function Index: Integer; virtual;
2349     procedure Rewind(const Marker: Integer); overload; virtual;
2350     procedure Rewind; overload; virtual;
2351     procedure Release(const Marker: Integer); virtual;
2352     procedure Seek(const Index: Integer); virtual;
Size()2353     function Size: Integer; virtual;
2354   protected
2355     { ITokenStream }
GetTokenSource()2356     function GetTokenSource: ITokenSource; virtual;
2357     procedure SetTokenSource(const Value: ITokenSource); virtual;
2358 
LT(const K: Integer)2359     function LT(const K: Integer): IToken; virtual;
Get(const I: Integer)2360     function Get(const I: Integer): IToken; virtual;
ToString(const Start, Stop: Integer)2361     function ToString(const Start, Stop: Integer): String; reintroduce; overload; virtual;
ToString(const Start, Stop: IToken)2362     function ToString(const Start, Stop: IToken): String; reintroduce; overload; virtual;
2363   protected
2364     { ICommonTokenStream }
2365     procedure SetTokenTypeChannel(const TType, Channel: Integer);
2366     procedure DiscardTokenType(const TType: Integer);
2367     procedure DiscardOffChannelTokens(const Discard: Boolean);
GetTokens()2368     function GetTokens: IList<IToken>; overload;
GetTokens(const Start, Stop: Integer)2369     function GetTokens(const Start, Stop: Integer): IList<IToken>; overload;
GetTokens(const Start, Stop: Integer;2370     function GetTokens(const Start, Stop: Integer;
2371       const Types: IBitSet): IList<IToken>; overload;
GetTokens(const Start, Stop: Integer;2372     function GetTokens(const Start, Stop: Integer;
2373       const Types: IList<Integer>): IList<IToken>; overload;
GetTokens(const Start, Stop,2374     function GetTokens(const Start, Stop,
2375       TokenType: Integer): IList<IToken>; overload;
2376     procedure Reset; virtual;
2377   public
2378     constructor Create; overload;
2379     constructor Create(const ATokenSource: ITokenSource); overload;
2380     constructor Create(const ATokenSource: ITokenSource;
2381       const AChannel: Integer); overload;
2382     constructor Create(const ALexer: ILexer); overload;
2383     constructor Create(const ALexer: ILexer;
2384       const AChannel: Integer); overload;
2385 
ToString()2386     function ToString: String; overload; override;
2387   end;
2388 
2389   TDFA = class abstract(TANTLRObject, IDFA)
2390   strict private
2391     FSpecialStateTransitionHandler: TSpecialStateTransitionHandler;
2392     FEOT: TSmallintArray;
2393     FEOF: TSmallintArray;
2394     FMin: TCharArray;
2395     FMax: TCharArray;
2396     FAccept: TSmallintArray;
2397     FSpecial: TSmallintArray;
2398     FTransition: TSmallintMatrix;
2399     FDecisionNumber: Integer;
2400     FRecognizer: Pointer; { IBaseRecognizer }
GetRecognizer()2401     function GetRecognizer: IBaseRecognizer;
2402     procedure SetRecognizer(const Value: IBaseRecognizer);
2403   strict protected
2404     procedure NoViableAlt(const S: Integer; const Input: IIntStream);
2405 
2406     property Recognizer: IBaseRecognizer read GetRecognizer write SetRecognizer;
2407     property DecisionNumber: Integer read FDecisionNumber write FDecisionNumber;
2408     property EOT: TSmallintArray read FEOT write FEOT;
2409     property EOF: TSmallintArray read FEOF write FEOF;
2410     property Min: TCharArray read FMin write FMin;
2411     property Max: TCharArray read FMax write FMax;
2412     property Accept: TSmallintArray read FAccept write FAccept;
2413     property Special: TSmallintArray read FSpecial write FSpecial;
2414     property Transition: TSmallintMatrix read FTransition write FTransition;
2415   protected
2416     { IDFA }
GetSpecialStateTransitionHandler()2417     function GetSpecialStateTransitionHandler: TSpecialStateTransitionHandler;
2418     procedure SetSpecialStateTransitionHandler(const Value: TSpecialStateTransitionHandler);
2419 
Predict(const Input: IIntStream)2420     function Predict(const Input: IIntStream): Integer;
2421     procedure Error(const NVAE: ENoViableAltException); virtual;
SpecialStateTransition(const S: Integer;2422     function SpecialStateTransition(const S: Integer;
2423       const Input: IIntStream): Integer; virtual;
Description()2424     function Description: String; virtual;
SpecialTransition(const State, Symbol: Integer)2425     function SpecialTransition(const State, Symbol: Integer): Integer;
2426   public
UnpackEncodedString(const EncodedString: String)2427     class function UnpackEncodedString(const EncodedString: String): TSmallintArray; static;
UnpackEncodedStringArray(const EncodedStrings: TStringArray)2428     class function UnpackEncodedStringArray(const EncodedStrings: TStringArray): TSmallintMatrix; overload; static;
UnpackEncodedStringArray(const EncodedStrings: array of String)2429     class function UnpackEncodedStringArray(const EncodedStrings: array of String): TSmallintMatrix; overload; static;
UnpackEncodedStringToUnsignedChars(const EncodedString: String)2430     class function UnpackEncodedStringToUnsignedChars(const EncodedString: String): TCharArray; static;
2431   end;
2432 
2433   TLexer = class abstract(TBaseRecognizer, ILexer, ITokenSource)
2434   strict private
2435     const
2436       TOKEN_dot_EOF = Ord(cscEOF);
2437   strict private
2438     /// <summary>Where is the lexer drawing characters from? </summary>
2439     FInput: ICharStream;
2440   protected
2441     { IBaseRecognizer }
GetSourceName()2442     function GetSourceName: String; override;
GetInput()2443     function GetInput: IIntStream; override;
2444     procedure Reset; override;
2445     procedure ReportError(const E: ERecognitionException); override;
GetErrorMessage(const E: ERecognitionException;2446     function GetErrorMessage(const E: ERecognitionException;
2447       const TokenNames: TStringArray): String; override;
2448   protected
2449     { ILexer }
GetCharStream()2450     function GetCharStream: ICharStream; virtual;
2451     procedure SetCharStream(const Value: ICharStream); virtual;
GetLine()2452     function GetLine: Integer; virtual;
GetCharPositionInLine()2453     function GetCharPositionInLine: Integer; virtual;
GetCharIndex()2454     function GetCharIndex: Integer; virtual;
GetText()2455     function GetText: String; virtual;
2456     procedure SetText(const Value: String); virtual;
2457 
NextToken()2458     function NextToken: IToken; virtual;
2459     procedure Skip;
2460     procedure DoTokens; virtual; abstract;
2461     procedure Emit(const Token: IToken); overload; virtual;
Emit()2462     function Emit: IToken; overload; virtual;
2463     procedure Match(const S: String); reintroduce; overload; virtual;
2464     procedure Match(const C: Integer); reintroduce; overload; virtual;
2465     procedure MatchAny; reintroduce; overload; virtual;
2466     procedure MatchRange(const A, B: Integer); virtual;
2467     procedure Recover(const RE: ERecognitionException); reintroduce; overload; virtual;
GetCharErrorDisplay(const C: Integer)2468     function GetCharErrorDisplay(const C: Integer): String;
2469     procedure TraceIn(const RuleName: String; const RuleIndex: Integer); reintroduce; overload; virtual;
2470     procedure TraceOut(const RuleName: String; const RuleIndex: Integer); reintroduce; overload; virtual;
2471   strict protected
2472     property Input: ICharStream read FInput;
2473     property CharIndex: Integer read GetCharIndex;
2474     property Text: String read GetText write SetText;
2475   public
2476     constructor Create; overload;
2477     constructor Create(const AInput: ICharStream); overload;
2478     constructor Create(const AInput: ICharStream;
2479       const AState: IRecognizerSharedState); overload;
2480   end;
2481 
2482   TParser = class(TBaseRecognizer, IParser)
2483   strict private
2484     FInput: ITokenStream;
2485   protected
2486     property Input: ITokenStream read FInput;
2487   protected
2488     { IBaseRecognizer }
2489     procedure Reset; override;
GetCurrentInputSymbol(const Input: IIntStream)2490     function GetCurrentInputSymbol(const Input: IIntStream): IANTLRInterface; override;
GetMissingSymbol(const Input: IIntStream;2491     function GetMissingSymbol(const Input: IIntStream;
2492       const E: ERecognitionException; const ExpectedTokenType: Integer;
2493       const Follow: IBitSet): IANTLRInterface; override;
GetSourceName()2494     function GetSourceName: String; override;
GetInput()2495     function GetInput: IIntStream; override;
2496   protected
2497     { IParser }
GetTokenStream()2498     function GetTokenStream: ITokenStream; virtual;
2499     procedure SetTokenStream(const Value: ITokenStream); virtual;
2500 
2501     procedure TraceIn(const RuleName: String; const RuleIndex: Integer); reintroduce; overload;
2502     procedure TraceOut(const RuleName: String; const RuleIndex: Integer); reintroduce; overload;
2503   public
2504     constructor Create(const AInput: ITokenStream); overload;
2505     constructor Create(const AInput: ITokenStream;
2506       const AState: IRecognizerSharedState); overload;
2507   end;
2508 
2509   TRuleReturnScope = class(TANTLRObject, IRuleReturnScope)
2510   protected
2511     { IRuleReturnScope }
GetStart()2512     function GetStart: IANTLRInterface; virtual;
2513     procedure SetStart(const Value: IANTLRInterface); virtual;
GetStop()2514     function GetStop: IANTLRInterface; virtual;
2515     procedure SetStop(const Value: IANTLRInterface); virtual;
GetTree()2516     function GetTree: IANTLRInterface; virtual;
2517     procedure SetTree(const Value: IANTLRInterface); virtual;
GetTemplate()2518     function GetTemplate: IANTLRInterface; virtual;
2519   end;
2520 
2521   TParserRuleReturnScope = class(TRuleReturnScope, IParserRuleReturnScope)
2522   strict private
2523     FStart: IToken;
2524     FStop: IToken;
2525   protected
2526     { IRuleReturnScope }
GetStart()2527     function GetStart: IANTLRInterface; override;
2528     procedure SetStart(const Value: IANTLRInterface); override;
GetStop()2529     function GetStop: IANTLRInterface; override;
2530     procedure SetStop(const Value: IANTLRInterface); override;
2531   end;
2532 
2533   TTokenRewriteStream = class(TCommonTokenStream, ITokenRewriteStream)
2534   public
2535     const
2536       DEFAULT_PROGRAM_NAME = 'default';
2537       PROGRAM_INIT_SIZE = 100;
2538       MIN_TOKEN_INDEX = 0;
2539   strict protected
2540     // Define the rewrite operation hierarchy
2541     type
2542       IRewriteOperation = interface(IANTLRInterface)
2543       ['{285A54ED-58FF-44B1-A268-2686476D4419}']
2544         { Property accessors }
GetInstructionIndex()2545         function GetInstructionIndex: Integer;
2546         procedure SetInstructionIndex(const Value: Integer);
GetIndex()2547         function GetIndex: Integer;
2548         procedure SetIndex(const Value: Integer);
GetText()2549         function GetText: IANTLRInterface;
2550         procedure SetText(const Value: IANTLRInterface);
GetParent()2551         function GetParent: ITokenRewriteStream;
2552         procedure SetParent(const Value: ITokenRewriteStream);
2553 
2554         { Methods }
2555 
2556         /// <summary>Execute the rewrite operation by possibly adding to the buffer.
2557         /// Return the index of the next token to operate on.
2558         /// </summary>
Execute(const Buf: TStringBuilder)2559         function Execute(const Buf: TStringBuilder): Integer;
2560 
2561         { Properties }
2562         property InstructionIndex: Integer read GetInstructionIndex write SetInstructionIndex;
2563         property Index: Integer read GetIndex write SetIndex;
2564         property Text: IANTLRInterface read GetText write SetText;
2565         property Parent: ITokenRewriteStream read GetParent write SetParent;
2566       end;
2567 
2568       TRewriteOperation = class(TANTLRObject, IRewriteOperation)
2569       strict private
2570         // What index into rewrites List are we?
2571         FInstructionIndex: Integer;
2572         // Token buffer index
2573         FIndex: Integer;
2574         FText: IANTLRInterface;
2575         FParent: Pointer; {ITokenRewriteStream;}
2576       protected
2577         { IRewriteOperation }
GetInstructionIndex()2578         function GetInstructionIndex: Integer;
2579         procedure SetInstructionIndex(const Value: Integer);
GetIndex()2580         function GetIndex: Integer;
2581         procedure SetIndex(const Value: Integer);
GetText()2582         function GetText: IANTLRInterface;
2583         procedure SetText(const Value: IANTLRInterface);
GetParent()2584         function GetParent: ITokenRewriteStream;
2585         procedure SetParent(const Value: ITokenRewriteStream);
2586 
Execute(const Buf: TStringBuilder)2587         function Execute(const Buf: TStringBuilder): Integer; virtual;
2588       protected
2589         constructor Create(const AIndex: Integer; const AText: IANTLRInterface;
2590           const AParent: ITokenRewriteStream);
2591 
2592         property Index: Integer read FIndex write FIndex;
2593         property Text: IANTLRInterface read FText write FText;
2594         property Parent: ITokenRewriteStream read GetParent write SetParent;
2595       public
ToString()2596         function ToString: String; override;
2597       end;
2598 
2599       IInsertBeforeOp = interface(IRewriteOperation)
2600       ['{BFB732E2-BE6A-4691-AE3B-5C8013DE924E}']
2601       end;
2602 
2603       TInsertBeforeOp = class(TRewriteOperation, IInsertBeforeOp)
2604       protected
2605         { IRewriteOperation }
Execute(const Buf: TStringBuilder)2606         function Execute(const Buf: TStringBuilder): Integer; override;
2607       end;
2608 
2609       /// <summary>I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp
2610       /// instructions.
2611       /// </summary>
2612       IReplaceOp = interface(IRewriteOperation)
2613       ['{630C434A-99EA-4589-A65D-64A7B3DAC407}']
2614         { Property accessors }
GetLastIndex()2615         function GetLastIndex: Integer;
2616         procedure SetLastIndex(const Value: Integer);
2617 
2618         { Properties }
2619         property LastIndex: Integer read GetLastIndex write SetLastIndex;
2620       end;
2621 
2622       TReplaceOp = class(TRewriteOperation, IReplaceOp)
2623       private
2624         FLastIndex: Integer;
2625       protected
2626         { IRewriteOperation }
Execute(const Buf: TStringBuilder)2627         function Execute(const Buf: TStringBuilder): Integer; override;
2628       protected
2629         { IReplaceOp }
GetLastIndex()2630         function GetLastIndex: Integer;
2631         procedure SetLastIndex(const Value: Integer);
2632       public
2633         constructor Create(const AStart, AStop: Integer;
2634           const AText: IANTLRInterface; const AParent: ITokenRewriteStream);
2635 
ToString()2636         function ToString: String; override;
2637       end;
2638 
2639       IDeleteOp = interface(IRewriteOperation)
2640       ['{C39345BC-F170-4C3A-A989-65E6B9F0712B}']
2641       end;
2642 
2643       TDeleteOp = class(TReplaceOp)
2644       public
ToString()2645         function ToString: String; override;
2646       end;
2647   strict private
2648     type
2649       TRewriteOpComparer<T: IRewriteOperation> = class(TComparer<T>)
2650       public
Compare(const Left, Right: T)2651         function Compare(const Left, Right: T): Integer; override;
2652       end;
2653   strict private
2654     /// <summary>You may have multiple, named streams of rewrite operations.
2655     /// I'm calling these things "programs."
2656     /// Maps String (name) -> rewrite (IList)
2657     /// </summary>
2658     FPrograms: IDictionary<String, IList<IRewriteOperation>>;
2659 
2660     /// <summary>Map String (program name) -> Integer index </summary>
2661     FLastRewriteTokenIndexes: IDictionary<String, Integer>;
2662   strict private
InitializeProgram(const Name: String)2663     function InitializeProgram(const Name: String): IList<IRewriteOperation>;
2664   protected
2665     { ITokenRewriteStream }
2666     procedure Rollback(const InstructionIndex: Integer); overload; virtual;
2667     procedure Rollback(const ProgramName: String;
2668       const InstructionIndex: Integer); overload; virtual;
2669 
2670     procedure DeleteProgram; overload; virtual;
2671     procedure DeleteProgram(const ProgramName: String); overload; virtual;
2672 
2673     procedure InsertAfter(const T: IToken; const Text: IANTLRInterface); overload; virtual;
2674     procedure InsertAfter(const Index: Integer; const Text: IANTLRInterface); overload; virtual;
2675     procedure InsertAfter(const ProgramName: String; const T: IToken;
2676       const Text: IANTLRInterface); overload; virtual;
2677     procedure InsertAfter(const ProgramName: String; const Index: Integer;
2678       const Text: IANTLRInterface); overload; virtual;
2679     procedure InsertAfter(const T: IToken; const Text: String); overload;
2680     procedure InsertAfter(const Index: Integer; const Text: String); overload;
2681     procedure InsertAfter(const ProgramName: String; const T: IToken;
2682       const Text: String); overload;
2683     procedure InsertAfter(const ProgramName: String; const Index: Integer;
2684       const Text: String); overload;
2685 
2686     procedure InsertBefore(const T: IToken; const Text: IANTLRInterface); overload; virtual;
2687     procedure InsertBefore(const Index: Integer; const Text: IANTLRInterface); overload; virtual;
2688     procedure InsertBefore(const ProgramName: String; const T: IToken;
2689       const Text: IANTLRInterface); overload; virtual;
2690     procedure InsertBefore(const ProgramName: String; const Index: Integer;
2691       const Text: IANTLRInterface); overload; virtual;
2692     procedure InsertBefore(const T: IToken; const Text: String); overload;
2693     procedure InsertBefore(const Index: Integer; const Text: String); overload;
2694     procedure InsertBefore(const ProgramName: String; const T: IToken;
2695       const Text: String); overload;
2696     procedure InsertBefore(const ProgramName: String; const Index: Integer;
2697       const Text: String); overload;
2698 
2699     procedure Replace(const Index: Integer; const Text: IANTLRInterface); overload; virtual;
2700     procedure Replace(const Start, Stop: Integer; const Text: IANTLRInterface); overload; virtual;
2701     procedure Replace(const IndexT: IToken; const Text: IANTLRInterface); overload; virtual;
2702     procedure Replace(const Start, Stop: IToken; const Text: IANTLRInterface); overload; virtual;
2703     procedure Replace(const ProgramName: String; const Start, Stop: Integer;
2704       const Text: IANTLRInterface); overload; virtual;
2705     procedure Replace(const ProgramName: String; const Start, Stop: IToken;
2706       const Text: IANTLRInterface); overload; virtual;
2707     procedure Replace(const Index: Integer; const Text: String); overload;
2708     procedure Replace(const Start, Stop: Integer; const Text: String); overload;
2709     procedure Replace(const IndexT: IToken; const Text: String); overload;
2710     procedure Replace(const Start, Stop: IToken; const Text: String); overload;
2711     procedure Replace(const ProgramName: String; const Start, Stop: Integer;
2712       const Text: String); overload;
2713     procedure Replace(const ProgramName: String; const Start, Stop: IToken;
2714       const Text: String); overload;
2715 
2716     procedure Delete(const Index: Integer); overload; virtual;
2717     procedure Delete(const Start, Stop: Integer); overload; virtual;
2718     procedure Delete(const IndexT: IToken); overload; virtual;
2719     procedure Delete(const Start, Stop: IToken); overload; virtual;
2720     procedure Delete(const ProgramName: String; const Start, Stop: Integer); overload; virtual;
2721     procedure Delete(const ProgramName: String; const Start, Stop: IToken); overload; virtual;
2722 
GetLastRewriteTokenIndex()2723     function GetLastRewriteTokenIndex: Integer; overload; virtual;
2724 
ToOriginalString()2725     function ToOriginalString: String; overload; virtual;
ToOriginalString(const Start, Stop: Integer)2726     function ToOriginalString(const Start, Stop: Integer): String; overload; virtual;
2727 
ToString(const ProgramName: String)2728     function ToString(const ProgramName: String): String; overload; virtual;
ToString(const ProgramName: String;2729     function ToString(const ProgramName: String;
2730       const Start, Stop: Integer): String; overload; virtual;
2731 
ToDebugString()2732     function ToDebugString: String; overload; virtual;
ToDebugString(const Start, Stop: Integer)2733     function ToDebugString(const Start, Stop: Integer): String; overload; virtual;
2734   protected
2735     { ITokenStream }
ToString(const Start, Stop: Integer)2736     function ToString(const Start, Stop: Integer): String; overload; override;
2737   strict protected
2738     procedure Init; virtual;
GetProgram(const Name: String)2739     function GetProgram(const Name: String): IList<IRewriteOperation>; virtual;
GetLastRewriteTokenIndex(const ProgramName: String)2740     function GetLastRewriteTokenIndex(const ProgramName: String): Integer; overload; virtual;
2741     procedure SetLastRewriteTokenIndex(const ProgramName: String; const I: Integer); overload; virtual;
2742 
2743     /// <summary>
2744     /// Return a map from token index to operation.
2745     /// </summary>
2746     /// <remarks>We need to combine operations and report invalid operations (like
2747     /// overlapping replaces that are not completed nested).  Inserts to
2748     /// same index need to be combined etc...   Here are the cases:
2749     ///
2750     /// I.i.u I.j.v               leave alone, nonoverlapping
2751     /// I.i.u I.i.v               combine: Iivu
2752     ///
2753     /// R.i-j.u R.x-y.v | i-j in x-y      delete first R
2754     /// R.i-j.u R.i-j.v             delete first R
2755     /// R.i-j.u R.x-y.v | x-y in i-j      ERROR
2756     /// R.i-j.u R.x-y.v | boundaries overlap  ERROR
2757     ///
2758     /// I.i.u R.x-y.v | i in x-y        delete I
2759     /// I.i.u R.x-y.v | i not in x-y      leave alone, nonoverlapping
2760     /// R.x-y.v I.i.u | i in x-y        ERROR
2761     /// R.x-y.v I.x.u               R.x-y.uv (combine, delete I)
2762     /// R.x-y.v I.i.u | i not in x-y      leave alone, nonoverlapping
2763     ///
2764     /// I.i.u = insert u before op @ index i
2765     /// R.x-y.u = replace x-y indexed tokens with u
2766     ///
2767     /// First we need to examine replaces.  For any replace op:
2768     ///
2769     ///   1. wipe out any insertions before op within that range.
2770     ///   2. Drop any replace op before that is contained completely within
2771     ///        that range.
2772     ///   3. Throw exception upon boundary overlap with any previous replace.
2773     ///
2774     /// Then we can deal with inserts:
2775     ///
2776     ///   1. for any inserts to same index, combine even if not adjacent.
2777     ///   2. for any prior replace with same left boundary, combine this
2778     ///        insert with replace and delete this replace.
2779     ///   3. throw exception if index in same range as previous replace
2780     ///
2781     /// Don't actually delete; make op null in list. Easier to walk list.
2782     /// Later we can throw as we add to index -> op map.
2783     ///
2784     /// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
2785     /// inserted stuff would be before the replace range.  But, if you
2786     /// add tokens in front of a method body '{' and then delete the method
2787     /// body, I think the stuff before the '{' you added should disappear too.
2788     /// </remarks>
ReduceToSingleOperationPerIndex(2789     function ReduceToSingleOperationPerIndex(
2790       const Rewrites: IList<IRewriteOperation>): IDictionary<Integer, IRewriteOperation>;
2791 
GetKindOfOps(const Rewrites: IList<IRewriteOperation>;2792     function GetKindOfOps(const Rewrites: IList<IRewriteOperation>;
2793       const Kind: TGUID): IList<IRewriteOperation>; overload;
2794     /// <summary>
2795     /// Get all operations before an index of a particular kind
2796     /// </summary>
GetKindOfOps(const Rewrites: IList<IRewriteOperation>;2797     function GetKindOfOps(const Rewrites: IList<IRewriteOperation>;
2798       const Kind: TGUID; const Before: Integer): IList<IRewriteOperation>; overload;
2799 
CatOpText(const A, B: IANTLRInterface)2800     function CatOpText(const A, B: IANTLRInterface): IANTLRInterface;
2801   public
2802     constructor Create; overload;
2803     constructor Create(const ATokenSource: ITokenSource); overload;
2804     constructor Create(const ATokenSource: ITokenSource;
2805       const AChannel: Integer); overload;
2806     constructor Create(const ALexer: ILexer); overload;
2807     constructor Create(const ALexer: ILexer;
2808       const AChannel: Integer); overload;
2809 
ToString()2810     function ToString: String; overload; override;
2811   end;
2812 
2813 { These functions return X or, if X = nil, an empty default instance }
Def(const X: IToken)2814 function Def(const X: IToken): IToken; overload;
Def(const X: IRuleReturnScope)2815 function Def(const X: IRuleReturnScope): IRuleReturnScope; overload;
2816 
2817 implementation
2818 
2819 uses
2820   StrUtils,
2821   Math,
2822   Antlr.Runtime.Tree;
2823 
2824 { ERecognitionException }
2825 
2826 constructor ERecognitionException.Create;
2827 begin
2828   Create('', nil);
2829 end;
2830 
2831 constructor ERecognitionException.Create(const AMessage: String);
2832 begin
2833   Create(AMessage, nil);
2834 end;
2835 
2836 constructor ERecognitionException.Create(const AInput: IIntStream);
2837 begin
2838   Create('', AInput);
2839 end;
2840 
2841 constructor ERecognitionException.Create(const AMessage: String;
2842   const AInput: IIntStream);
2843 var
2844   TokenStream: ITokenStream;
2845   CharStream: ICharStream;
2846 begin
2847   inherited Create(AMessage);
2848   FInput := AInput;
2849   FIndex := AInput.Index;
2850 
2851   if Supports(AInput, ITokenStream, TokenStream) then
2852   begin
2853     FToken := TokenStream.LT(1);
2854     FLine := FToken.Line;
2855     FCharPositionInLine := FToken.CharPositionInLine;
2856   end;
2857 
2858   if Supports(AInput, ITreeNodeStream) then
2859     ExtractInformationFromTreeNodeStream(AInput)
2860   else
2861   begin
2862     if Supports(AInput, ICharStream, CharStream) then
2863     begin
2864       FC := AInput.LA(1);
2865       FLine := CharStream.Line;
2866       FCharPositionInLine := CharStream.CharPositionInLine;
2867     end
2868     else
2869       FC := AInput.LA(1);
2870   end;
2871 end;
2872 
2873 procedure ERecognitionException.ExtractInformationFromTreeNodeStream(
2874   const Input: IIntStream);
2875 var
2876   Nodes: ITreeNodeStream;
2877   Adaptor: ITreeAdaptor;
2878   Payload, PriorPayload: IToken;
2879   I, NodeType: Integer;
2880   PriorNode: IANTLRInterface;
2881   Tree: ITree;
2882   Text: String;
2883   CommonTree: ICommonTree;
2884 begin
2885   Nodes := Input as ITreeNodeStream;
2886   FNode := Nodes.LT(1);
2887   Adaptor := Nodes.TreeAdaptor;
2888   Payload := Adaptor.GetToken(FNode);
2889 
2890   if Assigned(Payload) then
2891   begin
2892     FToken := Payload;
2893     if (Payload.Line <= 0) then
2894     begin
2895       // imaginary node; no line/pos info; scan backwards
2896       I := -1;
2897       PriorNode := Nodes.LT(I);
2898       while Assigned(PriorNode) do
2899       begin
2900         PriorPayload := Adaptor.GetToken(PriorNode);
2901         if Assigned(PriorPayload) and (PriorPayload.Line > 0) then
2902         begin
2903           // we found the most recent real line / pos info
2904           FLine := PriorPayload.Line;
2905           FCharPositionInLine := PriorPayload.CharPositionInLine;
2906           FApproximateLineInfo := True;
2907           Break;
2908         end;
2909         Dec(I);
2910         PriorNode := Nodes.LT(I)
2911       end;
2912     end
2913     else
2914     begin
2915       // node created from real token
2916       FLine := Payload.Line;
2917       FCharPositionInLine := Payload.CharPositionInLine;
2918     end;
2919   end else
2920     if Supports(FNode, ITree, Tree) then
2921     begin
2922       FLine := Tree.Line;
2923       FCharPositionInLine := Tree.CharPositionInLine;
2924       if Supports(FNode, ICommonTree, CommonTree) then
2925         FToken := CommonTree.Token;
2926     end
2927     else
2928     begin
2929       NodeType := Adaptor.GetNodeType(FNode);
2930       Text := Adaptor.GetNodeText(FNode);
2931       FToken := TCommonToken.Create(NodeType, Text);
2932     end;
2933 end;
2934 
ERecognitionException.GetUnexpectedType()2935 function ERecognitionException.GetUnexpectedType: Integer;
2936 var
2937   Nodes: ITreeNodeStream;
2938   Adaptor: ITreeAdaptor;
2939 begin
2940   if Supports(FInput, ITokenStream) then
2941     Result := FToken.TokenType
2942   else
2943     if Supports(FInput, ITreeNodeStream, Nodes) then
2944     begin
2945       Adaptor := Nodes.TreeAdaptor;
2946       Result := Adaptor.GetNodeType(FNode);
2947     end else
2948       Result := FC;
2949 end;
2950 
2951 { EMismatchedTokenException }
2952 
2953 constructor EMismatchedTokenException.Create(const AExpecting: Integer;
2954   const AInput: IIntStream);
2955 begin
2956   inherited Create(AInput);
2957   FExpecting := AExpecting;
2958 end;
2959 
EMismatchedTokenException.ToString()2960 function EMismatchedTokenException.ToString: String;
2961 begin
2962   Result := 'MismatchedTokenException(' + IntToStr(UnexpectedType)
2963     + '!=' + IntToStr(Expecting) + ')';
2964 
2965 end;
2966 
2967 { EUnwantedTokenException }
2968 
EUnwantedTokenException.GetUnexpectedToken()2969 function EUnwantedTokenException.GetUnexpectedToken: IToken;
2970 begin
2971   Result := FToken;
2972 end;
2973 
EUnwantedTokenException.ToString()2974 function EUnwantedTokenException.ToString: String;
2975 var
2976   Exp: String;
2977 begin
2978   if (Expecting = TToken.INVALID_TOKEN_TYPE) then
2979     Exp := ''
2980   else
2981     Exp := ', expected ' + IntToStr(Expecting);
2982   if (Token = nil) then
2983     Result := 'UnwantedTokenException(found=nil' + Exp + ')'
2984   else
2985     Result := 'UnwantedTokenException(found=' + Token.Text + Exp + ')'
2986 end;
2987 
2988 { EMissingTokenException }
2989 
2990 constructor EMissingTokenException.Create(const AExpecting: Integer;
2991   const AInput: IIntStream; const AInserted: IANTLRInterface);
2992 begin
2993   inherited Create(AExpecting, AInput);
2994   FInserted := AInserted;
2995 end;
2996 
EMissingTokenException.GetMissingType()2997 function EMissingTokenException.GetMissingType: Integer;
2998 begin
2999   Result := Expecting;
3000 end;
3001 
EMissingTokenException.ToString()3002 function EMissingTokenException.ToString: String;
3003 begin
3004   if Assigned(FInserted) and Assigned(FToken) then
3005     Result := 'MissingTokenException(inserted ' + FInserted.ToString
3006       + ' at ' + FToken.Text + ')'
3007   else
3008     if Assigned(FToken) then
3009       Result := 'MissingTokenException(at ' + FToken.Text + ')'
3010     else
3011       Result := 'MissingTokenException';
3012 end;
3013 
3014 { EMismatchedTreeNodeException }
3015 
3016 constructor EMismatchedTreeNodeException.Create(const AExpecting: Integer;
3017   const AInput: IIntStream);
3018 begin
3019   inherited Create(AInput);
3020   FExpecting := AExpecting;
3021 end;
3022 
EMismatchedTreeNodeException.ToString()3023 function EMismatchedTreeNodeException.ToString: String;
3024 begin
3025   Result := 'MismatchedTreeNodeException(' + IntToStr(UnexpectedType)
3026     + '!=' + IntToStr(Expecting) + ')';
3027 end;
3028 
3029 { ENoViableAltException }
3030 
3031 constructor ENoViableAltException.Create(
3032   const AGrammarDecisionDescription: String; const ADecisionNumber,
3033   AStateNumber: Integer; const AInput: IIntStream);
3034 begin
3035   inherited Create(AInput);
3036   FGrammarDecisionDescription := AGrammarDecisionDescription;
3037   FDecisionNumber := ADecisionNumber;
3038   FStateNumber := AStateNumber;
3039 end;
3040 
ENoViableAltException.ToString()3041 function ENoViableAltException.ToString: String;
3042 begin
3043   if Supports(Input, ICharStream) then
3044     Result := 'NoViableAltException(''' + Char(UnexpectedType) + '''@['
3045       + FGrammarDecisionDescription + '])'
3046   else
3047     Result := 'NoViableAltException(''' + IntToStr(UnexpectedType) + '''@['
3048       + FGrammarDecisionDescription + '])'
3049 end;
3050 
3051 { EEarlyExitException }
3052 
3053 constructor EEarlyExitException.Create(const ADecisionNumber: Integer;
3054   const AInput: IIntStream);
3055 begin
3056   inherited Create(AInput);
3057   FDecisionNumber := ADecisionNumber;
3058 end;
3059 
3060 { EMismatchedSetException }
3061 
3062 constructor EMismatchedSetException.Create(const AExpecting: IBitSet;
3063   const AInput: IIntStream);
3064 begin
3065   inherited Create(AInput);
3066   FExpecting := AExpecting;
3067 end;
3068 
EMismatchedSetException.ToString()3069 function EMismatchedSetException.ToString: String;
3070 begin
3071   Result := 'MismatchedSetException(' + IntToStr(UnexpectedType)
3072     + '!=' + Expecting.ToString + ')';
3073 end;
3074 
3075 { EMismatchedNotSetException }
3076 
EMismatchedNotSetException.ToString()3077 function EMismatchedNotSetException.ToString: String;
3078 begin
3079   Result := 'MismatchedNotSetException(' + IntToStr(UnexpectedType)
3080     + '!=' + Expecting.ToString + ')';
3081 end;
3082 
3083 { EFailedPredicateException }
3084 
3085 constructor EFailedPredicateException.Create(const AInput: IIntStream;
3086   const ARuleName, APredicateText: String);
3087 begin
3088   inherited Create(AInput);
3089   FRuleName := ARuleName;
3090   FPredicateText := APredicateText;
3091 end;
3092 
EFailedPredicateException.ToString()3093 function EFailedPredicateException.ToString: String;
3094 begin
3095   Result := 'FailedPredicateException(' + FRuleName + ',{' + FPredicateText + '}?)';
3096 end;
3097 
3098 { EMismatchedRangeException }
3099 
3100 constructor EMismatchedRangeException.Create(const AA, AB: Integer;
3101   const AInput: IIntStream);
3102 begin
3103   inherited Create(FInput);
3104   FA := AA;
3105   FB := AB;
3106 end;
3107 
EMismatchedRangeException.ToString()3108 function EMismatchedRangeException.ToString: String;
3109 begin
3110   Result := 'MismatchedNotSetException(' + IntToStr(UnexpectedType)
3111     + ' not in [' + IntToStr(FA)+ ',' + IntToStr(FB) + '])';
3112 end;
3113 
3114 { TCharStreamState }
3115 
GetCharPositionInLinenull3116 function TCharStreamState.GetCharPositionInLine: Integer;
3117 begin
3118   Result := FCharPositionInLine;
3119 end;
3120 
GetLinenull3121 function TCharStreamState.GetLine: Integer;
3122 begin
3123   Result := FLine;
3124 end;
3125 
TCharStreamState.GetP()3126 function TCharStreamState.GetP: Integer;
3127 begin
3128   Result := FP;
3129 end;
3130 
3131 procedure TCharStreamState.SetCharPositionInLine(const Value: Integer);
3132 begin
3133   FCharPositionInLine := Value;
3134 end;
3135 
3136 procedure TCharStreamState.SetLine(const Value: Integer);
3137 begin
3138   FLine := Value;
3139 end;
3140 
3141 procedure TCharStreamState.SetP(const Value: Integer);
3142 begin
3143   FP := Value;
3144 end;
3145 
3146 { TANTLRStringStream }
3147 
3148 constructor TANTLRStringStream.Create(const AInput: String);
3149 begin
3150   inherited Create;
3151   FLine := 1;
3152   FOwnsData := True;
3153   FN := Length(AInput);
3154   if (FN > 0) then
3155   begin
3156     GetMem(FData,FN * SizeOf(Char));
3157     Move(AInput[1],FData^,FN * SizeOf(Char));
3158   end;
3159 end;
3160 
3161 procedure TANTLRStringStream.Consume;
3162 begin
3163   if (FP < FN) then
3164   begin
3165     Inc(FCharPositionInLine);
3166     if (FData[FP] = #10) then
3167     begin
3168       Inc(FLine);
3169       FCharPositionInLine := 0;
3170     end;
3171     Inc(FP);
3172   end;
3173 end;
3174 
3175 constructor TANTLRStringStream.Create(const AData: PChar;
3176   const ANumberOfActualCharsInArray: Integer);
3177 begin
3178   inherited Create;
3179   FLine := 1;
3180   FOwnsData := False;
3181   FData := AData;
3182   FN := ANumberOfActualCharsInArray;
3183 end;
3184 
3185 constructor TANTLRStringStream.Create;
3186 begin
3187   inherited Create;
3188   FLine := 1;
3189 end;
3190 
3191 destructor TANTLRStringStream.Destroy;
3192 begin
3193   if (FOwnsData) then
3194     FreeMem(FData);
3195   inherited;
3196 end;
3197 
TANTLRStringStream.GetCharPositionInLine()3198 function TANTLRStringStream.GetCharPositionInLine: Integer;
3199 begin
3200   Result := FCharPositionInLine;
3201 end;
3202 
GetLinenull3203 function TANTLRStringStream.GetLine: Integer;
3204 begin
3205   Result := FLine;
3206 end;
3207 
GetSourceNamenull3208 function TANTLRStringStream.GetSourceName: String;
3209 begin
3210   Result := FName;
3211 end;
3212 
Indexnull3213 function TANTLRStringStream.Index: Integer;
3214 begin
3215   Result := FP;
3216 end;
3217 
LAnull3218 function TANTLRStringStream.LA(I: Integer): Integer;
3219 begin
3220   if (I = 0) then
3221     Result := 0 // undefined
3222   else begin
3223     if (I < 0) then
3224     begin
3225       Inc(I); // e.g., translate LA(-1) to use offset i=0; then data[p+0-1]
3226       if ((FP + I - 1) < 0) then
3227       begin
3228         Result := Integer(cscEOF);
3229         Exit;
3230       end;
3231     end;
3232 
3233     if ((FP + I - 1) >= FN) then
3234       Result := Integer(cscEOF)
3235     else
3236       Result := Integer(FData[FP + I - 1]);
3237   end;
3238 end;
3239 
TANTLRStringStream.LAChar(I: Integer)3240 function TANTLRStringStream.LAChar(I: Integer): Char;
3241 begin
3242   Result := Char(LA(I));
3243 end;
3244 
LTnull3245 function TANTLRStringStream.LT(const I: Integer): Integer;
3246 begin
3247   Result := LA(I);
3248 end;
3249 
TANTLRStringStream.Mark()3250 function TANTLRStringStream.Mark: Integer;
3251 var
3252   State: ICharStreamState;
3253 begin
3254   if (FMarkers = nil) then
3255   begin
3256     FMarkers := TList<ICharStreamState>.Create;
3257     FMarkers.Add(nil);  // depth 0 means no backtracking, leave blank
3258   end;
3259 
3260   Inc(FMarkDepth);
3261   if (FMarkDepth >= FMarkers.Count) then
3262   begin
3263     State := TCharStreamState.Create;
3264     FMarkers.Add(State);
3265   end
3266   else
3267     State := FMarkers[FMarkDepth];
3268 
3269   State.P := FP;
3270   State.Line := FLine;
3271   State.CharPositionInLine := FCharPositionInLine;
3272   FLastMarker := FMarkDepth;
3273   Result := FMarkDepth;
3274 end;
3275 
3276 procedure TANTLRStringStream.Release(const Marker: Integer);
3277 begin
3278   // unwind any other markers made after m and release m
3279   FMarkDepth := Marker;
3280   // release this marker
3281   Dec(FMarkDepth);
3282 end;
3283 
3284 procedure TANTLRStringStream.Reset;
3285 begin
3286   FP := 0;
3287   FLine := 1;
3288   FCharPositionInLine := 0;
3289   FMarkDepth := 0;
3290 end;
3291 
3292 procedure TANTLRStringStream.Rewind(const Marker: Integer);
3293 var
3294   State: ICharStreamState;
3295 begin
3296   State := FMarkers[Marker];
3297   // restore stream state
3298   Seek(State.P);
3299   FLine := State.Line;
3300   FCharPositionInLine := State.CharPositionInLine;
3301   Release(Marker);
3302 end;
3303 
3304 procedure TANTLRStringStream.Rewind;
3305 begin
3306   Rewind(FLastMarker);
3307 end;
3308 
3309 procedure TANTLRStringStream.Seek(const Index: Integer);
3310 begin
3311   if (Index <= FP) then
3312     FP := Index // just jump; don't update stream state (line, ...)
3313   else begin
3314     // seek forward, consume until p hits index
3315     while (FP < Index) do
3316       Consume;
3317   end;
3318 end;
3319 
3320 procedure TANTLRStringStream.SetCharPositionInLine(const Value: Integer);
3321 begin
3322   FCharPositionInLine := Value;
3323 end;
3324 
3325 procedure TANTLRStringStream.SetLine(const Value: Integer);
3326 begin
3327   FLine := Value;
3328 end;
3329 
TANTLRStringStream.Size()3330 function TANTLRStringStream.Size: Integer;
3331 begin
3332   Result := FN;
3333 end;
3334 
Substringnull3335 function TANTLRStringStream.Substring(const Start, Stop: Integer): String;
3336 begin
3337   Result := Copy(FData, Start + 1, Stop - Start + 1);
3338 end;
3339 
3340 { TANTLRFileStream }
3341 
3342 constructor TANTLRFileStream.Create(const AFileName: String);
3343 begin
3344   Create(AFilename,TEncoding.Default);
3345 end;
3346 
3347 constructor TANTLRFileStream.Create(const AFileName: String;
3348   const AEncoding: TEncoding);
3349 begin
3350   inherited Create;
3351   FFileName := AFileName;
3352   Load(FFileName, AEncoding);
3353 end;
3354 
GetSourceNamenull3355 function TANTLRFileStream.GetSourceName: String;
3356 begin
3357   Result := FFileName;
3358 end;
3359 
3360 procedure TANTLRFileStream.Load(const FileName: String;
3361   const Encoding: TEncoding);
3362 var
3363   FR: TStreamReader;
3364   S: String;
3365 begin
3366   if (FFileName <> '') then
3367   begin
3368     if (Encoding = nil) then
3369       FR := TStreamReader.Create(FileName,TEncoding.Default)
3370     else
3371       FR := TStreamReader.Create(FileName,Encoding);
3372 
3373     try
3374       if (FOwnsData) then
3375       begin
3376         FreeMem(FData);
3377         FData := nil;
3378       end;
3379 
3380       FOwnsData := True;
3381       S := FR.ReadToEnd;
3382       FN := Length(S);
3383       if (FN > 0) then
3384       begin
3385         GetMem(FData,FN * SizeOf(Char));
3386         Move(S[1],FData^,FN * SizeOf(Char));
3387       end;
3388     finally
3389       FR.Free;
3390     end;
3391   end;
3392 end;
3393 
3394 { TBitSet }
3395 
TBitSet.BitSetOf(const El: Integer)3396 class function TBitSet.BitSetOf(const El: Integer): IBitSet;
3397 begin
3398   Result := TBitSet.Create(El + 1);
3399   Result.Add(El);
3400 end;
3401 
TBitSet.BitSetOf(const A, B: Integer)3402 class function TBitSet.BitSetOf(const A, B: Integer): IBitSet;
3403 begin
3404   Result := TBitSet.Create(Max(A,B) + 1);
3405   Result.Add(A);
3406   Result.Add(B);
3407 end;
3408 
TBitSet.BitSetOf(const A, B, C: Integer)3409 class function TBitSet.BitSetOf(const A, B, C: Integer): IBitSet;
3410 begin
3411   Result := TBitSet.Create;
3412   Result.Add(A);
3413   Result.Add(B);
3414   Result.Add(C);
3415 end;
3416 
TBitSet.BitSetOf(const A, B, C, D: Integer)3417 class function TBitSet.BitSetOf(const A, B, C, D: Integer): IBitSet;
3418 begin
3419   Result := TBitSet.Create;
3420   Result.Add(A);
3421   Result.Add(B);
3422   Result.Add(C);
3423   Result.Add(D);
3424 end;
3425 
3426 procedure TBitSet.Add(const El: Integer);
3427 var
3428   N: Integer;
3429 begin
3430   N := WordNumber(El);
3431   if (N >= Length(FBits)) then
3432     GrowToInclude(El);
3433   FBits[N] := FBits[N] or BitMask(El);
3434 end;
3435 
TBitSet.BitMask(const BitNumber: Integer)3436 class function TBitSet.BitMask(const BitNumber: Integer): UInt64;
3437 var
3438   BitPosition: Integer;
3439 begin
3440   BitPosition := BitNumber and MOD_MASK;
3441   Result := UInt64(1) shl BitPosition;
3442 end;
3443 
BitSetOrnull3444 function TBitSet.BitSetOr(const A: IBitSet): IBitSet;
3445 begin
3446   Result := Clone as IBitSet;
3447   Result.OrInPlace(A);
3448 end;
3449 
TBitSet.Clone()3450 function TBitSet.Clone: IANTLRInterface;
3451 var
3452   BS: TBitSet;
3453 begin
3454   BS := TBitSet.Create;
3455   Result := BS;
3456   SetLength(BS.FBits,Length(FBits));
3457   if (Length(FBits) > 0) then
3458     Move(FBits[0],BS.FBits[0],Length(FBits) * SizeOf(UInt64));
3459 end;
3460 
3461 constructor TBitSet.Create;
3462 begin
3463   Create(BITS);
3464 end;
3465 
3466 constructor TBitSet.Create(const ABits: array of UInt64);
3467 begin
3468   inherited Create;
3469   SetLength(FBits, Length(ABits));
3470   if (Length(ABits) > 0) then
3471     Move(ABits[0], FBits[0], Length(ABits) * SizeOf(UInt64));
3472 end;
3473 
3474 constructor TBitSet.Create(const AItems: IList<Integer>);
3475 var
3476   V: Integer;
3477 begin
3478   Create(BITS);
3479   for V in AItems do
3480     Add(V);
3481 end;
3482 
3483 constructor TBitSet.Create(const ANBits: Integer);
3484 begin
3485   inherited Create;
3486   SetLength(FBits,((ANBits - 1) shr LOG_BITS) + 1);
3487 end;
3488 
Equalsnull3489 function TBitSet.Equals(Obj: TObject): Boolean;
3490 var
3491   OtherSet: TBitSet absolute Obj;
3492   I, N: Integer;
3493 begin
3494   Result := False;
3495   if (Obj = nil) or (not (Obj is TBitSet)) then
3496     Exit;
3497 
3498   N := Min(Length(FBits), Length(OtherSet.FBits));
3499 
3500   // for any bits in common, compare
3501   for I := 0 to N - 1 do
3502   begin
3503     if (FBits[I] <> OtherSet.FBits[I]) then
3504       Exit;
3505   end;
3506 
3507   // make sure any extra bits are off
3508   if (Length(FBits) > N) then
3509   begin
3510     for I := N + 1 to Length(FBits) - 1 do
3511     begin
3512       if (FBits[I] <> 0) then
3513         Exit;
3514     end;
3515   end
3516   else
3517     if (Length(OtherSet.FBits) > N) then
3518     begin
3519       for I := N + 1 to Length(OtherSet.FBits) - 1 do
3520       begin
3521         if (OtherSet.FBits[I] <> 0) then
3522           Exit;
3523       end;
3524     end;
3525 
3526   Result := True;
3527 end;
3528 
GetIsNilnull3529 function TBitSet.GetIsNil: Boolean;
3530 var
3531   I: Integer;
3532 begin
3533   for I := Length(FBits) - 1 downto 0 do
3534     if (FBits[I] <> 0) then
3535     begin
3536       Result := False;
3537       Exit;
3538     end;
3539   Result := True;
3540 end;
3541 
3542 procedure TBitSet.GrowToInclude(const Bit: Integer);
3543 var
3544   NewSize: Integer;
3545 begin
3546   NewSize := Max(Length(FBits) shl 1,NumWordsToHold(Bit));
3547   SetLength(FBits,NewSize);
3548 end;
3549 
TBitSet.LengthInLongWords()3550 function TBitSet.LengthInLongWords: Integer;
3551 begin
3552   Result := Length(FBits);
3553 end;
3554 
TBitSet.Member(const El: Integer)3555 function TBitSet.Member(const El: Integer): Boolean;
3556 var
3557   N: Integer;
3558 begin
3559   if (El < 0) then
3560     Result := False
3561   else
3562   begin
3563     N := WordNumber(El);
3564     if (N >= Length(FBits)) then
3565       Result := False
3566     else
3567       Result := ((FBits[N] and BitMask(El)) <> 0);
3568   end;
3569 end;
3570 
NumBitsnull3571 function TBitSet.NumBits: Integer;
3572 begin
3573   Result := Length(FBits) shl LOG_BITS;
3574 end;
3575 
TBitSet.NumWordsToHold(const El: Integer)3576 class function TBitSet.NumWordsToHold(const El: Integer): Integer;
3577 begin
3578   Result := (El shr LOG_BITS) + 1;
3579 end;
3580 
3581 procedure TBitSet.OrInPlace(const A: IBitSet);
3582 var
3583   I, M: Integer;
3584   ABits: TUInt64Array;
3585 begin
3586   if Assigned(A) then
3587   begin
3588     // If this is smaller than a, grow this first
3589     if (A.LengthInLongWords > Length(FBits)) then
3590       SetLength(FBits,A.LengthInLongWords);
3591     M := Min(Length(FBits), A.LengthInLongWords);
3592     ABits := A.ToPackedArray;
3593     for I := M - 1 downto 0 do
3594       FBits[I] := FBits[I] or ABits[I];
3595   end;
3596 end;
3597 
3598 procedure TBitSet.Remove(const El: Integer);
3599 var
3600   N: Integer;
3601 begin
3602   N := WordNumber(El);
3603   if (N < Length(FBits)) then
3604     FBits[N] := (FBits[N] and not BitMask(El));
3605 end;
3606 
Sizenull3607 function TBitSet.Size: Integer;
3608 var
3609   I, Bit: Integer;
3610   W: UInt64;
3611 begin
3612   Result := 0;
3613   for I := Length(FBits) - 1 downto 0 do
3614   begin
3615     W := FBits[I];
3616     if (W <> 0) then
3617     begin
3618       for Bit := BITS - 1 downto 0 do
3619       begin
3620         if ((W and (UInt64(1) shl Bit)) <> 0) then
3621           Inc(Result);
3622       end;
3623     end;
3624   end;
3625 end;
3626 
ToArraynull3627 function TBitSet.ToArray: TIntegerArray;
3628 var
3629   I, En: Integer;
3630 begin
3631   SetLength(Result,Size);
3632   En := 0;
3633   for I := 0 to (Length(FBits) shl LOG_BITS) - 1 do
3634   begin
3635     if Member(I) then
3636     begin
3637       Result[En] := I;
3638       Inc(En);
3639     end;
3640   end;
3641 end;
3642 
TBitSet.ToPackedArray()3643 function TBitSet.ToPackedArray: TUInt64Array;
3644 begin
3645   Result := FBits;
3646 end;
3647 
TBitSet.ToString()3648 function TBitSet.ToString: String;
3649 begin
3650   Result := ToString(nil);
3651 end;
3652 
TBitSet.ToString(const TokenNames: TStringArray)3653 function TBitSet.ToString(const TokenNames: TStringArray): String;
3654 var
3655   Buf: TStringBuilder;
3656   I: Integer;
3657   HavePrintedAnElement: Boolean;
3658 begin
3659   HavePrintedAnElement := False;
3660   Buf := TStringBuilder.Create;
3661   try
3662     Buf.Append('{');
3663     for I := 0 to (Length(FBits) shl LOG_BITS) - 1 do
3664     begin
3665       if Member(I) then
3666       begin
3667         if (I > 0) and HavePrintedAnElement then
3668           Buf.Append(',');
3669         if Assigned(TokenNames) then
3670           Buf.Append(TokenNames[I])
3671         else
3672           Buf.Append(I);
3673         HavePrintedAnElement := True;
3674       end;
3675     end;
3676     Buf.Append('}');
3677     Result := Buf.ToString;
3678   finally
3679     Buf.Free;
3680   end;
3681 end;
3682 
TBitSet.WordNumber(const Bit: Integer)3683 class function TBitSet.WordNumber(const Bit: Integer): Integer;
3684 begin
3685   Result := Bit shr LOG_BITS; // Bit / BITS
3686 end;
3687 
3688 { TRecognizerSharedState }
3689 
3690 constructor TRecognizerSharedState.Create;
3691 var
3692   I: Integer;
3693 begin
3694   inherited;
3695   SetLength(FFollowing,TBaseRecognizer.INITIAL_FOLLOW_STACK_SIZE);
3696   for I := 0 to TBaseRecognizer.INITIAL_FOLLOW_STACK_SIZE - 1 do
3697     FFollowing[I] := TBitSet.Create;
3698   FFollowingStackPointer := -1;
3699   FLastErrorIndex := -1;
3700   FTokenStartCharIndex := -1;
3701 end;
3702 
TRecognizerSharedState.GetBacktracking()3703 function TRecognizerSharedState.GetBacktracking: Integer;
3704 begin
3705   Result := FBacktracking;
3706 end;
3707 
GetChannelnull3708 function TRecognizerSharedState.GetChannel: Integer;
3709 begin
3710   Result := FChannel;
3711 end;
3712 
GetErrorRecoverynull3713 function TRecognizerSharedState.GetErrorRecovery: Boolean;
3714 begin
3715   Result := FErrorRecovery;
3716 end;
3717 
GetFailednull3718 function TRecognizerSharedState.GetFailed: Boolean;
3719 begin
3720   Result := FFailed;
3721 end;
3722 
TRecognizerSharedState.GetFollowing()3723 function TRecognizerSharedState.GetFollowing: TBitSetArray;
3724 begin
3725   Result := FFollowing;
3726 end;
3727 
GetFollowingStackPointernull3728 function TRecognizerSharedState.GetFollowingStackPointer: Integer;
3729 begin
3730   Result := FFollowingStackPointer;
3731 end;
3732 
TRecognizerSharedState.GetLastErrorIndex()3733 function TRecognizerSharedState.GetLastErrorIndex: Integer;
3734 begin
3735   Result := FLastErrorIndex;
3736 end;
3737 
GetRuleMemonull3738 function TRecognizerSharedState.GetRuleMemo: TDictionaryArray<Integer, Integer>;
3739 begin
3740   Result := FRuleMemo;
3741 end;
3742 
TRecognizerSharedState.GetRuleMemoCount()3743 function TRecognizerSharedState.GetRuleMemoCount: Integer;
3744 begin
3745   Result := Length(FRuleMemo);
3746 end;
3747 
GetSyntaxErrorsnull3748 function TRecognizerSharedState.GetSyntaxErrors: Integer;
3749 begin
3750   Result := FSyntaxErrors;
3751 end;
3752 
GetTextnull3753 function TRecognizerSharedState.GetText: String;
3754 begin
3755   Result := FText;
3756 end;
3757 
TRecognizerSharedState.GetToken()3758 function TRecognizerSharedState.GetToken: IToken;
3759 begin
3760   Result := FToken;
3761 end;
3762 
GetTokenStartCharIndexnull3763 function TRecognizerSharedState.GetTokenStartCharIndex: Integer;
3764 begin
3765   Result := FTokenStartCharIndex;
3766 end;
3767 
GetTokenStartCharPositionInLinenull3768 function TRecognizerSharedState.GetTokenStartCharPositionInLine: Integer;
3769 begin
3770   Result := FTokenStartCharPositionInLine;
3771 end;
3772 
GetTokenStartLinenull3773 function TRecognizerSharedState.GetTokenStartLine: Integer;
3774 begin
3775   Result := FTokenStartLine;
3776 end;
3777 
GetTokenTypenull3778 function TRecognizerSharedState.GetTokenType: Integer;
3779 begin
3780   Result := FTokenType;
3781 end;
3782 
3783 procedure TRecognizerSharedState.SetBacktracking(const Value: Integer);
3784 begin
3785   FBacktracking := Value;
3786 end;
3787 
3788 procedure TRecognizerSharedState.SetChannel(const Value: Integer);
3789 begin
3790   FChannel := Value;
3791 end;
3792 
3793 procedure TRecognizerSharedState.SetErrorRecovery(const Value: Boolean);
3794 begin
3795   FErrorRecovery := Value;
3796 end;
3797 
3798 procedure TRecognizerSharedState.SetFailed(const Value: Boolean);
3799 begin
3800   FFailed := Value;
3801 end;
3802 
3803 procedure TRecognizerSharedState.SetFollowing(const Value: TBitSetArray);
3804 begin
3805   FFollowing := Value;
3806 end;
3807 
3808 procedure TRecognizerSharedState.SetFollowingStackPointer(const Value: Integer);
3809 begin
3810   FFollowingStackPointer := Value;
3811 end;
3812 
3813 procedure TRecognizerSharedState.SetLastErrorIndex(const Value: Integer);
3814 begin
3815   FLastErrorIndex := Value;
3816 end;
3817 
3818 procedure TRecognizerSharedState.SetRuleMemoCount(const Value: Integer);
3819 begin
3820   SetLength(FRuleMemo, Value);
3821 end;
3822 
3823 procedure TRecognizerSharedState.SetSyntaxErrors(const Value: Integer);
3824 begin
3825   FSyntaxErrors := Value;
3826 end;
3827 
3828 procedure TRecognizerSharedState.SetText(const Value: String);
3829 begin
3830   FText := Value;
3831 end;
3832 
3833 procedure TRecognizerSharedState.SetToken(const Value: IToken);
3834 begin
3835   FToken := Value;
3836 end;
3837 
3838 procedure TRecognizerSharedState.SetTokenStartCharIndex(const Value: Integer);
3839 begin
3840   FTokenStartCharIndex := Value;
3841 end;
3842 
3843 procedure TRecognizerSharedState.SetTokenStartCharPositionInLine(
3844   const Value: Integer);
3845 begin
3846   FTokenStartCharPositionInLine := Value;
3847 end;
3848 
3849 procedure TRecognizerSharedState.SetTokenStartLine(const Value: Integer);
3850 begin
3851   FTokenStartLine := Value;
3852 end;
3853 
3854 procedure TRecognizerSharedState.SetTokenType(const Value: Integer);
3855 begin
3856   FTokenType := Value;
3857 end;
3858 
3859 { TCommonToken }
3860 
3861 constructor TCommonToken.Create;
3862 begin
3863   inherited;
3864   FChannel := TToken.DEFAULT_CHANNEL;
3865   FCharPositionInLine := -1;
3866   FIndex := -1;
3867 end;
3868 
3869 constructor TCommonToken.Create(const ATokenType: Integer);
3870 begin
3871   Create;
3872   FTokenType := ATokenType;
3873 end;
3874 
3875 constructor TCommonToken.Create(const AInput: ICharStream; const ATokenType,
3876   AChannel, AStart, AStop: Integer);
3877 begin
3878   Create;
3879   FInput := AInput;
3880   FTokenType := ATokenType;
3881   FChannel := AChannel;
3882   FStart := AStart;
3883   FStop := AStop;
3884 end;
3885 
3886 constructor TCommonToken.Create(const ATokenType: Integer; const AText: String);
3887 begin
3888   Create;
3889   FTokenType := ATokenType;
3890   FChannel := TToken.DEFAULT_CHANNEL;
3891   FText := AText;
3892 end;
3893 
TCommonToken.GetChannel()3894 function TCommonToken.GetChannel: Integer;
3895 begin
3896   Result := FChannel;
3897 end;
3898 
TCommonToken.GetCharPositionInLine()3899 function TCommonToken.GetCharPositionInLine: Integer;
3900 begin
3901   Result := FCharPositionInLine;
3902 end;
3903 
GetInputStreamnull3904 function TCommonToken.GetInputStream: ICharStream;
3905 begin
3906   Result := FInput;
3907 end;
3908 
GetLinenull3909 function TCommonToken.GetLine: Integer;
3910 begin
3911   Result := FLine;
3912 end;
3913 
GetStartIndexnull3914 function TCommonToken.GetStartIndex: Integer;
3915 begin
3916   Result := FStart;
3917 end;
3918 
GetStopIndexnull3919 function TCommonToken.GetStopIndex: Integer;
3920 begin
3921   Result := FStop;
3922 end;
3923 
GetTextnull3924 function TCommonToken.GetText: String;
3925 begin
3926   if (FText <> '') then
3927     Result := FText
3928   else
3929     if (FInput = nil) then
3930       Result := ''
3931     else
3932       Result := FInput.Substring(FStart, FStop);
3933 end;
3934 
GetTokenIndexnull3935 function TCommonToken.GetTokenIndex: Integer;
3936 begin
3937   Result := FIndex;
3938 end;
3939 
TCommonToken.GetTokenType()3940 function TCommonToken.GetTokenType: Integer;
3941 begin
3942   Result := FTokenType;
3943 end;
3944 
3945 procedure TCommonToken.SetChannel(const Value: Integer);
3946 begin
3947   FChannel := Value;
3948 end;
3949 
3950 procedure TCommonToken.SetCharPositionInLine(const Value: Integer);
3951 begin
3952   FCharPositionInLine := Value;
3953 end;
3954 
3955 procedure TCommonToken.SetInputStream(const Value: ICharStream);
3956 begin
3957   FInput := Value;
3958 end;
3959 
3960 procedure TCommonToken.SetLine(const Value: Integer);
3961 begin
3962   FLine := Value;
3963 end;
3964 
3965 procedure TCommonToken.SetStartIndex(const Value: Integer);
3966 begin
3967   FStart := Value;
3968 end;
3969 
3970 procedure TCommonToken.SetStopIndex(const Value: Integer);
3971 begin
3972   FStop := Value;
3973 end;
3974 
3975 procedure TCommonToken.SetText(const Value: String);
3976 begin
3977   (* Override the text for this token.  The property getter
3978    * will return this text rather than pulling from the buffer.
3979    * Note that this does not mean that start/stop indexes are
3980    * not valid.  It means that the input was converted to a new
3981    * string in the token object.
3982    *)
3983   FText := Value;
3984 end;
3985 
3986 procedure TCommonToken.SetTokenIndex(const Value: Integer);
3987 begin
3988   FIndex := Value;
3989 end;
3990 
3991 procedure TCommonToken.SetTokenType(const Value: Integer);
3992 begin
3993   FTokenType := Value;
3994 end;
3995 
ToStringnull3996 function TCommonToken.ToString: String;
3997 var
3998   ChannelStr, Txt: String;
3999 begin
4000   if (FChannel > 0) then
4001     ChannelStr := ',channel=' + IntToStr(FChannel)
4002   else
4003     ChannelStr := '';
4004 
4005   Txt := GetText;
4006   if (Txt <> '') then
4007   begin
4008     Txt := ReplaceStr(Txt,#10,'\n');
4009     Txt := ReplaceStr(Txt,#13,'\r');
4010     Txt := ReplaceStr(Txt,#9,'\t');
4011   end else
4012     Txt := '<no text>';
4013 
4014   Result := Format('[@%d,%d:%d=''%s'',<%d>%s,%d:%d]',
4015     [FIndex,FStart,FStop,Txt,FTokenType,ChannelStr,FLine,FCharPositionInLine]);
4016 end;
4017 
4018 constructor TCommonToken.Create(const AOldToken: IToken);
4019 var
4020   OldCommonToken: ICommonToken;
4021 begin
4022   Create;
4023   FText := AOldToken.Text;
4024   FTokenType := AOldToken.TokenType;
4025   FLine := AOldToken.Line;
4026   FIndex := AOldToken.TokenIndex;
4027   FCharPositionInLine := AOldToken.CharPositionInLine;
4028   FChannel := AOldToken.Channel;
4029   if Supports(AOldToken, ICommonToken, OldCommonToken) then
4030   begin
4031     FStart := OldCommonToken.StartIndex;
4032     FStop := OldCommonToken.StopIndex;
4033   end;
4034 end;
4035 
4036 { TClassicToken }
4037 
4038 constructor TClassicToken.Create(const AOldToken: IToken);
4039 begin
4040   inherited Create;
4041   FText := AOldToken.Text;
4042   FTokenType := AOldToken.TokenType;
4043   FLine := AOldToken.Line;
4044   FCharPositionInLine := AOldToken.CharPositionInLine;
4045   FChannel := AOldToken.Channel;
4046 end;
4047 
4048 constructor TClassicToken.Create(const ATokenType: Integer);
4049 begin
4050   inherited Create;
4051   FTokenType := ATokenType;
4052 end;
4053 
4054 constructor TClassicToken.Create(const ATokenType: Integer; const AText: String;
4055   const AChannel: Integer);
4056 begin
4057   inherited Create;
4058   FTokenType := ATokenType;
4059   FText := AText;
4060   FChannel := AChannel;
4061 end;
4062 
4063 constructor TClassicToken.Create(const ATokenType: Integer;
4064   const AText: String);
4065 begin
4066   inherited Create;
4067   FTokenType := ATokenType;
4068   FText := AText;
4069 end;
4070 
GetChannelnull4071 function TClassicToken.GetChannel: Integer;
4072 begin
4073   Result := FChannel;
4074 end;
4075 
GetCharPositionInLinenull4076 function TClassicToken.GetCharPositionInLine: Integer;
4077 begin
4078   Result := FCharPositionInLine;
4079 end;
4080 
GetInputStreamnull4081 function TClassicToken.GetInputStream: ICharStream;
4082 begin
4083   // No default implementation
4084   Result := nil;
4085 end;
4086 
GetLinenull4087 function TClassicToken.GetLine: Integer;
4088 begin
4089   Result := FLine;
4090 end;
4091 
GetTextnull4092 function TClassicToken.GetText: String;
4093 begin
4094   Result := FText;
4095 end;
4096 
TClassicToken.GetTokenIndex()4097 function TClassicToken.GetTokenIndex: Integer;
4098 begin
4099   Result := FIndex;
4100 end;
4101 
TClassicToken.GetTokenType()4102 function TClassicToken.GetTokenType: Integer;
4103 begin
4104   Result := FTokenType;
4105 end;
4106 
4107 procedure TClassicToken.SetChannel(const Value: Integer);
4108 begin
4109   FChannel := Value;
4110 end;
4111 
4112 procedure TClassicToken.SetCharPositionInLine(const Value: Integer);
4113 begin
4114   FCharPositionInLine := Value;
4115 end;
4116 
4117 procedure TClassicToken.SetInputStream(const Value: ICharStream);
4118 begin
4119   // No default implementation
4120 end;
4121 
4122 procedure TClassicToken.SetLine(const Value: Integer);
4123 begin
4124   FLine := Value;
4125 end;
4126 
4127 procedure TClassicToken.SetText(const Value: String);
4128 begin
4129   FText := Value;
4130 end;
4131 
4132 procedure TClassicToken.SetTokenIndex(const Value: Integer);
4133 begin
4134   FIndex := Value;
4135 end;
4136 
4137 procedure TClassicToken.SetTokenType(const Value: Integer);
4138 begin
4139   FTokenType := Value;
4140 end;
4141 
ToStringnull4142 function TClassicToken.ToString: String;
4143 var
4144   ChannelStr, Txt: String;
4145 begin
4146   if (FChannel > 0) then
4147     ChannelStr := ',channel=' + IntToStr(FChannel)
4148   else
4149     ChannelStr := '';
4150   Txt := FText;
4151   if (Txt <> '') then
4152   begin
4153     Txt := ReplaceStr(Txt,#10,'\n');
4154     Txt := ReplaceStr(Txt,#13,'\r');
4155     Txt := ReplaceStr(Txt,#9,'\t');
4156   end else
4157     Txt := '<no text>';
4158 
4159   Result := Format('[@%d,''%s'',<%d>%s,%d:%d]',
4160     [FIndex,Txt,FTokenType,ChannelStr,FLine,FCharPositionInLine]);
4161 end;
4162 
4163 { TToken }
4164 
4165 class procedure TToken.Initialize;
4166 begin
4167   EOF_TOKEN := TCommonToken.Create(EOF);
4168   INVALID_TOKEN := TCommonToken.Create(INVALID_TOKEN_TYPE);
4169   SKIP_TOKEN := TCommonToken.Create(INVALID_TOKEN_TYPE);
4170 end;
4171 
4172 { TBaseRecognizer }
4173 
4174 constructor TBaseRecognizer.Create;
4175 begin
4176   inherited;
4177   FState := TRecognizerSharedState.Create;
4178 end;
4179 
TBaseRecognizer.AlreadyParsedRule(const Input: IIntStream;4180 function TBaseRecognizer.AlreadyParsedRule(const Input: IIntStream;
4181   const RuleIndex: Integer): Boolean;
4182 var
4183   StopIndex: Integer;
4184 begin
4185   StopIndex := GetRuleMemoization(RuleIndex, Input.Index);
4186   Result := (StopIndex <> MEMO_RULE_UNKNOWN);
4187   if Result then
4188   begin
4189     if (StopIndex = MEMO_RULE_FAILED) then
4190       FState.Failed := True
4191     else
4192       Input.Seek(StopIndex + 1);  // jump to one past stop token
4193   end;
4194 end;
4195 
4196 procedure TBaseRecognizer.BeginBacktrack(const Level: Integer);
4197 begin
4198   // No defeault implementation
4199 end;
4200 
4201 procedure TBaseRecognizer.BeginResync;
4202 begin
4203   // No defeault implementation
4204 end;
4205 
4206 procedure TBaseRecognizer.ConsumeUntil(const Input: IIntStream;
4207   const TokenType: Integer);
4208 var
4209   TType: Integer;
4210 begin
4211   TType := Input.LA(1);
4212   while (TType <> TToken.EOF) and (TType <> TokenType) do
4213   begin
4214     Input.Consume;
4215     TType := Input.LA(1);
4216   end;
4217 end;
4218 
TBaseRecognizer.CombineFollows(const Exact: Boolean)4219 function TBaseRecognizer.CombineFollows(const Exact: Boolean): IBitSet;
4220 var
4221   I, Top: Integer;
4222   LocalFollowSet: IBitSet;
4223 begin
4224   Top := FState.FollowingStackPointer;
4225   Result := TBitSet.Create;
4226   for I := Top downto 0 do
4227   begin
4228     LocalFollowSet := FState.Following[I];
4229     Result.OrInPlace(LocalFollowSet);
4230     if (Exact) then
4231     begin
4232       // can we see end of rule?
4233       if LocalFollowSet.Member(TToken.EOR_TOKEN_TYPE) then
4234       begin
4235         // Only leave EOR in set if at top (start rule); this lets
4236         // us know if have to include follow(start rule); i.e., EOF
4237         if (I > 0) then
4238           Result.Remove(TToken.EOR_TOKEN_TYPE);
4239       end
4240       else
4241         // can't see end of rule, quit
4242         Break;
4243     end;
4244   end;
4245 end;
4246 
ComputeContextSensitiveRuleFOLLOWnull4247 function TBaseRecognizer.ComputeContextSensitiveRuleFOLLOW: IBitSet;
4248 begin
4249   Result := CombineFollows(True);
4250 end;
4251 
TBaseRecognizer.ComputeErrorRecoverySet()4252 function TBaseRecognizer.ComputeErrorRecoverySet: IBitSet;
4253 begin
4254   Result := CombineFollows(False);
4255 end;
4256 
4257 procedure TBaseRecognizer.ConsumeUntil(const Input: IIntStream;
4258   const BitSet: IBitSet);
4259 var
4260   TType: Integer;
4261 begin
4262   TType := Input.LA(1);
4263   while (TType <> TToken.EOF) and (not BitSet.Member(TType)) do
4264   begin
4265     Input.Consume;
4266     TType := Input.LA(1);
4267   end;
4268 end;
4269 
4270 constructor TBaseRecognizer.Create(const AState: IRecognizerSharedState);
4271 begin
4272   if (AState = nil) then
4273     Create
4274   else
4275   begin
4276     inherited Create;
4277     FState := AState;
4278   end;
4279 end;
4280 
4281 procedure TBaseRecognizer.DisplayRecognitionError(
4282   const TokenNames: TStringArray; const E: ERecognitionException);
4283 var
4284   Hdr, Msg: String;
4285 begin
4286   Hdr := GetErrorHeader(E);
4287   Msg := GetErrorMessage(E, TokenNames);
4288   EmitErrorMessage(Hdr + ' ' + Msg);
4289 end;
4290 
4291 procedure TBaseRecognizer.EmitErrorMessage(const Msg: String);
4292 begin
4293   WriteLn(Msg);
4294 end;
4295 
4296 procedure TBaseRecognizer.EndBacktrack(const Level: Integer;
4297   const Successful: Boolean);
4298 begin
4299   // No defeault implementation
4300 end;
4301 
4302 procedure TBaseRecognizer.EndResync;
4303 begin
4304   // No defeault implementation
4305 end;
4306 
GetBacktrackingLevelnull4307 function TBaseRecognizer.GetBacktrackingLevel: Integer;
4308 begin
4309   Result := FState.Backtracking;
4310 end;
4311 
TBaseRecognizer.GetCurrentInputSymbol(4312 function TBaseRecognizer.GetCurrentInputSymbol(
4313   const Input: IIntStream): IANTLRInterface;
4314 begin
4315   // No defeault implementation
4316   Result := nil;
4317 end;
4318 
GetErrorHeadernull4319 function TBaseRecognizer.GetErrorHeader(const E: ERecognitionException): String;
4320 begin
4321   Result := 'line ' + IntToStr(E.Line) + ':' + IntToStr(E.CharPositionInLine);
4322 end;
4323 
TBaseRecognizer.GetErrorMessage(const E: ERecognitionException;4324 function TBaseRecognizer.GetErrorMessage(const E: ERecognitionException;
4325   const TokenNames: TStringArray): String;
4326 var
4327   UTE: EUnwantedTokenException absolute E;
4328   MTE: EMissingTokenException absolute E;
4329   MMTE: EMismatchedTokenException absolute E;
4330   MTNE: EMismatchedTreeNodeException absolute E;
4331   NVAE: ENoViableAltException absolute E;
4332   EEE: EEarlyExitException absolute E;
4333   MSE: EMismatchedSetException absolute E;
4334   MNSE: EMismatchedNotSetException absolute E;
4335   FPE: EFailedPredicateException absolute E;
4336   TokenName: String;
4337 begin
4338   Result := E.Message;
4339   if (E is EUnwantedTokenException) then
4340   begin
4341     if (UTE.Expecting = TToken.EOF) then
4342       TokenName := 'EOF'
4343     else
4344       TokenName := TokenNames[UTE.Expecting];
4345     Result := 'extraneous input ' + GetTokenErrorDisplay(UTE.UnexpectedToken)
4346       + ' expecting ' + TokenName;
4347   end
4348   else
4349     if (E is EMissingTokenException) then
4350     begin
4351       if (MTE.Expecting = TToken.EOF) then
4352         TokenName := 'EOF'
4353       else
4354         TokenName := TokenNames[MTE.Expecting];
4355       Result := 'missing ' + TokenName + ' at ' + GetTokenErrorDisplay(E.Token);
4356     end
4357     else
4358       if (E is EMismatchedTokenException) then
4359       begin
4360         if (MMTE.Expecting = TToken.EOF) then
4361           TokenName := 'EOF'
4362         else
4363           TokenName := TokenNames[MMTE.Expecting];
4364         Result := 'mismatched input ' + GetTokenErrorDisplay(E.Token)
4365           + ' expecting ' + TokenName;
4366       end
4367       else
4368         if (E is EMismatchedTreeNodeException) then
4369         begin
4370           if (MTNE.Expecting = TToken.EOF) then
4371             Result := 'EOF'
4372           else
4373             Result := TokenNames[MTNE.Expecting];
4374           // The ternary operator is only necessary because of a bug in the .NET framework
4375           Result := 'mismatched tree node: ';
4376           if (MTNE.Node <> nil) and (MTNE.Node.ToString <> '') then
4377             Result := Result + MTNE.Node.ToString;
4378           Result := Result + ' expecting ' + TokenName;
4379         end
4380         else
4381           if (E is ENoViableAltException) then
4382           begin
4383             // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
4384             // and "(decision="+nvae.decisionNumber+") and
4385             // "state "+nvae.stateNumber
4386             Result := 'no viable alternative at input ' + GetTokenErrorDisplay(E.Token);
4387           end
4388           else
4389             if (E is EEarlyExitException) then
4390             begin
4391               // for development, can add "(decision="+eee.decisionNumber+")"
4392               Result := 'required (...)+ loop did not  match anyting at input '
4393                 + GetTokenErrorDisplay(E.Token);
4394             end else
4395               if (E is EMismatchedSetException) then
4396               begin
4397                 Result := 'mismatched input ' + GetTokenErrorDisplay(E.Token)
4398                   + ' expecting set ' + MSE.Expecting.ToString;
4399               end
4400               else
4401                 if (E is EMismatchedNotSetException) then
4402                 begin
4403                   Result := 'mismatched input ' + GetTokenErrorDisplay(E.Token)
4404                     + ' expecting set ' + MSE.Expecting.ToString;
4405                 end
4406                 else
4407                   if (E is EFailedPredicateException) then
4408                   begin
4409                     Result := 'rule ' + FPE.RuleName
4410                       + ' failed predicate: {' + FPE.PredicateText + '}?';
4411                   end;
4412 end;
4413 
TBaseRecognizer.GetGrammarFileName()4414 function TBaseRecognizer.GetGrammarFileName: String;
4415 begin
4416   // No defeault implementation
4417   Result := '';
4418 end;
4419 
TBaseRecognizer.GetMissingSymbol(const Input: IIntStream;4420 function TBaseRecognizer.GetMissingSymbol(const Input: IIntStream;
4421   const E: ERecognitionException; const ExpectedTokenType: Integer;
4422   const Follow: IBitSet): IANTLRInterface;
4423 begin
4424   // No defeault implementation
4425   Result := nil;
4426 end;
4427 
GetNumberOfSyntaxErrorsnull4428 function TBaseRecognizer.GetNumberOfSyntaxErrors: Integer;
4429 begin
4430   Result := FState.SyntaxErrors;
4431 end;
4432 
GetRuleMemoizationnull4433 function TBaseRecognizer.GetRuleMemoization(const RuleIndex,
4434   RuleStartIndex: Integer): Integer;
4435 var
4436   Dict: IDictionary<Integer, Integer>;
4437 begin
4438   Dict := FState.RuleMemo[RuleIndex];
4439   if (Dict = nil) then
4440   begin
4441     Dict := TDictionary<Integer, Integer>.Create;
4442     FState.RuleMemo[RuleIndex] := Dict;
4443   end;
4444   if (not Dict.TryGetValue(RuleStartIndex, Result)) then
4445     Result := MEMO_RULE_UNKNOWN;
4446 end;
4447 
TBaseRecognizer.GetRuleMemoizationChaceSize()4448 function TBaseRecognizer.GetRuleMemoizationChaceSize: Integer;
4449 var
4450   RuleMap: IDictionary<Integer, Integer>;
4451 begin
4452   Result := 0;
4453   if Assigned(FState.RuleMemo) then
4454   begin
4455     for RuleMap in FState.RuleMemo do
4456       if Assigned(RuleMap) then
4457         Inc(Result,RuleMap.Count);  // how many input indexes are recorded?
4458   end;
4459 end;
4460 
TBaseRecognizer.GetState()4461 function TBaseRecognizer.GetState: IRecognizerSharedState;
4462 begin
4463   Result := FState;
4464 end;
4465 
GetTokenErrorDisplaynull4466 function TBaseRecognizer.GetTokenErrorDisplay(const T: IToken): String;
4467 begin
4468   Result := T.Text;
4469   if (Result = '') then
4470   begin
4471     if (T.TokenType = TToken.EOF) then
4472       Result := '<EOF>'
4473     else
4474       Result := '<' + IntToStr(T.TokenType) + '>';
4475   end;
4476   Result := ReplaceStr(Result,#10,'\n');
4477   Result := ReplaceStr(Result,#13,'\r');
4478   Result := ReplaceStr(Result,#9,'\t');
4479   Result := '''' + Result + '''';
4480 end;
4481 
GetTokenNamesnull4482 function TBaseRecognizer.GetTokenNames: TStringArray;
4483 begin
4484   // no default implementation
4485   Result := nil;
4486 end;
4487 
TBaseRecognizer.Match(const Input: IIntStream;4488 function TBaseRecognizer.Match(const Input: IIntStream;
4489   const TokenType: Integer; const Follow: IBitSet): IANTLRInterface;
4490 begin
4491   Result := GetCurrentInputSymbol(Input);
4492   if (Input.LA(1) = TokenType) then
4493   begin
4494     Input.Consume;
4495     FState.ErrorRecovery := False;
4496     FState.Failed := False;
4497   end else
4498   begin
4499     if (FState.Backtracking > 0) then
4500       FState.Failed := True
4501     else
4502     begin
4503       Mismatch(Input, TokenType, Follow);
4504       Result := RecoverFromMismatchedToken(Input, TokenType, Follow);
4505     end;
4506   end;
4507 end;
4508 
4509 procedure TBaseRecognizer.MatchAny(const Input: IIntStream);
4510 begin
4511   FState.ErrorRecovery := False;
4512   FState.Failed := False;
4513   Input.Consume;
4514 end;
4515 
4516 procedure TBaseRecognizer.Memoize(const Input: IIntStream; const RuleIndex,
4517   RuleStartIndex: Integer);
4518 var
4519   StopTokenIndex: Integer;
4520   Dict: IDictionary<Integer, Integer>;
4521 begin
4522   Dict := FState.RuleMemo[RuleIndex];
4523   if Assigned(Dict) then
4524   begin
4525     if FState.Failed then
4526       StopTokenIndex := MEMO_RULE_FAILED
4527     else
4528       StopTokenIndex := Input.Index - 1;
4529     Dict.AddOrSetValue(RuleStartIndex, StopTokenIndex);
4530   end;
4531 end;
4532 
4533 procedure TBaseRecognizer.Mismatch(const Input: IIntStream;
4534   const TokenType: Integer; const Follow: IBitSet);
4535 begin
4536   if MismatchIsUnwantedToken(Input, TokenType) then
4537     raise EUnwantedTokenException.Create(TokenType, Input)
4538   else
4539     if MismatchIsMissingToken(Input, Follow) then
4540       raise EMissingTokenException.Create(TokenType, Input, nil)
4541     else
4542       raise EMismatchedTokenException.Create(TokenType, Input);
4543 end;
4544 
TBaseRecognizer.MismatchIsMissingToken(const Input: IIntStream;4545 function TBaseRecognizer.MismatchIsMissingToken(const Input: IIntStream;
4546   const Follow: IBitSet): Boolean;
4547 var
4548   ViableTokensFollowingThisRule, Follow2: IBitSet;
4549 begin
4550   if (Follow = nil) then
4551     // we have no information about the follow; we can only consume
4552     // a single token and hope for the best
4553     Result := False
4554   else
4555   begin
4556     Follow2 := Follow;
4557     // compute what can follow this grammar element reference
4558     if (Follow.Member(TToken.EOR_TOKEN_TYPE)) then
4559     begin
4560       ViableTokensFollowingThisRule := ComputeContextSensitiveRuleFOLLOW();
4561       Follow2 := Follow.BitSetOr(ViableTokensFollowingThisRule);
4562       if (FState.FollowingStackPointer >= 0) then
4563         // remove EOR if we're not the start symbol
4564         Follow2.Remove(TToken.EOR_TOKEN_TYPE);
4565     end;
4566 
4567     // if current token is consistent with what could come after set
4568     // then we know we're missing a token; error recovery is free to
4569     // "insert" the missing token
4570 
4571     // BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR
4572     // in follow set to indicate that the fall of the start symbol is
4573     // in the set (EOF can follow).
4574     if (Follow2.Member(Input.LA(1)) or Follow2.Member(TToken.EOR_TOKEN_TYPE)) then
4575       Result := True
4576     else
4577       Result := False;
4578   end;
4579 end;
4580 
MismatchIsUnwantedTokennull4581 function TBaseRecognizer.MismatchIsUnwantedToken(const Input: IIntStream;
4582   const TokenType: Integer): Boolean;
4583 begin
4584   Result := (Input.LA(2) = TokenType);
4585 end;
4586 
4587 procedure TBaseRecognizer.PushFollow(const FSet: IBitSet);
4588 var
4589   F: TBitSetArray;
4590   I: Integer;
4591 begin
4592   if ((FState.FollowingStackPointer + 1) >= Length(FState.Following)) then
4593   begin
4594     SetLength(F, Length(FState.Following) * 2);
4595     FillChar(F[0], Length(F) * SizeOf(IBitSet), 0);
4596     for I := 0 to Length(FState.Following) - 1 do
4597       F[I] := FState.Following[I];
4598     FState.Following := F;
4599   end;
4600   FState.FollowingStackPointer := FState.FollowingStackPointer + 1;
4601   FState.Following[FState.FollowingStackPointer] := FSet;
4602 end;
4603 
4604 procedure TBaseRecognizer.Recover(const Input: IIntStream;
4605   const RE: ERecognitionException);
4606 var
4607   FollowSet: IBitSet;
4608 begin
4609   if (FState.LastErrorIndex = Input.Index) then
4610     // uh oh, another error at same token index; must be a case
4611     // where LT(1) is in the recovery token set so nothing is
4612     // consumed; consume a single token so at least to prevent
4613     // an infinite loop; this is a failsafe.
4614     Input.Consume;
4615   FState.LastErrorIndex := Input.Index;
4616   FollowSet := ComputeErrorRecoverySet;
4617   BeginResync;
4618   ConsumeUntil(Input,FollowSet);
4619   EndResync;
4620 end;
4621 
TBaseRecognizer.RecoverFromMismatchedSet(const Input: IIntStream;4622 function TBaseRecognizer.RecoverFromMismatchedSet(const Input: IIntStream;
4623   const E: ERecognitionException; const Follow: IBitSet): IANTLRInterface;
4624 begin
4625   if MismatchIsMissingToken(Input, Follow) then
4626   begin
4627     ReportError(E);
4628     // we don't know how to conjure up a token for sets yet
4629     Result := GetMissingSymbol(Input, E, TToken.INVALID_TOKEN_TYPE, Follow);
4630   end
4631   else
4632   begin
4633     // TODO do single token deletion like above for Token mismatch
4634     Result := nil;
4635     raise E;
4636   end;
4637 end;
4638 
RecoverFromMismatchedTokennull4639 function TBaseRecognizer.RecoverFromMismatchedToken(const Input: IIntStream;
4640   const TokenType: Integer; const Follow: IBitSet): IANTLRInterface;
4641 var
4642   E: ERecognitionException;
4643 begin
4644   // if next token is what we are looking for then "delete" this token
4645   if MismatchIsUnwantedToken(Input, TokenType) then
4646   begin
4647     E := EUnwantedTokenException.Create(TokenType, Input);
4648     BeginResync;
4649     Input.Consume; // simply delete extra token
4650     EndResync;
4651     ReportError(E);  // report after consuming so AW sees the token in the exception
4652     // we want to return the token we're actually matching
4653     Result := GetCurrentInputSymbol(Input);
4654     Input.Consume;  // move past ttype token as if all were ok
4655   end
4656   else
4657   begin
4658     // can't recover with single token deletion, try insertion
4659     if MismatchIsMissingToken(Input, Follow) then
4660     begin
4661       E := nil;
4662       Result := GetMissingSymbol(Input, E, TokenType, Follow);
4663       E := EMissingTokenException.Create(TokenType, Input, Result);
4664       ReportError(E);  // report after inserting so AW sees the token in the exception
4665     end
4666     else
4667     begin
4668       // even that didn't work; must throw the exception
4669       raise EMismatchedTokenException.Create(TokenType, Input);
4670     end;
4671   end;
4672 end;
4673 
4674 procedure TBaseRecognizer.ReportError(const E: ERecognitionException);
4675 begin
4676   // if we've already reported an error and have not matched a token
4677   // yet successfully, don't report any errors.
4678   if (not FState.ErrorRecovery) then
4679   begin
4680     FState.SyntaxErrors := FState.SyntaxErrors + 1; // don't count spurious
4681     FState.ErrorRecovery := True;
4682     DisplayRecognitionError(GetTokenNames, E);
4683   end;
4684 end;
4685 
4686 procedure TBaseRecognizer.Reset;
4687 var
4688   I: Integer;
4689 begin
4690   // wack everything related to error recovery
4691   if (FState = nil) then
4692     Exit;  // no shared state work to do
4693 
4694   FState.FollowingStackPointer := -1;
4695   FState.ErrorRecovery := False;
4696   FState.LastErrorIndex := -1;
4697   FState.Failed := False;
4698   FState.SyntaxErrors := 0;
4699 
4700   // wack everything related to backtracking and memoization
4701   FState.Backtracking := 0;
4702   if Assigned(FState.RuleMemo) then
4703     for I := 0 to Length(FState.RuleMemo) - 1 do
4704     begin
4705       // wipe cache
4706       FState.RuleMemo[I] := nil;
4707     end;
4708 end;
4709 
ToStringsnull4710 function TBaseRecognizer.ToStrings(const Tokens: IList<IToken>): IList<String>;
4711 var
4712   Token: IToken;
4713 begin
4714   if (Tokens = nil) then
4715     Result := nil
4716   else
4717   begin
4718     Result := TList<String>.Create;
4719     for Token in Tokens do
4720       Result.Add(Token.Text);
4721   end;
4722 end;
4723 
4724 procedure TBaseRecognizer.TraceIn(const RuleName: String;
4725   const RuleIndex: Integer; const InputSymbol: String);
4726 begin
4727   Write('enter ' + RuleName + ' ' + InputSymbol);
4728   if (FState.Failed) then
4729     WriteLn(' failed=True');
4730   if (FState.Backtracking > 0) then
4731     Write(' backtracking=' + IntToStr(FState.Backtracking));
4732   WriteLn;
4733 end;
4734 
4735 procedure TBaseRecognizer.TraceOut(const RuleName: String;
4736   const RuleIndex: Integer; const InputSymbol: String);
4737 begin
4738   Write('exit ' + RuleName + ' ' + InputSymbol);
4739   if (FState.Failed) then
4740     WriteLn(' failed=True');
4741   if (FState.Backtracking > 0) then
4742     Write(' backtracking=' + IntToStr(FState.Backtracking));
4743   WriteLn;
4744 end;
4745 
4746 { TCommonTokenStream }
4747 
4748 procedure TCommonTokenStream.Consume;
4749 begin
4750   if (FP < FTokens.Count) then
4751   begin
4752     Inc(FP);
4753     FP := SkipOffTokenChannels(FP); // leave p on valid token
4754   end;
4755 end;
4756 
4757 constructor TCommonTokenStream.Create;
4758 begin
4759   inherited;
4760   FP := -1;
4761   FChannel := TToken.DEFAULT_CHANNEL;
4762   FTokens := TList<IToken>.Create;
4763   FTokens.Capacity := 500;
4764 end;
4765 
4766 constructor TCommonTokenStream.Create(const ATokenSource: ITokenSource);
4767 begin
4768   Create;
4769   FTokenSource := ATokenSource;
4770 end;
4771 
4772 procedure TCommonTokenStream.DiscardOffChannelTokens(const Discard: Boolean);
4773 begin
4774   FDiscardOffChannelTokens := Discard;
4775 end;
4776 
4777 procedure TCommonTokenStream.DiscardTokenType(const TType: Integer);
4778 begin
4779   if (FDiscardSet = nil) then
4780     FDiscardSet := THashList<Integer, Integer>.Create;
4781   FDiscardSet.Add(TType, TType);
4782 end;
4783 
4784 procedure TCommonTokenStream.FillBuffer;
4785 var
4786   Index: Integer;
4787   T: IToken;
4788   Discard: Boolean;
4789 begin
4790   Index := 0;
4791   T := FTokenSource.NextToken;
4792   while Assigned(T) and (T.TokenType <> Integer(cscEOF)) do
4793   begin
4794     Discard := False;
4795     // is there a channel override for token type?
4796     if Assigned(FChannelOverrideMap) then
4797       if FChannelOverrideMap.ContainsKey(T.TokenType) then
4798         T.Channel := FChannelOverrideMap[T.TokenType];
4799 
4800     if Assigned(FDiscardSet) and FDiscardSet.ContainsKey(T.TokenType) then
4801       Discard := True
4802     else
4803       if FDiscardOffChannelTokens and (T.Channel <> FChannel) then
4804         Discard := True;
4805 
4806     if (not Discard) then
4807     begin
4808       T.TokenIndex := Index;
4809       FTokens.Add(T);
4810       Inc(Index);
4811     end;
4812 
4813     T := FTokenSource.NextToken;
4814   end;
4815   // leave p pointing at first token on channel
4816   FP := 0;
4817   FP := SkipOffTokenChannels(FP);
4818 end;
4819 
TCommonTokenStream.Get(const I: Integer)4820 function TCommonTokenStream.Get(const I: Integer): IToken;
4821 begin
4822   Result := FTokens[I];
4823 end;
4824 
GetSourceNamenull4825 function TCommonTokenStream.GetSourceName: String;
4826 begin
4827   Result := FTokenSource.SourceName;
4828 end;
4829 
GetTokensnull4830 function TCommonTokenStream.GetTokens(const Start, Stop: Integer;
4831   const Types: IList<Integer>): IList<IToken>;
4832 begin
4833   Result := GetTokens(Start, Stop, TBitSet.Create(Types));
4834 end;
4835 
GetTokensnull4836 function TCommonTokenStream.GetTokens(const Start, Stop,
4837   TokenType: Integer): IList<IToken>;
4838 begin
4839   Result := GetTokens(Start, Stop, TBitSet.BitSetOf(TokenType));
4840 end;
4841 
GetTokensnull4842 function TCommonTokenStream.GetTokens(const Start, Stop: Integer;
4843   const Types: IBitSet): IList<IToken>;
4844 var
4845   I, StartIndex, StopIndex: Integer;
4846   T: IToken;
4847 begin
4848   if (FP = -1) then
4849     FillBuffer;
4850   StopIndex := Min(Stop,FTokens.Count - 1);
4851   StartIndex := Max(Start,0);
4852   if (StartIndex > StopIndex) then
4853     Result := nil
4854   else
4855   begin
4856     Result := TList<IToken>.Create;
4857     for I := StartIndex to StopIndex do
4858     begin
4859       T := FTokens[I];
4860       if (Types = nil) or Types.Member(T.TokenType) then
4861         Result.Add(T);
4862     end;
4863     if (Result.Count = 0) then
4864       Result := nil;
4865   end;
4866 end;
4867 
GetTokensnull4868 function TCommonTokenStream.GetTokens: IList<IToken>;
4869 begin
4870   if (FP = -1) then
4871     FillBuffer;
4872   Result := FTokens;
4873 end;
4874 
GetTokensnull4875 function TCommonTokenStream.GetTokens(const Start,
4876   Stop: Integer): IList<IToken>;
4877 begin
4878   Result := GetTokens(Start, Stop, IBitSet(nil));
4879 end;
4880 
TCommonTokenStream.GetTokenSource()4881 function TCommonTokenStream.GetTokenSource: ITokenSource;
4882 begin
4883   Result := FTokenSource;
4884 end;
4885 
TCommonTokenStream.Index()4886 function TCommonTokenStream.Index: Integer;
4887 begin
4888   Result := FP;
4889 end;
4890 
LAnull4891 function TCommonTokenStream.LA(I: Integer): Integer;
4892 begin
4893   Result := LT(I).TokenType;
4894 end;
4895 
TCommonTokenStream.LAChar(I: Integer)4896 function TCommonTokenStream.LAChar(I: Integer): Char;
4897 begin
4898   Result := Char(LA(I));
4899 end;
4900 
LBnull4901 function TCommonTokenStream.LB(const K: Integer): IToken;
4902 var
4903   I, N: Integer;
4904 begin
4905   if (FP = -1) then
4906     FillBuffer;
4907   if (K = 0) then
4908     Result := nil
4909   else
4910     if ((FP - K) < 0) then
4911       Result := nil
4912     else
4913     begin
4914       I := FP;
4915       N := 1;
4916       // find k good tokens looking backwards
4917       while (N <= K) do
4918       begin
4919         // skip off-channel tokens
4920         I := SkipOffTokenChannelsReverse(I - 1); // leave p on valid token
4921         Inc(N);
4922       end;
4923       if (I < 0) then
4924         Result := nil
4925       else
4926         Result := FTokens[I];
4927     end;
4928 end;
4929 
LTnull4930 function TCommonTokenStream.LT(const K: Integer): IToken;
4931 var
4932   I, N: Integer;
4933 begin
4934   if (FP = -1) then
4935     FillBuffer;
4936   if (K = 0) then
4937     Result := nil
4938   else
4939     if (K < 0) then
4940       Result := LB(-K)
4941     else
4942       if ((FP + K - 1) >= FTokens.Count) then
4943         Result := TToken.EOF_TOKEN
4944       else
4945       begin
4946         I := FP;
4947         N := 1;
4948         // find k good tokens
4949         while (N < K) do
4950         begin
4951           // skip off-channel tokens
4952           I := SkipOffTokenChannels(I + 1); // leave p on valid token
4953           Inc(N);
4954         end;
4955         if (I >= FTokens.Count) then
4956           Result := TToken.EOF_TOKEN
4957         else
4958           Result := FTokens[I];
4959       end;
4960 end;
4961 
Marknull4962 function TCommonTokenStream.Mark: Integer;
4963 begin
4964   if (FP = -1) then
4965     FillBuffer;
4966   FLastMarker := Index;
4967   Result := FLastMarker;
4968 end;
4969 
4970 procedure TCommonTokenStream.Release(const Marker: Integer);
4971 begin
4972   // no resources to release
4973 end;
4974 
4975 procedure TCommonTokenStream.Reset;
4976 begin
4977   FP := 0;
4978   FLastMarker := 0;
4979 end;
4980 
4981 procedure TCommonTokenStream.Rewind(const Marker: Integer);
4982 begin
4983   Seek(Marker);
4984 end;
4985 
4986 procedure TCommonTokenStream.Rewind;
4987 begin
4988   Seek(FLastMarker);
4989 end;
4990 
4991 procedure TCommonTokenStream.Seek(const Index: Integer);
4992 begin
4993   FP := Index;
4994 end;
4995 
4996 procedure TCommonTokenStream.SetTokenSource(const Value: ITokenSource);
4997 begin
4998   FTokenSource := Value;
4999   FTokens.Clear;
5000   FP := -1;
5001   FChannel := TToken.DEFAULT_CHANNEL;
5002 end;
5003 
5004 procedure TCommonTokenStream.SetTokenTypeChannel(const TType, Channel: Integer);
5005 begin
5006   if (FChannelOverrideMap = nil) then
5007     FChannelOverrideMap := TDictionary<Integer, Integer>.Create;
5008   FChannelOverrideMap[TType] := Channel;
5009 end;
5010 
Sizenull5011 function TCommonTokenStream.Size: Integer;
5012 begin
5013   Result := FTokens.Count;
5014 end;
5015 
SkipOffTokenChannelsnull5016 function TCommonTokenStream.SkipOffTokenChannels(const I: Integer): Integer;
5017 var
5018   N: Integer;
5019 begin
5020   Result := I;
5021   N := FTokens.Count;
5022   while (Result < N) and (FTokens[Result].Channel <> FChannel) do
5023     Inc(Result);
5024 end;
5025 
TCommonTokenStream.SkipOffTokenChannelsReverse(5026 function TCommonTokenStream.SkipOffTokenChannelsReverse(
5027   const I: Integer): Integer;
5028 begin
5029   Result := I;
5030   while (Result >= 0) and (FTokens[Result].Channel <> FChannel) do
5031     Dec(Result);
5032 end;
5033 
TCommonTokenStream.ToString()5034 function TCommonTokenStream.ToString: String;
5035 begin
5036   if (FP = -1) then
5037     FillBuffer;
5038   Result := ToString(0, FTokens.Count - 1);
5039 end;
5040 
TCommonTokenStream.ToString(const Start, Stop: Integer)5041 function TCommonTokenStream.ToString(const Start, Stop: Integer): String;
5042 var
5043   I, Finish: Integer;
5044   Buf: TStringBuilder;
5045   T: IToken;
5046 begin
5047   if (Start < 0) or (Stop < 0) then
5048     Result := ''
5049   else
5050   begin
5051     if (FP = -1) then
5052       FillBuffer;
5053     if (Stop >= FTokens.Count) then
5054       Finish := FTokens.Count - 1
5055     else
5056       Finish := Stop;
5057     Buf := TStringBuilder.Create;
5058     try
5059       for I := Start to Finish do
5060       begin
5061         T := FTokens[I];
5062         Buf.Append(T.Text);
5063       end;
5064       Result := Buf.ToString;
5065     finally
5066       Buf.Free;
5067     end;
5068   end;
5069 end;
5070 
TCommonTokenStream.ToString(const Start, Stop: IToken)5071 function TCommonTokenStream.ToString(const Start, Stop: IToken): String;
5072 begin
5073   if Assigned(Start) and Assigned(Stop) then
5074     Result := ToString(Start.TokenIndex, Stop.TokenIndex)
5075   else
5076     Result := '';
5077 end;
5078 
5079 constructor TCommonTokenStream.Create(const ATokenSource: ITokenSource;
5080   const AChannel: Integer);
5081 begin
5082   Create(ATokenSource);
5083   FChannel := AChannel;
5084 end;
5085 
5086 constructor TCommonTokenStream.Create(const ALexer: ILexer);
5087 begin
5088   Create(ALexer as ITokenSource);
5089 end;
5090 
5091 constructor TCommonTokenStream.Create(const ALexer: ILexer;
5092   const AChannel: Integer);
5093 begin
5094   Create(ALexer as ITokenSource, AChannel);
5095 end;
5096 
5097 { TDFA }
5098 
TDFA.Description()5099 function TDFA.Description: String;
5100 begin
5101   Result := 'n/a';
5102 end;
5103 
5104 procedure TDFA.Error(const NVAE: ENoViableAltException);
5105 begin
5106   // No default implementation
5107 end;
5108 
GetRecognizernull5109 function TDFA.GetRecognizer: IBaseRecognizer;
5110 begin
5111   Result := IBaseRecognizer(FRecognizer);
5112 end;
5113 
GetSpecialStateTransitionHandlernull5114 function TDFA.GetSpecialStateTransitionHandler: TSpecialStateTransitionHandler;
5115 begin
5116   Result := FSpecialStateTransitionHandler;
5117 end;
5118 
5119 procedure TDFA.NoViableAlt(const S: Integer; const Input: IIntStream);
5120 var
5121   NVAE: ENoViableAltException;
5122 begin
5123   if (Recognizer.State.Backtracking > 0) then
5124     Recognizer.State.Failed := True
5125   else
5126   begin
5127     NVAE := ENoViableAltException.Create(Description, FDecisionNumber, S, Input);
5128     Error(NVAE);
5129     raise NVAE;
5130   end;
5131 end;
5132 
Predictnull5133 function TDFA.Predict(const Input: IIntStream): Integer;
5134 var
5135   Mark, S, SNext, SpecialState: Integer;
5136   C: Char;
5137 begin
5138   Result := 0;
5139   Mark := Input.Mark; // remember where decision started in input
5140   S := 0; // we always start at s0
5141   try
5142     while True do
5143     begin
5144       SpecialState := FSpecial[S];
5145       if (SpecialState >= 0) then
5146       begin
5147         S := FSpecialStateTransitionHandler(Self, SpecialState, Input);
5148         if (S = -1) then
5149         begin
5150           NoViableAlt(S, Input);
5151           Exit;
5152         end;
5153         Input.Consume;
5154         Continue;
5155       end;
5156 
5157       if (FAccept[S] >= 1) then
5158       begin
5159         Result := FAccept[S];
5160         Exit;
5161       end;
5162 
5163       // look for a normal char transition
5164       C := Char(Input.LA(1)); // -1 == \uFFFF, all tokens fit in 65000 space
5165       if (C >= FMin[S]) and (C <= FMax[S]) then
5166       begin
5167         SNext := FTransition[S,Integer(C) - Integer(FMin[S])];  // move to next state
5168         if (SNext < 0) then
5169         begin
5170           // was in range but not a normal transition
5171           // must check EOT, which is like the else clause.
5172           // eot[s]>=0 indicates that an EOT edge goes to another
5173           // state.
5174           if (FEOT[S] >= 0) then  // EOT Transition to accept state?
5175           begin
5176             S := FEOT[S];
5177             Input.Consume;
5178             // TODO: I had this as return accept[eot[s]]
5179             // which assumed here that the EOT edge always
5180             // went to an accept...faster to do this, but
5181             // what about predicated edges coming from EOT
5182             // target?
5183             Continue;
5184           end;
5185 
5186           NoViableAlt(S, Input);
5187           Exit;
5188         end;
5189         S := SNext;
5190         Input.Consume;
5191         Continue;
5192       end;
5193 
5194       if (FEOT[S] >= 0) then
5195       begin
5196         // EOT Transition?
5197         S := FEOT[S];
5198         Input.Consume;
5199         Continue;
5200       end;
5201 
5202       if (C = Char(TToken.EOF)) and (FEOF[S] >= 0) then
5203       begin
5204         // EOF Transition to accept state?
5205         Result := FAccept[FEOF[S]];
5206         Exit;
5207       end;
5208 
5209       // not in range and not EOF/EOT, must be invalid symbol
5210       NoViableAlt(S, Input);
5211       Exit;
5212     end;
5213   finally
5214     Input.Rewind(Mark);
5215   end;
5216 end;
5217 
5218 procedure TDFA.SetRecognizer(const Value: IBaseRecognizer);
5219 begin
5220   FRecognizer := Pointer(Value);
5221 end;
5222 
5223 procedure TDFA.SetSpecialStateTransitionHandler(
5224   const Value: TSpecialStateTransitionHandler);
5225 begin
5226   FSpecialStateTransitionHandler := Value;
5227 end;
5228 
SpecialStateTransitionnull5229 function TDFA.SpecialStateTransition(const S: Integer;
5230   const Input: IIntStream): Integer;
5231 begin
5232   // No default implementation
5233   Result := -1;
5234 end;
5235 
SpecialTransitionnull5236 function TDFA.SpecialTransition(const State, Symbol: Integer): Integer;
5237 begin
5238   Result := 0;
5239 end;
5240 
TDFA.UnpackEncodedString(5241 class function TDFA.UnpackEncodedString(
5242   const EncodedString: String): TSmallintArray;
5243 var
5244   I, J, DI, Size: Integer;
5245   N, V: Char;
5246 begin
5247   Size := 0;
5248   I := 1;
5249   while (I <= Length(EncodedString)) do
5250   begin
5251     Inc(Size,Integer(EncodedString[I]));
5252     Inc(I,2);
5253   end;
5254 
5255   SetLength(Result,Size);
5256   DI := 0;
5257   I := 1;
5258   while (I <= Length(EncodedString)) do
5259   begin
5260     N := EncodedString[I];
5261     V := EncodedString[I + 1];
5262     // add v n times to data
5263     for J := 1 to Integer(N) do
5264     begin
5265       Result[DI] := Smallint(V);
5266       Inc(DI);
5267     end;
5268     Inc(I,2);
5269   end;
5270 end;
5271 
TDFA.UnpackEncodedStringArray(5272 class function TDFA.UnpackEncodedStringArray(
5273   const EncodedStrings: array of String): TSmallintMatrix;
5274 var
5275   I: Integer;
5276 begin
5277   SetLength(Result,Length(EncodedStrings));
5278   for I := 0 to Length(EncodedStrings) - 1 do
5279     Result[I] := UnpackEncodedString(EncodedStrings[I]);
5280 end;
5281 
TDFA.UnpackEncodedStringArray(5282 class function TDFA.UnpackEncodedStringArray(
5283   const EncodedStrings: TStringArray): TSmallintMatrix;
5284 var
5285   I: Integer;
5286 begin
5287   SetLength(Result,Length(EncodedStrings));
5288   for I := 0 to Length(EncodedStrings) - 1 do
5289     Result[I] := UnpackEncodedString(EncodedStrings[I]);
5290 end;
5291 
TDFA.UnpackEncodedStringToUnsignedChars(5292 class function TDFA.UnpackEncodedStringToUnsignedChars(
5293   const EncodedString: String): TCharArray;
5294 var
5295   I, J, DI, Size: Integer;
5296   N, V: Char;
5297 begin
5298   Size := 0;
5299   I := 1;
5300   while (I <= Length(EncodedString)) do
5301   begin
5302     Inc(Size,Integer(EncodedString[I]));
5303     Inc(I,2);
5304   end;
5305 
5306   SetLength(Result,Size);
5307   DI := 0;
5308   I := 1;
5309   while (I <= Length(EncodedString)) do
5310   begin
5311     N := EncodedString[I];
5312     V := EncodedString[I + 1];
5313     // add v n times to data
5314     for J := 1 to Integer(N) do
5315     begin
5316       Result[DI] := V;
5317       Inc(DI);
5318     end;
5319     Inc(I,2);
5320   end;
5321 end;
5322 
5323 { TLexer }
5324 
5325 constructor TLexer.Create;
5326 begin
5327   inherited;
5328 end;
5329 
5330 constructor TLexer.Create(const AInput: ICharStream);
5331 begin
5332   inherited Create;
5333   FInput := AInput;
5334 end;
5335 
5336 constructor TLexer.Create(const AInput: ICharStream;
5337   const AState: IRecognizerSharedState);
5338 begin
5339   inherited Create(AState);
5340   FInput := AInput;
5341 end;
5342 
Emitnull5343 function TLexer.Emit: IToken;
5344 begin
5345   Result := TCommonToken.Create(FInput, FState.TokenType, FState.Channel,
5346     FState.TokenStartCharIndex, GetCharIndex - 1);
5347   Result.Line := FState.TokenStartLine;
5348   Result.Text := FState.Text;
5349   Result.CharPositionInLine := FState.TokenStartCharPositionInLine;
5350   Emit(Result);
5351 end;
5352 
5353 procedure TLexer.Emit(const Token: IToken);
5354 begin
5355   FState.Token := Token;
5356 end;
5357 
GetCharErrorDisplaynull5358 function TLexer.GetCharErrorDisplay(const C: Integer): String;
5359 begin
5360   case C of
5361     // TToken.EOF
5362     TOKEN_dot_EOF:
5363       Result := '<EOF>';
5364     10:
5365       Result := '\n';
5366     9:
5367       Result := '\t';
5368     13:
5369       Result := '\r';
5370     else
5371       Result := Char(C);
5372   end;
5373   Result := '''' + Result + '''';
5374 end;
5375 
GetCharIndexnull5376 function TLexer.GetCharIndex: Integer;
5377 begin
5378   Result := FInput.Index;
5379 end;
5380 
GetCharPositionInLinenull5381 function TLexer.GetCharPositionInLine: Integer;
5382 begin
5383   Result := FInput.CharPositionInLine;
5384 end;
5385 
TLexer.GetCharStream()5386 function TLexer.GetCharStream: ICharStream;
5387 begin
5388   Result := FInput;
5389 end;
5390 
GetErrorMessagenull5391 function TLexer.GetErrorMessage(const E: ERecognitionException;
5392   const TokenNames: TStringArray): String;
5393 var
5394   MTE: EMismatchedTokenException absolute E;
5395   NVAE: ENoViableAltException absolute E;
5396   EEE: EEarlyExitException absolute E;
5397   MNSE: EMismatchedNotSetException absolute E;
5398   MSE: EMismatchedSetException absolute E;
5399   MRE: EMismatchedRangeException absolute E;
5400 begin
5401   if (E is EMismatchedTokenException) then
5402     Result := 'mismatched character ' + GetCharErrorDisplay(E.Character)
5403       + ' expecting ' + GetCharErrorDisplay(MTE.Expecting)
5404   else
5405     if (E is ENoViableAltException) then
5406       // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
5407       // and "(decision="+nvae.decisionNumber+") and
5408       // "state "+nvae.stateNumber
5409       Result := 'no viable alternative at character ' + GetCharErrorDisplay(NVAE.Character)
5410     else
5411       if (E is EEarlyExitException) then
5412         // for development, can add "(decision="+eee.decisionNumber+")"
5413         Result := 'required (...)+ loop did not match anything at character '
5414           + GetCharErrorDisplay(EEE.Character)
5415       else
5416         if (E is EMismatchedNotSetException) then
5417           Result := 'mismatched character ' + GetCharErrorDisplay(MNSE.Character)
5418             + ' expecting set ' + MNSE.Expecting.ToString
5419         else
5420           if (E is EMismatchedSetException) then
5421             Result := 'mismatched character ' + GetCharErrorDisplay(MSE.Character)
5422               + ' expecting set ' + MSE.Expecting.ToString
5423           else
5424             if (E is EMismatchedRangeException) then
5425               Result := 'mismatched character ' + GetCharErrorDisplay(MRE.Character)
5426                 + ' expecting set ' + GetCharErrorDisplay(MRE.A) + '..'
5427                 + GetCharErrorDisplay(MRE.B)
5428             else
5429               Result := inherited GetErrorMessage(E, TokenNames);
5430 end;
5431 
TLexer.GetInput()5432 function TLexer.GetInput: IIntStream;
5433 begin
5434   Result := FInput;
5435 end;
5436 
GetLinenull5437 function TLexer.GetLine: Integer;
5438 begin
5439   Result := FInput.Line;
5440 end;
5441 
GetSourceNamenull5442 function TLexer.GetSourceName: String;
5443 begin
5444   Result := FInput.SourceName;
5445 end;
5446 
TLexer.GetText()5447 function TLexer.GetText: String;
5448 begin
5449   if (FState.Text <> '') then
5450     Result := FState.Text
5451   else
5452     Result := FInput.Substring(FState.TokenStartCharIndex, GetCharIndex - 1)
5453 end;
5454 
5455 procedure TLexer.Match(const S: String);
5456 var
5457   I: Integer;
5458   MTE: EMismatchedTokenException;
5459 begin
5460   for I := 1 to Length(S) do
5461   begin
5462     if (FInput.LA(1) <> Integer(S[I])) then
5463     begin
5464       if (FState.Backtracking > 0) then
5465       begin
5466         FState.Failed := True;
5467         Exit;
5468       end;
5469       MTE := EMismatchedTokenException.Create(Integer(S[I]), FInput);
5470       Recover(MTE); // don't really recover; just consume in lexer
5471       raise MTE;
5472     end;
5473     FInput.Consume;
5474     FState.Failed := False;
5475   end;
5476 end;
5477 
5478 procedure TLexer.Match(const C: Integer);
5479 var
5480   MTE: EMismatchedTokenException;
5481 begin
5482   if (FInput.LA(1) <> C) then
5483   begin
5484     if (FState.Backtracking > 0) then
5485     begin
5486       FState.Failed := True;
5487       Exit;
5488     end;
5489     MTE := EMismatchedTokenException.Create(C, FInput);
5490     Recover(MTE);
5491     raise MTE;
5492   end;
5493   FInput.Consume;
5494   FState.Failed := False;
5495 end;
5496 
5497 procedure TLexer.MatchAny;
5498 begin
5499   FInput.Consume;
5500 end;
5501 
5502 procedure TLexer.MatchRange(const A, B: Integer);
5503 var
5504   MRE: EMismatchedRangeException;
5505 begin
5506   if (FInput.LA(1) < A) or (FInput.LA(1) > B) then
5507   begin
5508     if (FState.Backtracking > 0) then
5509     begin
5510       FState.Failed := True;
5511       Exit;
5512     end;
5513     MRE := EMismatchedRangeException.Create(A, B, FInput);
5514     Recover(MRE);
5515     raise MRE;
5516   end;
5517   FInput.Consume;
5518   FState.Failed := False;
5519 end;
5520 
NextTokennull5521 function TLexer.NextToken: IToken;
5522 begin
5523   while True do
5524   begin
5525     FState.Token := nil;
5526     FState.Channel := TToken.DEFAULT_CHANNEL;
5527     FState.TokenStartCharIndex := FInput.Index;
5528     FState.TokenStartCharPositionInLine := FInput.CharPositionInLine;
5529     FState.TokenStartLine := Finput.Line;
5530     FState.Text := '';
5531     if (FInput.LA(1) = Integer(cscEOF)) then
5532     begin
5533       Result := TToken.EOF_TOKEN;
5534       Exit;
5535     end;
5536 
5537     try
5538       DoTokens;
5539       if (FState.Token = nil) then
5540         Emit
5541       else
5542         if (FState.Token = TToken.SKIP_TOKEN) then
5543           Continue;
5544       Exit(FState.Token);
5545     except
5546       on NVA: ENoViableAltException do
5547       begin
5548         ReportError(NVA);
5549         Recover(NVA);  // throw out current char and try again
5550       end;
5551 
5552       on RE: ERecognitionException do
5553       begin
5554         ReportError(RE);
5555         // Match() routine has already called Recover()
5556       end;
5557     end;
5558   end;
5559 end;
5560 
5561 procedure TLexer.Recover(const RE: ERecognitionException);
5562 begin
5563   FInput.Consume;
5564 end;
5565 
5566 procedure TLexer.ReportError(const E: ERecognitionException);
5567 begin
5568   DisplayRecognitionError(GetTokenNames, E);
5569 end;
5570 
5571 procedure TLexer.Reset;
5572 begin
5573   inherited; // reset all recognizer state variables
5574   // wack Lexer state variables
5575   if Assigned(FInput) then
5576     FInput.Seek(0);  // rewind the input
5577   if (FState = nil) then
5578     Exit;  // no shared state work to do
5579   FState.Token := nil;
5580   FState.TokenType := TToken.INVALID_TOKEN_TYPE;
5581   FState.Channel := TToken.DEFAULT_CHANNEL;
5582   FState.TokenStartCharIndex := -1;
5583   FState.TokenStartCharPositionInLine := -1;
5584   FState.TokenStartLine := -1;
5585   FState.Text := '';
5586 end;
5587 
5588 procedure TLexer.SetCharStream(const Value: ICharStream);
5589 begin
5590   FInput := nil;
5591   Reset;
5592   FInput := Value;
5593 end;
5594 
5595 procedure TLexer.SetText(const Value: String);
5596 begin
5597   FState.Text := Value;
5598 end;
5599 
5600 procedure TLexer.Skip;
5601 begin
5602   FState.Token := TToken.SKIP_TOKEN;
5603 end;
5604 
5605 procedure TLexer.TraceIn(const RuleName: String; const RuleIndex: Integer);
5606 var
5607   InputSymbol: String;
5608 begin
5609   InputSymbol := Char(FInput.LT(1)) + ' line=' + IntToStr(GetLine) + ':'
5610     + IntToStr(GetCharPositionInLine);
5611   inherited TraceIn(RuleName, RuleIndex, InputSymbol);
5612 end;
5613 
5614 procedure TLexer.TraceOut(const RuleName: String; const RuleIndex: Integer);
5615 var
5616   InputSymbol: String;
5617 begin
5618   InputSymbol := Char(FInput.LT(1)) + ' line=' + IntToStr(GetLine) + ':'
5619     + IntToStr(GetCharPositionInLine);
5620   inherited TraceOut(RuleName, RuleIndex, InputSymbol);
5621 end;
5622 
5623 { TParser }
5624 
5625 constructor TParser.Create(const AInput: ITokenStream);
5626 begin
5627   inherited Create; // highlight that we go to base class to set state object
5628   SetTokenStream(AInput);
5629 end;
5630 
5631 constructor TParser.Create(const AInput: ITokenStream;
5632   const AState: IRecognizerSharedState);
5633 begin
5634   inherited Create(AState); // share the state object with another parser
5635   SetTokenStream(AInput);
5636 end;
5637 
TParser.GetCurrentInputSymbol(5638 function TParser.GetCurrentInputSymbol(
5639   const Input: IIntStream): IANTLRInterface;
5640 begin
5641   Result := FInput.LT(1)
5642 end;
5643 
TParser.GetInput()5644 function TParser.GetInput: IIntStream;
5645 begin
5646   Result := FInput;
5647 end;
5648 
GetMissingSymbolnull5649 function TParser.GetMissingSymbol(const Input: IIntStream;
5650   const E: ERecognitionException; const ExpectedTokenType: Integer;
5651   const Follow: IBitSet): IANTLRInterface;
5652 var
5653   TokenText: String;
5654   T: ICommonToken;
5655   Current: IToken;
5656 begin
5657   if (ExpectedTokenType = TToken.EOF) then
5658     TokenText := '<missing EOF>'
5659   else
5660     TokenText := '<missing ' + GetTokenNames[ExpectedTokenType] + '>';
5661   T := TCommonToken.Create(ExpectedTokenType, TokenText);
5662   Current := FInput.LT(1);
5663   if (Current.TokenType = TToken.EOF) then
5664     Current := FInput.LT(-1);
5665   T.Line := Current.Line;
5666   T.CharPositionInLine := Current.CharPositionInLine;
5667   T.Channel := DEFAULT_TOKEN_CHANNEL;
5668   Result := T;
5669 end;
5670 
TParser.GetSourceName()5671 function TParser.GetSourceName: String;
5672 begin
5673   Result := FInput.SourceName;
5674 end;
5675 
TParser.GetTokenStream()5676 function TParser.GetTokenStream: ITokenStream;
5677 begin
5678   Result := FInput;
5679 end;
5680 
5681 procedure TParser.Reset;
5682 begin
5683   inherited; // reset all recognizer state variables
5684   if Assigned(FInput) then
5685     FInput.Seek(0); // rewind the input
5686 end;
5687 
5688 procedure TParser.SetTokenStream(const Value: ITokenStream);
5689 begin
5690   FInput := nil;
5691   Reset;
5692   FInput := Value;
5693 end;
5694 
5695 procedure TParser.TraceIn(const RuleName: String; const RuleIndex: Integer);
5696 begin
5697   inherited TraceIn(RuleName, RuleIndex, FInput.LT(1).ToString);
5698 end;
5699 
5700 procedure TParser.TraceOut(const RuleName: String; const RuleIndex: Integer);
5701 begin
5702   inherited TraceOut(RuleName, RuleIndex, FInput.LT(1).ToString);
5703 end;
5704 
5705 { TRuleReturnScope }
5706 
TRuleReturnScope.GetStart()5707 function TRuleReturnScope.GetStart: IANTLRInterface;
5708 begin
5709   Result := nil;
5710 end;
5711 
GetStopnull5712 function TRuleReturnScope.GetStop: IANTLRInterface;
5713 begin
5714   Result := nil;
5715 end;
5716 
TRuleReturnScope.GetTemplate()5717 function TRuleReturnScope.GetTemplate: IANTLRInterface;
5718 begin
5719   Result := nil;
5720 end;
5721 
TRuleReturnScope.GetTree()5722 function TRuleReturnScope.GetTree: IANTLRInterface;
5723 begin
5724   Result := nil;
5725 end;
5726 
5727 procedure TRuleReturnScope.SetStart(const Value: IANTLRInterface);
5728 begin
5729   raise EInvalidOperation.Create('Setter has not been defined for this property.');
5730 end;
5731 
5732 procedure TRuleReturnScope.SetStop(const Value: IANTLRInterface);
5733 begin
5734   raise EInvalidOperation.Create('Setter has not been defined for this property.');
5735 end;
5736 
5737 procedure TRuleReturnScope.SetTree(const Value: IANTLRInterface);
5738 begin
5739   raise EInvalidOperation.Create('Setter has not been defined for this property.');
5740 end;
5741 
5742 { TParserRuleReturnScope }
5743 
TParserRuleReturnScope.GetStart()5744 function TParserRuleReturnScope.GetStart: IANTLRInterface;
5745 begin
5746   Result := FStart;
5747 end;
5748 
GetStopnull5749 function TParserRuleReturnScope.GetStop: IANTLRInterface;
5750 begin
5751   Result := FStop;
5752 end;
5753 
5754 procedure TParserRuleReturnScope.SetStart(const Value: IANTLRInterface);
5755 begin
5756   FStart := Value as IToken;
5757 end;
5758 
5759 procedure TParserRuleReturnScope.SetStop(const Value: IANTLRInterface);
5760 begin
5761   FStop := Value as IToken;
5762 end;
5763 
5764 { TTokenRewriteStream }
5765 
5766 procedure TTokenRewriteStream.Delete(const Start, Stop: IToken);
5767 begin
5768   Delete(DEFAULT_PROGRAM_NAME, Start, Stop);
5769 end;
5770 
5771 procedure TTokenRewriteStream.Delete(const IndexT: IToken);
5772 begin
5773   Delete(DEFAULT_PROGRAM_NAME, IndexT, IndexT);
5774 end;
5775 
5776 constructor TTokenRewriteStream.Create;
5777 begin
5778   inherited;
5779   Init;
5780 end;
5781 
5782 constructor TTokenRewriteStream.Create(const ATokenSource: ITokenSource);
5783 begin
5784   inherited Create(ATokenSource);
5785   Init;
5786 end;
5787 
5788 constructor TTokenRewriteStream.Create(const ALexer: ILexer);
5789 begin
5790   Create(ALexer as ITokenSource);
5791 end;
5792 
5793 constructor TTokenRewriteStream.Create(const ALexer: ILexer;
5794   const AChannel: Integer);
5795 begin
5796   Create(ALexer as ITokenSource, AChannel);
5797 end;
5798 
CatOpTextnull5799 function TTokenRewriteStream.CatOpText(const A, B: IANTLRInterface): IANTLRInterface;
5800 var
5801   X, Y: String;
5802 begin
5803   if Assigned(A) then
5804     X := A.ToString
5805   else
5806     X := '';
5807 
5808   if Assigned(B) then
5809     Y := B.ToString
5810   else
5811     Y := '';
5812 
5813   Result := TANTLRString.Create(X + Y);
5814 end;
5815 
5816 constructor TTokenRewriteStream.Create(const ATokenSource: ITokenSource;
5817   const AChannel: Integer);
5818 begin
5819   inherited Create(ATokenSource, AChannel);
5820   Init;
5821 end;
5822 
5823 procedure TTokenRewriteStream.Delete(const ProgramName: String; const Start,
5824   Stop: IToken);
5825 begin
5826   Replace(ProgramName, Start, Stop, nil);
5827 end;
5828 
5829 procedure TTokenRewriteStream.Delete(const ProgramName: String; const Start,
5830   Stop: Integer);
5831 begin
5832   Replace(ProgramName, Start, Stop, nil);
5833 end;
5834 
5835 procedure TTokenRewriteStream.Delete(const Start, Stop: Integer);
5836 begin
5837   Delete(DEFAULT_PROGRAM_NAME, Start, Stop);
5838 end;
5839 
5840 procedure TTokenRewriteStream.Delete(const Index: Integer);
5841 begin
5842   Delete(DEFAULT_PROGRAM_NAME, Index, Index);
5843 end;
5844 
5845 procedure TTokenRewriteStream.DeleteProgram(const ProgramName: String);
5846 begin
5847   Rollback(ProgramName, MIN_TOKEN_INDEX);
5848 end;
5849 
5850 procedure TTokenRewriteStream.DeleteProgram;
5851 begin
5852   DeleteProgram(DEFAULT_PROGRAM_NAME);
5853 end;
5854 
GetLastRewriteTokenIndexnull5855 function TTokenRewriteStream.GetLastRewriteTokenIndex: Integer;
5856 begin
5857   Result := GetLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
5858 end;
5859 
GetKindOfOpsnull5860 function TTokenRewriteStream.GetKindOfOps(
5861   const Rewrites: IList<IRewriteOperation>;
5862   const Kind: TGUID): IList<IRewriteOperation>;
5863 begin
5864   Result := GetKindOfOps(Rewrites, Kind, Rewrites.Count);
5865 end;
5866 
GetKindOfOpsnull5867 function TTokenRewriteStream.GetKindOfOps(
5868   const Rewrites: IList<IRewriteOperation>; const Kind: TGUID;
5869   const Before: Integer): IList<IRewriteOperation>;
5870 var
5871   I: Integer;
5872   Op: IRewriteOperation;
5873   Obj: IInterface;
5874 begin
5875   Result := TList<IRewriteOperation>.Create;
5876   I := 0;
5877   while (I < Before) and (I < Rewrites.Count) do
5878   begin
5879     Op := Rewrites[I];
5880     if Assigned(Op) and (Op.QueryInterface(Kind, Obj) = 0) then
5881       Result.Add(Op);
5882     Inc(I);
5883   end;
5884 end;
5885 
GetLastRewriteTokenIndexnull5886 function TTokenRewriteStream.GetLastRewriteTokenIndex(
5887   const ProgramName: String): Integer;
5888 begin
5889   if (not FLastRewriteTokenIndexes.TryGetValue(ProgramName, Result)) then
5890     Result := -1;
5891 end;
5892 
GetProgramnull5893 function TTokenRewriteStream.GetProgram(
5894   const Name: String): IList<IRewriteOperation>;
5895 var
5896   InstructionStream: IList<IRewriteOperation>;
5897 begin
5898   InstructionStream := FPrograms[Name];
5899   if (InstructionStream = nil) then
5900     InstructionStream := InitializeProgram(Name);
5901   Result := InstructionStream;
5902 end;
5903 
5904 procedure TTokenRewriteStream.InsertAfter(const ProgramName: String;
5905   const T: IToken; const Text: IANTLRInterface);
5906 begin
5907   InsertAfter(ProgramName, T.TokenIndex, Text);
5908 end;
5909 
5910 procedure TTokenRewriteStream.Init;
5911 var
5912   List: IList<IRewriteOperation>;
5913 begin
5914   FPrograms := TDictionary<String, IList<IRewriteOperation>>.Create;
5915   List := TList<IRewriteOperation>.Create;
5916   List.Capacity := PROGRAM_INIT_SIZE;
5917   FPrograms.Add(DEFAULT_PROGRAM_NAME, List);
5918   FLastRewriteTokenIndexes := TDictionary<String, Integer>.Create;
5919 end;
5920 
TTokenRewriteStream.InitializeProgram(5921 function TTokenRewriteStream.InitializeProgram(
5922   const Name: String): IList<IRewriteOperation>;
5923 begin
5924   Result := TList<IRewriteOperation>.Create;
5925   Result.Capacity := PROGRAM_INIT_SIZE;
5926   FPrograms[Name] := Result;
5927 end;
5928 
5929 procedure TTokenRewriteStream.InsertAfter(const ProgramName: String;
5930   const Index: Integer; const Text: IANTLRInterface);
5931 begin
5932   // to insert after, just insert before next index (even if past end)
5933   InsertBefore(ProgramName, Index + 1, Text);
5934 end;
5935 
5936 procedure TTokenRewriteStream.InsertAfter(const T: IToken;
5937   const Text: IANTLRInterface);
5938 begin
5939   InsertAfter(DEFAULT_PROGRAM_NAME, T, Text);
5940 end;
5941 
5942 procedure TTokenRewriteStream.InsertAfter(const Index: Integer;
5943   const Text: IANTLRInterface);
5944 begin
5945   InsertAfter(DEFAULT_PROGRAM_NAME, Index, Text);
5946 end;
5947 
5948 procedure TTokenRewriteStream.InsertBefore(const Index: Integer;
5949   const Text: IANTLRInterface);
5950 begin
5951   InsertBefore(DEFAULT_PROGRAM_NAME, Index, Text);
5952 end;
5953 
5954 procedure TTokenRewriteStream.InsertBefore(const ProgramName: String;
5955   const T: IToken; const Text: IANTLRInterface);
5956 begin
5957   InsertBefore(ProgramName, T.TokenIndex, Text);
5958 end;
5959 
5960 procedure TTokenRewriteStream.InsertBefore(const ProgramName: String;
5961   const Index: Integer; const Text: IANTLRInterface);
5962 var
5963   Op: IRewriteOperation;
5964 begin
5965   Op := TInsertBeforeOp.Create(Index, Text, Self);
5966   GetProgram(ProgramName).Add(Op);
5967 end;
5968 
5969 procedure TTokenRewriteStream.InsertBefore(const T: IToken;
5970   const Text: IANTLRInterface);
5971 begin
5972   InsertBefore(DEFAULT_PROGRAM_NAME, T, Text);
5973 end;
5974 
5975 procedure TTokenRewriteStream.Replace(const Start, Stop: IToken;
5976   const Text: IANTLRInterface);
5977 begin
5978   Replace(DEFAULT_PROGRAM_NAME, Stop, Stop, Text);
5979 end;
5980 
5981 procedure TTokenRewriteStream.Replace(const IndexT: IToken;
5982   const Text: IANTLRInterface);
5983 begin
5984   Replace(DEFAULT_PROGRAM_NAME, IndexT, IndexT, Text);
5985 end;
5986 
5987 procedure TTokenRewriteStream.Replace(const ProgramName: String; const Start,
5988   Stop: Integer; const Text: IANTLRInterface);
5989 var
5990   Op: IRewriteOperation;
5991   Rewrites: IList<IRewriteOperation>;
5992 begin
5993   if (Start > Stop) or (Start < 0) or (Stop < 0) or (Stop >= GetTokens.Count) then
5994     raise EArgumentOutOfRangeException.Create('replace: range invalid: '
5995       + IntToStr(Start) + '..' + IntToStr(Stop) + '(size='
5996       + IntToStr(GetTokens.Count) + ')');
5997 
5998   Op := TReplaceOp.Create(Start, Stop, Text, Self);
5999   Rewrites := GetProgram(ProgramName);
6000   Op.InstructionIndex := Rewrites.Count;
6001   Rewrites.Add(Op);
6002 end;
6003 
ReduceToSingleOperationPerIndexnull6004 function TTokenRewriteStream.ReduceToSingleOperationPerIndex(
6005   const Rewrites: IList<IRewriteOperation>): IDictionary<Integer, IRewriteOperation>;
6006 var
6007   I, J: Integer;
6008   Op: IRewriteOperation;
6009   ROp, PrevROp: IReplaceOp;
6010   IOp, PrevIOp: IInsertBeforeOp;
6011   Inserts, PrevInserts, PrevReplaces: IList<IRewriteOperation>;
6012   Disjoint, Same: Boolean;
6013 begin
6014   // WALK REPLACES
6015   for I := 0 to Rewrites.Count - 1 do
6016   begin
6017     Op := Rewrites[I];
6018     if (Op = nil) then
6019       Continue;
6020     if (not Supports(Op, IReplaceOp, ROp)) then
6021       Continue;
6022 
6023     // Wipe prior inserts within range
6024     Inserts := GetKindOfOps(Rewrites, IInsertBeforeOp, I);
6025     for J := 0 to Inserts.Count - 1 do
6026     begin
6027       IOp := Inserts[J] as IInsertBeforeOp;
6028       if (IOp.Index >= ROp.Index) and (IOp.Index <= ROp.LastIndex) then
6029       begin
6030         // delete insert as it's a no-op.
6031         Rewrites[IOp.InstructionIndex] := nil;
6032       end;
6033     end;
6034 
6035     // Drop any prior replaces contained within
6036     PrevReplaces := GetKindOfOps(Rewrites, IReplaceOp, I);
6037     for J := 0 to PrevReplaces.Count - 1 do
6038     begin
6039       PrevROp := PrevReplaces[J] as IReplaceOp;
6040       if (PrevROp.Index >= ROp.Index) and (PrevROp.LastIndex <= ROp.LastIndex) then
6041       begin
6042         // delete replace as it's a no-op.
6043         Rewrites[PrevROp.InstructionIndex] := nil;
6044         Continue;
6045       end;
6046       // throw exception unless disjoint or identical
6047       Disjoint := (PrevROp.LastIndex < ROp.Index) or (PrevROp.Index > ROp.LastIndex);
6048       Same := (PrevROp.Index = ROp.Index) and (PrevROp.LastIndex = ROp.LastIndex);
6049       if (not Disjoint) and (not Same) then
6050         raise EArgumentOutOfRangeException.Create('replace of boundaries of '
6051           + ROp.ToString + ' overlap with previous ' + PrevROp.ToString);
6052     end;
6053   end;
6054 
6055   // WALK INSERTS
6056   for I := 0 to Rewrites.Count - 1 do
6057   begin
6058     Op := Rewrites[I];
6059     if (Op = nil) then
6060       Continue;
6061     if (not Supports(Op, IInsertBeforeOp, IOp)) then
6062       Continue;
6063 
6064     // combine current insert with prior if any at same index
6065     PrevInserts := GetKindOfOps(Rewrites, IInsertBeforeOp, I);
6066     for J := 0 to PrevInserts.Count - 1 do
6067     begin
6068       PrevIOp := PrevInserts[J] as IInsertBeforeOp;
6069       if (PrevIOp.Index = IOp.Index) then
6070       begin
6071         // combine objects
6072         // convert to strings...we're in process of toString'ing
6073         // whole token buffer so no lazy eval issue with any templates
6074         IOp.Text := CatOpText(IOp.Text, PrevIOp.Text);
6075         // delete redundant prior insert
6076         Rewrites[PrevIOp.InstructionIndex] := nil;
6077       end;
6078     end;
6079 
6080     // look for replaces where iop.index is in range; error
6081     PrevReplaces := GetKindOfOps(Rewrites, IReplaceOp, I);
6082     for J := 0 to PrevReplaces.Count - 1 do
6083     begin
6084       Rop := PrevReplaces[J] as IReplaceOp;
6085       if (IOp.Index = ROp.Index) then
6086       begin
6087         ROp.Text := CatOpText(IOp.Text, ROp.Text);
6088         Rewrites[I] := nil;  // delete current insert
6089         Continue;
6090       end;
6091       if (IOp.Index >= ROp.Index) and (IOp.Index <= ROp.LastIndex) then
6092         raise EArgumentOutOfRangeException.Create('insert op '
6093           + IOp.ToString + ' within boundaries of previous ' + ROp.ToString);
6094     end;
6095   end;
6096 
6097   Result := TDictionary<Integer, IRewriteOperation>.Create;
6098   for Op in Rewrites do
6099   begin
6100     if (Op = nil) then
6101       Continue; // ignore deleted ops
6102     if (Result.ContainsKey(Op.Index)) then
6103       raise Exception.Create('should only be one op per index');
6104     Result.Add(Op.Index, Op);
6105   end;
6106 end;
6107 
6108 procedure TTokenRewriteStream.Replace(const ProgramName: String; const Start,
6109   Stop: IToken; const Text: IANTLRInterface);
6110 begin
6111   Replace(ProgramName, Start.TokenIndex, Stop.TokenIndex, Text);
6112 end;
6113 
6114 procedure TTokenRewriteStream.Replace(const Index: Integer;
6115   const Text: IANTLRInterface);
6116 begin
6117   Replace(DEFAULT_PROGRAM_NAME, Index, Index, Text);
6118 end;
6119 
6120 procedure TTokenRewriteStream.Replace(const Start, Stop: Integer;
6121   const Text: IANTLRInterface);
6122 begin
6123   Replace(DEFAULT_PROGRAM_NAME, Start, Stop, Text);
6124 end;
6125 
6126 procedure TTokenRewriteStream.Rollback(const InstructionIndex: Integer);
6127 begin
6128   Rollback(DEFAULT_PROGRAM_NAME, InstructionIndex);
6129 end;
6130 
6131 procedure TTokenRewriteStream.Rollback(const ProgramName: String;
6132   const InstructionIndex: Integer);
6133 var
6134   InstructionStream: IList<IRewriteOperation>;
6135 begin
6136   InstructionStream := FPrograms[ProgramName];
6137   if Assigned(InstructionStream) then
6138     FPrograms[ProgramName] := InstructionStream.GetRange(MIN_TOKEN_INDEX,
6139       InstructionIndex - MIN_TOKEN_INDEX);
6140 end;
6141 
6142 procedure TTokenRewriteStream.SetLastRewriteTokenIndex(
6143   const ProgramName: String; const I: Integer);
6144 begin
6145   FLastRewriteTokenIndexes[ProgramName] := I;
6146 end;
6147 
ToDebugStringnull6148 function TTokenRewriteStream.ToDebugString: String;
6149 begin
6150   Result := ToDebugString(MIN_TOKEN_INDEX, Size - 1);
6151 end;
6152 
ToDebugStringnull6153 function TTokenRewriteStream.ToDebugString(const Start, Stop: Integer): String;
6154 var
6155   Buf: TStringBuilder;
6156   I: Integer;
6157 begin
6158   Buf := TStringBuilder.Create;
6159   try
6160     if (Start >= MIN_TOKEN_INDEX) then
6161       for I := Start to Min(Stop,GetTokens.Count - 1) do
6162         Buf.Append(Get(I).ToString);
6163   finally
6164     Buf.Free;
6165   end;
6166 end;
6167 
ToOriginalStringnull6168 function TTokenRewriteStream.ToOriginalString: String;
6169 begin
6170   Result := ToOriginalString(MIN_TOKEN_INDEX, Size - 1);
6171 end;
6172 
ToOriginalStringnull6173 function TTokenRewriteStream.ToOriginalString(const Start,
6174   Stop: Integer): String;
6175 var
6176   Buf: TStringBuilder;
6177   I: Integer;
6178 begin
6179   Buf := TStringBuilder.Create;
6180   try
6181     if (Start >= MIN_TOKEN_INDEX) then
6182       for I := Start to Min(Stop, GetTokens.Count - 1) do
6183         Buf.Append(Get(I).Text);
6184     Result := Buf.ToString;
6185   finally
6186     Buf.Free;
6187   end;
6188 end;
6189 
TTokenRewriteStream.ToString()6190 function TTokenRewriteStream.ToString: String;
6191 begin
6192   Result := ToString(MIN_TOKEN_INDEX, Size - 1);
6193 end;
6194 
TTokenRewriteStream.ToString(const ProgramName: String)6195 function TTokenRewriteStream.ToString(const ProgramName: String): String;
6196 begin
6197   Result := ToString(ProgramName, MIN_TOKEN_INDEX, Size - 1);
6198 end;
6199 
TTokenRewriteStream.ToString(const ProgramName: String; const Start,6200 function TTokenRewriteStream.ToString(const ProgramName: String; const Start,
6201   Stop: Integer): String;
6202 var
6203   Rewrites: IList<IRewriteOperation>;
6204   I, StartIndex, StopIndex: Integer;
6205   IndexToOp: IDictionary<Integer, IRewriteOperation>;
6206   Buf: TStringBuilder;
6207   Tokens: IList<IToken>;
6208   T: IToken;
6209   Op: IRewriteOperation;
6210   Pair: TPair<Integer, IRewriteOperation>;
6211 begin
6212   Rewrites := FPrograms[ProgramName];
6213   Tokens := GetTokens;
6214   // ensure start/end are in range
6215   StopIndex := Min(Stop,Tokens.Count - 1);
6216   StartIndex := Max(Start,0);
6217 
6218   if (Rewrites = nil) or (Rewrites.Count = 0) then
6219   begin
6220      // no instructions to execute
6221     Result := ToOriginalString(StartIndex, StopIndex);
6222     Exit;
6223   end;
6224 
6225   Buf := TStringBuilder.Create;
6226   try
6227     // First, optimize instruction stream
6228     IndexToOp := ReduceToSingleOperationPerIndex(Rewrites);
6229 
6230     // Walk buffer, executing instructions and emitting tokens
6231     I := StartIndex;
6232     while (I <= StopIndex) and (I < Tokens.Count) do
6233     begin
6234       if (not IndexToOp.TryGetValue(I, Op)) then
6235         Op := nil;
6236       IndexToOp.Remove(I); // remove so any left have index size-1
6237       T := Tokens[I];
6238       if (Op = nil) then
6239       begin
6240         // no operation at that index, just dump token
6241         Buf.Append(T.Text);
6242         Inc(I); // move to next token
6243       end
6244       else
6245         I := Op.Execute(Buf); // execute operation and skip
6246     end;
6247 
6248     // include stuff after end if it's last index in buffer
6249     // So, if they did an insertAfter(lastValidIndex, "foo"), include
6250     // foo if end==lastValidIndex.
6251     if (StopIndex = Tokens.Count - 1) then
6252     begin
6253       // Scan any remaining operations after last token
6254       // should be included (they will be inserts).
6255       for Pair in IndexToOp do
6256       begin
6257         if (Pair.Value.Index >= Tokens.Count - 1) then
6258           Buf.Append(Pair.Value.Text.ToString);
6259       end;
6260     end;
6261     Result := Buf.ToString;
6262   finally
6263     Buf.Free;
6264   end;
6265 end;
6266 
TTokenRewriteStream.ToString(const Start, Stop: Integer)6267 function TTokenRewriteStream.ToString(const Start, Stop: Integer): String;
6268 begin
6269   Result := ToString(DEFAULT_PROGRAM_NAME, Start, Stop);
6270 end;
6271 
6272 procedure TTokenRewriteStream.InsertBefore(const Index: Integer;
6273   const Text: String);
6274 var
6275   S: IANTLRString;
6276 begin
6277   S := TANTLRString.Create(Text);
6278   InsertBefore(Index, S);
6279 end;
6280 
6281 procedure TTokenRewriteStream.InsertBefore(const T: IToken; const Text: String);
6282 var
6283   S: IANTLRString;
6284 begin
6285   S := TANTLRString.Create(Text);
6286   InsertBefore(T, S);
6287 end;
6288 
6289 procedure TTokenRewriteStream.InsertBefore(const ProgramName: String;
6290   const Index: Integer; const Text: String);
6291 var
6292   S: IANTLRString;
6293 begin
6294   S := TANTLRString.Create(Text);
6295   InsertBefore(ProgramName, Index, S);
6296 end;
6297 
6298 procedure TTokenRewriteStream.InsertBefore(const ProgramName: String;
6299   const T: IToken; const Text: String);
6300 var
6301   S: IANTLRString;
6302 begin
6303   S := TANTLRString.Create(Text);
6304   InsertBefore(ProgramName, T, S);
6305 end;
6306 
6307 procedure TTokenRewriteStream.InsertAfter(const Index: Integer;
6308   const Text: String);
6309 var
6310   S: IANTLRString;
6311 begin
6312   S := TANTLRString.Create(Text);
6313   InsertAfter(Index,S);
6314 end;
6315 
6316 procedure TTokenRewriteStream.InsertAfter(const T: IToken; const Text: String);
6317 var
6318   S: IANTLRString;
6319 begin
6320   S := TANTLRString.Create(Text);
6321   InsertAfter(T,S);
6322 end;
6323 
6324 procedure TTokenRewriteStream.InsertAfter(const ProgramName: String;
6325   const Index: Integer; const Text: String);
6326 var
6327   S: IANTLRString;
6328 begin
6329   S := TANTLRString.Create(Text);
6330   InsertAfter(ProgramName,Index,S);
6331 end;
6332 
6333 procedure TTokenRewriteStream.InsertAfter(const ProgramName: String;
6334   const T: IToken; const Text: String);
6335 var
6336   S: IANTLRString;
6337 begin
6338   S := TANTLRString.Create(Text);
6339   InsertAfter(ProgramName,T,S);
6340 end;
6341 
6342 procedure TTokenRewriteStream.Replace(const IndexT: IToken; const Text: String);
6343 var
6344   S: IANTLRString;
6345 begin
6346   S := TANTLRString.Create(Text);
6347   Replace(IndexT, S);
6348 end;
6349 
6350 procedure TTokenRewriteStream.Replace(const Start, Stop: Integer;
6351   const Text: String);
6352 var
6353   S: IANTLRString;
6354 begin
6355   S := TANTLRString.Create(Text);
6356   Replace(Start, Stop, S);
6357 end;
6358 
6359 procedure TTokenRewriteStream.Replace(const Index: Integer; const Text: String);
6360 var
6361   S: IANTLRString;
6362 begin
6363   S := TANTLRString.Create(Text);
6364   Replace(Index, S);
6365 end;
6366 
6367 procedure TTokenRewriteStream.Replace(const ProgramName: String; const Start,
6368   Stop: IToken; const Text: String);
6369 var
6370   S: IANTLRString;
6371 begin
6372   S := TANTLRString.Create(Text);
6373   Replace(ProgramName, Start, Stop, S);
6374 end;
6375 
6376 procedure TTokenRewriteStream.Replace(const ProgramName: String; const Start,
6377   Stop: Integer; const Text: String);
6378 var
6379   S: IANTLRString;
6380 begin
6381   S := TANTLRString.Create(Text);
6382   Replace(ProgramName, Start, Stop, S);
6383 end;
6384 
6385 procedure TTokenRewriteStream.Replace(const Start, Stop: IToken;
6386   const Text: String);
6387 var
6388   S: IANTLRString;
6389 begin
6390   S := TANTLRString.Create(Text);
6391   Replace(Start, Stop, S);
6392 end;
6393 
6394 { TTokenRewriteStream.TRewriteOperation }
6395 
6396 constructor TTokenRewriteStream.TRewriteOperation.Create(const AIndex: Integer;
6397   const AText: IANTLRInterface; const AParent: ITokenRewriteStream);
6398 begin
6399   inherited Create;
6400   FIndex := AIndex;
6401   FText := AText;
6402   FParent := Pointer(AParent);
6403 end;
6404 
TRewriteOperationnull6405 function TTokenRewriteStream.TRewriteOperation.Execute(
6406   const Buf: TStringBuilder): Integer;
6407 begin
6408   Result := FIndex;
6409 end;
6410 
TRewriteOperationnull6411 function TTokenRewriteStream.TRewriteOperation.GetIndex: Integer;
6412 begin
6413   Result := FIndex;
6414 end;
6415 
TRewriteOperationnull6416 function TTokenRewriteStream.TRewriteOperation.GetInstructionIndex: Integer;
6417 begin
6418   Result := FInstructionIndex;
6419 end;
6420 
TRewriteOperationnull6421 function TTokenRewriteStream.TRewriteOperation.GetParent: ITokenRewriteStream;
6422 begin
6423   Result := ITokenRewriteStream(FParent);
6424 end;
6425 
TRewriteOperationnull6426 function TTokenRewriteStream.TRewriteOperation.GetText: IANTLRInterface;
6427 begin
6428   Result := FText;
6429 end;
6430 
6431 procedure TTokenRewriteStream.TRewriteOperation.SetIndex(const Value: Integer);
6432 begin
6433   FIndex := Value;
6434 end;
6435 
6436 procedure TTokenRewriteStream.TRewriteOperation.SetInstructionIndex(
6437   const Value: Integer);
6438 begin
6439   FInstructionIndex := Value;
6440 end;
6441 
6442 procedure TTokenRewriteStream.TRewriteOperation.SetParent(
6443   const Value: ITokenRewriteStream);
6444 begin
6445   FParent := Pointer(Value);
6446 end;
6447 
6448 procedure TTokenRewriteStream.TRewriteOperation.SetText(
6449   const Value: IANTLRInterface);
6450 begin
6451   FText := Value;
6452 end;
6453 
TRewriteOperationnull6454 function TTokenRewriteStream.TRewriteOperation.ToString: String;
6455 var
6456   OpName: String;
6457   DollarIndex: Integer;
6458 begin
6459   OpName := ClassName;
6460   DollarIndex := Pos('$',OpName) - 1; // Delphi strings are 1-based
6461   if (DollarIndex >= 0) then
6462     OpName := Copy(OpName,DollarIndex + 1,Length(OpName) - (DollarIndex + 1));
6463   Result := '<' + OpName + '@' + IntToStr(FIndex) + ':"' + FText.ToString + '">';
6464 end;
6465 
6466 { TTokenRewriteStream.TRewriteOpComparer<T> }
6467 
TTokenRewriteStream.TRewriteOpComparer(const Left,6468 function TTokenRewriteStream.TRewriteOpComparer<T>.Compare(const Left,
6469   Right: T): Integer;
6470 begin
6471   if (Left.GetIndex < Right.GetIndex) then
6472     Result := -1
6473   else
6474     if (Left.GetIndex > Right.GetIndex) then
6475       Result := 1
6476     else
6477       Result := 0;
6478 end;
6479 
6480 { TTokenRewriteStream.TInsertBeforeOp }
6481 
TTokenRewriteStream.TInsertBeforeOp.Execute(6482 function TTokenRewriteStream.TInsertBeforeOp.Execute(
6483   const Buf: TStringBuilder): Integer;
6484 begin
6485   Buf.Append(Text.ToString);
6486   Buf.Append(Parent.Get(Index).Text);
6487   Result := Index + 1;
6488 end;
6489 
6490 { TTokenRewriteStream.TReplaceOp }
6491 
6492 constructor TTokenRewriteStream.TReplaceOp.Create(const AStart, AStop: Integer;
6493   const AText: IANTLRInterface; const AParent: ITokenRewriteStream);
6494 begin
6495   inherited Create(AStart, AText, AParent);
6496   FLastIndex := AStop;
6497 end;
6498 
TTokenRewriteStream.TReplaceOp.Execute(6499 function TTokenRewriteStream.TReplaceOp.Execute(
6500   const Buf: TStringBuilder): Integer;
6501 begin
6502   if (Text <> nil) then
6503     Buf.Append(Text.ToString);
6504   Result := FLastIndex + 1;
6505 end;
6506 
TReplaceOpnull6507 function TTokenRewriteStream.TReplaceOp.GetLastIndex: Integer;
6508 begin
6509   Result := FLastIndex;
6510 end;
6511 
6512 procedure TTokenRewriteStream.TReplaceOp.SetLastIndex(const Value: Integer);
6513 begin
6514   FLastIndex := Value;
6515 end;
6516 
TReplaceOpnull6517 function TTokenRewriteStream.TReplaceOp.ToString: String;
6518 begin
6519   Result := '<ReplaceOp@' + IntToStr(Index) + '..' + IntToStr(FLastIndex)
6520     + ':"' + Text.ToString + '">';
6521 end;
6522 
6523 { TTokenRewriteStream.TDeleteOp }
6524 
TTokenRewriteStream.TDeleteOp.ToString()6525 function TTokenRewriteStream.TDeleteOp.ToString: String;
6526 begin
6527   Result := '<DeleteOp@' + IntToStr(Index) + '..' + IntToStr(FLastIndex) + '>';
6528 end;
6529 
6530 { Utilities }
6531 
6532 var
6533   EmptyToken: IToken = nil;
6534   EmptyRuleReturnScope: IRuleReturnScope = nil;
6535 
Def(const X: IToken)6536 function Def(const X: IToken): IToken; overload;
6537 begin
6538   if Assigned(X) then
6539     Result := X
6540   else
6541   begin
6542     if (EmptyToken = nil) then
6543       EmptyToken := TCommonToken.Create;
6544     Result := EmptyToken;
6545   end;
6546 end;
6547 
Def(const X: IRuleReturnScope)6548 function Def(const X: IRuleReturnScope): IRuleReturnScope;
6549 begin
6550   if Assigned(X) then
6551     Result := X
6552   else
6553   begin
6554     if (EmptyRuleReturnScope = nil) then
6555       EmptyRuleReturnScope := TRuleReturnScope.Create;
6556     Result := EmptyRuleReturnScope;
6557   end;
6558 end;
6559 
6560 initialization
6561   TToken.Initialize;
6562 
6563 end.
6564