xref: /aosp_15_r20/external/antlr/runtime/Delphi/README.TXT (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot==================================================
2*16467b97STreehugger RobotANTLR v3 Delphi Code generator and Runtime library
3*16467b97STreehugger Robot==================================================
4*16467b97STreehugger Robot
5*16467b97STreehugger RobotOctober 27, 2008
6*16467b97STreehugger RobotErik van Bilsen (erik AT bilsen DOT com)
7*16467b97STreehugger Robot
8*16467b97STreehugger RobotPlease see LICENSE.TXT for the full text of the license and NOTICE.TXT
9*16467b97STreehugger Robotfor attribution notices.
10*16467b97STreehugger Robot
11*16467b97STreehugger RobotArchitecture
12*16467b97STreehugger Robot============
13*16467b97STreehugger RobotThe Delphi target consists of a set of code generation templates and a runtime
14*16467b97STreehugger Robotlibrary (written in Delphi 2009) for the Win32 platform.
15*16467b97STreehugger RobotThe Delphi code generation targets and the runtime library are modeled on the
16*16467b97STreehugger RobotC# version.
17*16467b97STreehugger Robot
18*16467b97STreehugger RobotYou need to use Delphi 2009 or a later version to be able to use this target.
19*16467b97STreehugger RobotYou will not be able to compile generated code with older versions of Delphi.
20*16467b97STreehugger RobotThe reason for this is that this Delphi target uses a lot of new Delphi
21*16467b97STreehugger Robotlanguage features such as generics.
22*16467b97STreehugger Robot
23*16467b97STreehugger RobotTo use the Delphi target, you only need to put the runtime source code in a
24*16467b97STreehugger Robotdirectory of your choice, and add this directory to you Delphi library path or
25*16467b97STreehugger Robotto your project's search path.
26*16467b97STreehugger Robot
27*16467b97STreehugger RobotThe runtime consists of the following units:
28*16467b97STreehugger Robot-Antlr.Runtime: the main Antlr unit that contains the parser and lexer classes
29*16467b97STreehugger Robot-Antlr.Runtime.Tree: the tree parser class and other tree related classes
30*16467b97STreehugger Robot-Antlr.Runtime.Collections: several collection utilities
31*16467b97STreehugger Robot-Antlr.Runtime.Tools: this is a special Delphi addition to the runtime
32*16467b97STreehugger Robot containing several helper classes and utilities
33*16467b97STreehugger RobotYou will find these files in the "Antlr3.Runtime" subdirectory.
34*16467b97STreehugger Robot
35*16467b97STreehugger RobotIn your projects, you usually only need to use the Antlr.Runtime unit, and the
36*16467b97STreehugger RobotAntlr.Runtime.Tree unit for tree parsers.
37*16467b97STreehugger RobotThis target does not require any third party libraries, and you do not have to
38*16467b97STreehugger Robotdeploy any DLLs or other files with your ANTLR Delphi projects.
39*16467b97STreehugger Robot
40*16467b97STreehugger RobotPlease note that this Delphi target does not support StringTemplate output, but
41*16467b97STreehugger Robotit does support all other output types, including AST output.
42*16467b97STreehugger Robot
43*16467b97STreehugger RobotStatus
44*16467b97STreehugger Robot======
45*16467b97STreehugger RobotAs of October 2008, the Delphi target is in sync with ANTLR 3.1.
46*16467b97STreehugger Robot
47*16467b97STreehugger RobotThis version passes all the unit tests (which you can find in the
48*16467b97STreehugger Robot"Antlr3.Runtime.Tests" subdirectory) without any memory leaks.
49*16467b97STreehugger RobotAlso, all the grammar samples in the "examples-v3\Delphi" directory function
50*16467b97STreehugger Robotcorrectly and without any memory leaks.
51*16467b97STreehugger Robot
52*16467b97STreehugger RobotPerformance
53*16467b97STreehugger Robot===========
54*16467b97STreehugger RobotThis target should perform reasonably well compared to other ANTLR targets.
55*16467b97STreehugger RobotFor some grammars, especially tree grammars, the code that is generated is not
56*16467b97STreehugger Robotas efficient as for other targets. This has to do with the way the code is
57*16467b97STreehugger Robotgenerated to work around some issues with the Delphi language. But even with
58*16467b97STreehugger Robotthese workarounds, the target performs within reasonable boundaries.
59*16467b97STreehugger Robot
60*16467b97STreehugger RobotUsage
61*16467b97STreehugger Robot=====
62*16467b97STreehugger RobotHere is a short list of Delphi specific issues you need to take into account
63*16467b97STreehugger Robotwhen using this target. Please check out the Delphi sample grammars in the
64*16467b97STreehugger Robot"examples-v3" archive for examples of all the issues described below. And these
65*16467b97STreehugger Robotexamples are a great way to get started with ANTLR.
66*16467b97STreehugger Robot
67*16467b97STreehugger RobotSpecify that Delphi code should be generated for a grammar
68*16467b97STreehugger Robot----------------------------------------------------------
69*16467b97STreehugger RobotTo specify that the ANTLR tool should generate Delphi (2009) code (rather than
70*16467b97STreehugger Robotthe default of generating Java code) for a grammar, set the grammar-level option
71*16467b97STreehugger Robotnamed "language" to the value "Delphi" as shown below:
72*16467b97STreehugger Robot
73*16467b97STreehugger Robot  grammar MyGrammar;
74*16467b97STreehugger Robot
75*16467b97STreehugger Robot  options {
76*16467b97STreehugger Robot  	language=Delphi;
77*16467b97STreehugger Robot  }
78*16467b97STreehugger Robot  ...
79*16467b97STreehugger Robot
80*16467b97STreehugger RobotFor the example grammar named MyGrammar above, the grammar file would typically
81*16467b97STreehugger Robotbe named MyGrammar.g. The grammar filename (excluding the extension) must match
82*16467b97STreehugger Robotthe grammar name as declared with the grammar directive in the file.
83*16467b97STreehugger Robot
84*16467b97STreehugger RobotUse Delphi code in actions
85*16467b97STreehugger Robot--------------------------
86*16467b97STreehugger RobotObviously, any custom actions inside your grammars should be written in the
87*16467b97STreehugger RobotDelphi language. This also applies to less obvious actions like
88*16467b97STreehugger Robot{$channel=HIDDEN;}, which should be written as {$channel:=HIDDEN;} (with the
89*16467b97STreehugger Robotcolon before the equals sign).
90*16467b97STreehugger Robot
91*16467b97STreehugger RobotRule names must not be case sensitive
92*16467b97STreehugger Robot-------------------------------------
93*16467b97STreehugger RobotSince the Delphi language is not case sensitive, you must take care that the
94*16467b97STreehugger Robotnames of rules in your grammars differ by more than only case. For example, if
95*16467b97STreehugger Robotyou have a parser rule called "expression", then you shouldn't have a lexer rule
96*16467b97STreehugger Robotcalled "EXPRESSION" or "Expression" or any other combination of upper- and lower
97*16467b97STreehugger Robotcase characters that math the same word. ANTLR will still be able to generate
98*16467b97STreehugger RobotDelphi code for this, but you will not be able to compile it because of
99*16467b97STreehugger Robotduplicate identifiers.
100*16467b97STreehugger Robot
101*16467b97STreehugger RobotThe @members grammar action
102*16467b97STreehugger Robot---------------------------
103*16467b97STreehugger RobotThe Delphi target does not recognize the default @members grammar action. It
104*16467b97STreehugger Robotuses the following three grammar actions instead (see the C and Java sample
105*16467b97STreehugger Robotgrammars for examples):
106*16467b97STreehugger Robot
107*16467b97STreehugger Robot@memberDeclarations: use this action that declare members in the generated
108*16467b97STreehugger Robotparser/lexer class. For example:
109*16467b97STreehugger Robot
110*16467b97STreehugger Robot  @memberDeclarations {
111*16467b97STreehugger Robot	enumIsKeyword: Boolean;
112*16467b97STreehugger Robot	function isTypeName(const name: String): Boolean;
113*16467b97STreehugger Robot  }
114*16467b97STreehugger Robot
115*16467b97STreehugger Robot  These declarations will appear inside the parser/lexer class declaration.
116*16467b97STreehugger Robot
117*16467b97STreehugger Robot@memberInitializations: use this action to initialize variables declared in the
118*16467b97STreehugger Robot@memberDeclarations action. For example:
119*16467b97STreehugger Robot
120*16467b97STreehugger Robot  @memberInitializations {
121*16467b97STreehugger Robot	enumIsKeyword := True;
122*16467b97STreehugger Robot  }
123*16467b97STreehugger Robot
124*16467b97STreehugger Robot  These statements will appear inside the constructor of the parser/lexer class.
125*16467b97STreehugger Robot
126*16467b97STreehugger Robot@memberImplementations: use this action for any code that must appear in the
127*16467b97STreehugger Robotparser class implementation. For example:
128*16467b97STreehugger Robot
129*16467b97STreehugger Robot  @memberImplementations {
130*16467b97STreehugger Robot  function TCParser.isTypeName(const name: String): Boolean;
131*16467b97STreehugger Robot  begin
132*16467b97STreehugger Robot    Result := [...]
133*16467b97STreehugger Robot  end;
134*16467b97STreehugger Robot  }
135*16467b97STreehugger Robot
136*16467b97STreehugger Robot  The code inside this action appears as-is inside the implementation section of
137*16467b97STreehugger Robot  the parser/lexer unit. This means that you need to specify the full name of
138*16467b97STreehugger Robot  the method, including the parser/lexer class name (eg. TCParser.isTypeName).
139*16467b97STreehugger Robot  The class name is based on the name of the grammar, and whether it is a parser
140*16467b97STreehugger Robot  or lexer. So, if your grammar is called "MyGrammar", then the lexer class will
141*16467b97STreehugger Robot  be called TMyGrammarLexer and the parser class will be called
142*16467b97STreehugger Robot  TMyGrammarParser.
143*16467b97STreehugger Robot
144*16467b97STreehugger RobotThe @vars grammar action
145*16467b97STreehugger Robot------------------------
146*16467b97STreehugger RobotANTLR supports an @init (and @after) grammar action for any code you want to
147*16467b97STreehugger Robotexecute at the beginning (or end) of a rule. If that code, or any other code
148*16467b97STreehugger Robotinside the rule, makes use of a local variable, then you need to declare that
149*16467b97STreehugger Robotvariable first. The Delphi target adds the @vars grammar action for this
150*16467b97STreehugger Robotpurpose. You can declare any local variables inside this action, as in this
151*16467b97STreehugger Robotexample (taken from the Python example grammar):
152*16467b97STreehugger Robot
153*16467b97STreehugger Robot  LEADING_WS
154*16467b97STreehugger Robot  @vars {
155*16467b97STreehugger Robot    spaces: Integer;
156*16467b97STreehugger Robot    S: String;
157*16467b97STreehugger Robot  }
158*16467b97STreehugger Robot  @init {
159*16467b97STreehugger Robot    spaces := 0;
160*16467b97STreehugger Robot  }
161*16467b97STreehugger Robot
162*16467b97STreehugger RobotThe variables you declare in the @vars action will appear inside the "var"
163*16467b97STreehugger Robotdeclaration block of the method for the rule (in this case for the
164*16467b97STreehugger RobotLEADING_WS rule).
165*16467b97STreehugger Robot
166*16467b97STreehugger RobotThe @usesInterface and @usedImplementation grammar actions
167*16467b97STreehugger Robot----------------------------------------------------------
168*16467b97STreehugger RobotIf you need to add units to the uses clause of the generated units, then you can
169*16467b97STreehugger Robotuse the @usesInterface and @usesImplementation grammar actions. For example, if
170*16467b97STreehugger Robotsome code inside the grammer rules needs access to the Delphi TStringList class,
171*16467b97STreehugger Robotthen you will need to use the Classes unit.
172*16467b97STreehugger RobotUse the @usesInterface action if you need the units to appear in the interface
173*16467b97STreehugger Robotpart, or @usesImplementation if you only need a unit inside the implementation.
174*16467b97STreehugger RobotFor example:
175*16467b97STreehugger Robot
176*16467b97STreehugger Robot  @usesImplementation {
177*16467b97STreehugger Robot    Classes,
178*16467b97STreehugger Robot    Generics.Collections,
179*16467b97STreehugger Robot  }
180*16467b97STreehugger Robot
181*16467b97STreehugger RobotNote that you need to add a comma after each unit in this list. The Delphi units
182*16467b97STreehugger RobotSysUtils, StrUtils and Math are added to the uses clause automatically.
183*16467b97STreehugger RobotAlso note that you will usually put the @usesInterface/@usesImplementation
184*16467b97STreehugger Robotactions at the top of your grammar file, like you would the with the @header
185*16467b97STreehugger Robotaction for other language targets.
186*16467b97STreehugger Robot
187*16467b97STreehugger RobotThe Delphi target is interface based
188*16467b97STreehugger Robot------------------------------------
189*16467b97STreehugger RobotAll classes inside the Delphi ANTLR runtime use object interfaces. This greatly
190*16467b97STreehugger Robotsimplifies memory management and makes using the runtime much easier. This means
191*16467b97STreehugger Robotthat you will never declare class variables for ANTLR objects, but only use
192*16467b97STreehugger Robotinterface variables. For example, a typical test rig in Delphi looks like this
193*16467b97STreehugger Robot(taken from the SimpleC example):
194*16467b97STreehugger Robot
195*16467b97STreehugger Robot  procedure Run(const InputFilename: String);
196*16467b97STreehugger Robot  var
197*16467b97STreehugger Robot    Input: ICharStream;
198*16467b97STreehugger Robot    Lex: ISimpleCLexer;
199*16467b97STreehugger Robot    Tokens: ICommonTokenStream;
200*16467b97STreehugger Robot    Parser: ISimpleCParser;
201*16467b97STreehugger Robot    R: Iprog_return;
202*16467b97STreehugger Robot  begin
203*16467b97STreehugger Robot    Input := TANTLRFileStream.Create(InputFilename);
204*16467b97STreehugger Robot    Lex := TSimpleCLexer.Create(Input);
205*16467b97STreehugger Robot    Tokens := TCommonTokenStream.Create(Lex);
206*16467b97STreehugger Robot    Parser := TSimpleCParser.Create(Tokens);
207*16467b97STreehugger Robot    R := Parser.prog;
208*16467b97STreehugger Robot    WriteLn('tree=' + (R.Tree as ITree).ToStringTree);
209*16467b97STreehugger Robot  end;
210*16467b97STreehugger Robot
211*16467b97STreehugger RobotNote that all variables are declared as interface variables (starting with a
212*16467b97STreehugger Robotcapital I) instead of class variables (with a capital T). And there is no need
213*16467b97STreehugger Robotto destroy these objects yourself (there are no calls to Free and no
214*16467b97STreehugger Robottry..finally blocks to protect these resources).
215*16467b97STreehugger Robot
216*16467b97STreehugger RobotIf you are new to interface-based programming, then don't worry: just remember
217*16467b97STreehugger Robotto declare all ANTLR objects using interface variables, and don't call Free
218*16467b97STreehugger Roboton them.
219*16467b97STreehugger Robot
220*16467b97STreehugger RobotNote that the C# and Java versions of the tree creation classes use the general
221*16467b97STreehugger RobotObject type for tree nodes. In the Delphi version, tree nodes are of type
222*16467b97STreehugger RobotIANTLRInterface, and can be implemented in various class (like TCommonTree).
223*16467b97STreehugger Robot
224*16467b97STreehugger RobotAntlr.Runtime.Tools
225*16467b97STreehugger Robot-------------------
226*16467b97STreehugger RobotThis unit contains some classes and interfaces you may find useful inside ANTLR
227*16467b97STreehugger Robotprojects. Also, this unit contains declarations for the IANTLRInterface
228*16467b97STreehugger Robotinterface and TANTLRObject class. All ANTLR classes derive from TANTLRObject and
229*16467b97STreehugger Robotimplement the IANTLRInterface interface.
230*16467b97STreehugger Robot
231*16467b97STreehugger RobotOther interfaces/classes you may find useful are:
232*16467b97STreehugger Robot
233*16467b97STreehugger Robot* IANTLRString (implemented in TANTLRString): a wrapper around a Delphi string
234*16467b97STreehugger Robot  that allows you to treat a string as a regular ANTLR object.
235*16467b97STreehugger Robot
236*16467b97STreehugger Robot* IList<T> (implemented in TList<T>): a generic list containing elements of
237*16467b97STreehugger Robot  type <T>. For example, you can create a list of Integers like this:
238*16467b97STreehugger Robot
239*16467b97STreehugger Robot  var
240*16467b97STreehugger Robot    List: IList<Integer>;
241*16467b97STreehugger Robot  begin
242*16467b97STreehugger Robot    List := TList<Integer>.Create;
243*16467b97STreehugger Robot    List.Add(123);
244*16467b97STreehugger Robot  end;
245*16467b97STreehugger Robot
246*16467b97STreehugger Robot  Note that this is basically the same TList<T> declared in Delphi's unit
247*16467b97STreehugger Robot  Generics.Collections, but it implements the IList<T> interface.
248*16467b97STreehugger Robot
249*16467b97STreehugger Robot* IDictionary<TKey, TValue> (implemented in TDictionary<TKey, TValue>): a
250*16467b97STreehugger Robot  generic dictionary that maps elements of type <TKey> to <TValue>. For example,
251*16467b97STreehugger Robot  to map Strings to TANTLRObjects, use:
252*16467b97STreehugger Robot
253*16467b97STreehugger Robot  var
254*16467b97STreehugger Robot    Map: IDictionary<String, IANTLRInterface>
255*16467b97STreehugger Robot  begin
256*16467b97STreehugger Robot    Map := TDictionary<String, IANTLRInterface>.Create;
257*16467b97STreehugger Robot    Map.Add('foo', TANTLRObject.Create);
258*16467b97STreehugger Robot  end;
259*16467b97STreehugger Robot
260*16467b97STreehugger Robot  Again, this class is similar to Delphi's TDictionary, but it implements the
261*16467b97STreehugger Robot  IDictionary<TKey, TValue> interface.
262*16467b97STreehugger Robot
263*16467b97STreehugger Robot
264*16467b97STreehugger Robot
265*16467b97STreehugger RobotErik van Bilsen
266