1/*
2 [The "BSD license"]
3 Copyright (c) 2008 Erik van Bilsen
4 Copyright (c) 2007-2008 Johannes Luber
5 Copyright (c) 2005-2007 Kunle Odutola
6 Copyright (c) 2005 Terence Parr
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 1. Redistributions of source code must retain the above copyright
13    notice, this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright
15    notice, this list of conditions and the following disclaimer in the
16    documentation and/or other materials provided with the 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
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31group AST;
32
33@outputFile.imports() ::= <<
34<@super.imports()><if(!TREE_PARSER)><! tree parser would already have imported !>  Antlr.Runtime.Tree,<\n><endif>
35>>
36
37@genericParser.members() ::= <<
38<@super.members()>
39<parserMembers()>
40>>
41
42@genericParser.membersConstructor() ::= <<
43<@super.membersConstructor()>
44<parserMembersConstructor()>
45>>
46
47@genericParser.membersImplementation() ::= <<
48<@super.membersImplementation()>
49<parserMembersImplementation()>
50>>
51
52/** Add an adaptor property that knows how to build trees */
53parserMembers() ::= <<
54  strict protected
55    FAdaptor: ITreeAdaptor;
56    procedure SetAdaptor(const Value: ITreeAdaptor);
57    property Adaptor: ITreeAdaptor read FAdaptor;
58  public
59    property TreeAdaptor: ITreeAdaptor read FAdaptor write SetAdaptor;
60
61>>
62
63parserMembersConstructor() ::= <<
64FAdaptor := TCommonTreeAdaptor.Create;
65>>
66
67parserMembersImplementation() ::= <<
68procedure T<grammar.recognizerName>.SetAdaptor(const Value: ITreeAdaptor);
69begin
70  FAdaptor := Value;
71  <grammar.directDelegates:{g|<g:delegateName()>.TreeAdaptor := FAdaptor;}>
72end;
73>>
74
75@returnScope.ruleReturnMembers() ::= <<
76function T<grammar.recognizerName>.T<ruleDescriptor:returnStructName()>.GetTree: IANTLRInterface;
77begin
78  Result := FTree;
79end;
80
81procedure T<grammar.recognizerName>.T<ruleDescriptor:returnStructName()>.SetTree(const Value: IANTLRInterface);
82begin
83  FTree := Value as I<ASTLabelType>;
84end;
85>>
86
87@returnScopeDeclaration.ruleReturnMembers() ::= <<
88strict private
89  FTree: I<ASTLabelType>;
90protected
91  { IRuleReturnScope }
92  function GetTree: IANTLRInterface; override;
93  procedure SetTree(const Value: IANTLRInterface); override;
94>>
95
96/** Add a variable to track rule's return AST */
97ruleDeclarations() ::= <<
98<super.ruleDeclarations()>
99Root[0] := nil;<\n>
100>>
101
102ruleDeclarationVars() ::= <<
103<super.ruleDeclarationVars()>
104Root: array [0..63] of I<ASTLabelType>;
105>>
106
107ruleLabelDefs() ::= <<
108<super.ruleLabelDefs()>
109<ruleDescriptor.tokenLabels:{<it.label.text>_tree := nil;}; separator="\n">
110<ruleDescriptor.tokenListLabels:{<it.label.text>_tree := nil;}; separator="\n">
111<ruleDescriptor.allTokenRefsInAltsWithRewrites:{Locals['Stream_<it>'] := TRewriteRule<rewriteElementType>Stream.Create(Adaptor,'token <it>');}; separator="\n">
112<ruleDescriptor.allRuleRefsInAltsWithRewrites:{Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor,'rule <it>');}; separator="\n">
113>>
114
115ruleLabelDefVars() ::= <<
116<super.ruleLabelDefVars()>
117<ruleDescriptor.tokenLabels:{<it.label.text>_tree: I<ASTLabelType>;}; separator="\n">
118<ruleDescriptor.tokenListLabels:{<it.label.text>_tree: I<ASTLabelType>;}; separator="\n">
119>>
120/** When doing auto AST construction, we must define some variables;
121 *  These should be turned off if doing rewrites.  This must be a "mode"
122 *  as a rule could have both rewrite and AST within the same alternative
123 *  block.
124 */
125@alt.declarations() ::= <<
126<if(autoAST)>
127<if(outerAlt)>
128<if(!rewriteMode)>
129Root[0] := Adaptor.GetNilNode as I<ASTLabelType>;
130<endif>
131<endif>
132<endif>
133>>
134
135// T r a c k i n g  R u l e  E l e m e n t s
136
137/** ID and track it for use in a rewrite rule */
138tokenRefTrack(token,label,elementIndex,terminalOptions) ::= <<
139<tokenRefBang(...)> <! Track implies no auto AST construction!>
140<if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<token>'] as IRewriteRuleElementStream).Add(<label>);<\n>
141>>
142
143/** ids+=ID and track it for use in a rewrite rule; adds to ids *and*
144 *  to the tracking list stream_ID for use in the rewrite.
145 */
146tokenRefTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
147<tokenRefTrack(...)>
148<listLabel(elem=label,...)>
149>>
150
151/** ^(ID ...) track for rewrite */
152tokenRefRuleRootTrack(token,label,elementIndex,terminalOptions) ::= <<
153<tokenRefBang(...)>
154<if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<token>'] as IRewriteRuleElementStream).Add(<label>);<\n>
155>>
156
157/** Match ^(label+=TOKEN ...) track for rewrite */
158tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
159<tokenRefRuleRootTrack(...)>
160<listLabel(elem=label,...)>
161>>
162
163wildcardTrack(label,elementIndex) ::= <<
164<super.wildcard(...)>
165>>
166
167/** rule when output=AST and tracking for rewrite */
168ruleRefTrack(rule,label,elementIndex,args,scope) ::= <<
169<super.ruleRef(...)>
170<if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<rule.name>'] as IRewriteRuleElementStream).Add(<label>.Tree);<\n>
171>>
172
173/** x+=rule when output=AST and tracking for rewrite */
174ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
175<ruleRefTrack(...)>
176<listLabel(elem=label+".Tree",...)>
177>>
178
179/** ^(rule ...) rewrite */
180ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= <<
181<ruleRefRuleRoot(...)>
182<if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<rule>'] as IRewriteRuleElementStream).Add(<label>.Tree);
183>>
184
185/** ^(x+=rule ...) rewrite */
186ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
187<ruleRefRuleRootTrack(...)>
188<listLabel(elem=label+".Tree",...)>
189>>
190
191// R e w r i t e
192
193rewriteCode(
194	alts, description,
195	referencedElementsDeep, // ALL referenced elements to right of ->
196	referencedTokenLabels,
197	referencedTokenListLabels,
198	referencedRuleLabels,
199	referencedRuleListLabels,
200    referencedWildcardLabels,
201    referencedWildcardListLabels,
202	rewriteBlockLevel, enclosingTreeLevel, treeLevel) ::=
203<<
204
205// AST REWRITE
206// elements:          <referencedElementsDeep; separator=", ">
207// token labels:      <referencedTokenLabels; separator=", ">
208// rule labels:       <referencedRuleLabels; separator=", ">
209// token list labels: <referencedTokenListLabels; separator=", ">
210// rule list labels:  <referencedRuleListLabels; separator=", ">
211<if(backtracking)>
212if (State.Backtracking = 0) then
213begin<\n>
214<endif>
215<prevRuleRootRef()>.Tree := Root[0];
216<rewriteCodeLabels()>
217Root[0] := Adaptor.GetNilNode as I<ASTLabelType>;
218<alts:rewriteAlt(); separator="else ">
219<! if tree parser and rewrite=true !>
220<if(TREE_PARSER)>
221<if(rewriteMode)>
222<prevRuleRootRef()>.Tree = (<ASTLabelType>)adaptor.rulePostProcessing(root[0]);
223input.ReplaceChildren(adaptor.GetParent(retval.Start),
224                      adaptor.GetChildIndex(retval.Start),
225                      adaptor.GetChildIndex(_last),
226                      retval.Tree);
227<endif>
228<endif>
229<! if parser or rewrite!=true, we need to set result !>
230<if(!TREE_PARSER)>
231<prevRuleRootRef()>.Tree := Root[0];<\n>
232<endif>
233<if(!rewriteMode)>
234<prevRuleRootRef()>.Tree := Root[0];<\n>
235<endif>
236<if(backtracking)>
237end;
238<endif>
239>>
240
241rewriteCodeLabels() ::= <<
242<referencedTokenLabels
243    :{Locals['Stream_<it>'] := TRewriteRule<rewriteElementType>Stream.Create(Adaptor, 'token <it>', <it>);};
244    separator="\n"
245>
246<referencedTokenListLabels
247    :{Locals['Stream_<it>'] := TRewriteRule<rewriteElementType>Stream.Create(Adaptor,'token <it>', list_<it>);};
248    separator="\n"
249>
250<referencedRuleLabels:{
251if Assigned(<it>) then
252  Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor, 'token <it>', <it>.Tree)
253else
254  Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor, 'token <it>', nil);}; separator="\n">
255<referencedRuleListLabels
256    :{Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor, 'token <it>', list_<it>);};
257    separator="\n"
258>
259>>
260
261/** Generate code for an optional rewrite block; note it uses the deep ref'd element
262  *  list rather shallow like other blocks.
263  */
264rewriteOptionalBlock(
265	alt,rewriteBlockLevel,
266	referencedElementsDeep, // all nested refs
267	referencedElements,     // elements in immediately block; no nested blocks
268	description) ::=
269<<
270(* <fileName>:<description> *)
271if (<referencedElementsDeep:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">) then
272begin
273  <alt>
274end;
275<referencedElementsDeep:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).Reset;<\n>}>
276>>
277
278rewriteClosureBlock(
279	alt,rewriteBlockLevel,
280	referencedElementsDeep, // all nested refs
281	referencedElements,     // elements in immediately block; no nested blocks
282	description) ::=
283<<
284(* <fileName>:<description> *)
285while (<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">) do
286begin
287  <alt>
288end;
289<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).Reset();<\n>}>
290>>
291
292rewritePositiveClosureBlock(
293	alt,rewriteBlockLevel,
294	referencedElementsDeep, // all nested refs
295	referencedElements,     // elements in immediately block; no nested blocks
296	description) ::=
297<<
298if (not (<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">)) then
299  raise ERewriteEarlyExitException.Create('');
300
301while (<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">) do
302begin
303  <alt>
304end;
305<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).Reset();<\n>}>
306>>
307
308rewriteAlt(a) ::= <<
309(* <a.description> *)
310<if(a.pred)>
311if (<a.pred>) then
312begin
313  <a.alt>
314end<\n>
315<else>
316begin
317  <a.alt>
318end;<\n>
319<endif>
320>>
321
322/** For empty rewrites: "r : ... -> ;" */
323rewriteEmptyAlt() ::= "Root[0] = null;"
324
325rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= <<
326(* <fileName>:<description> *)
327begin
328  Root[<treeLevel>] := Adaptor.GetNilNode as I<ASTLabelType>;
329  <root:rewriteElement()>
330  <children:rewriteElement()>
331  Adaptor.AddChild(Root[<enclosingTreeLevel>], Root[<treeLevel>]);
332end;<\n>
333>>
334
335rewriteElementList(elements) ::= "<elements:rewriteElement()>"
336
337rewriteElement(e) ::= <<
338<@pregen()>
339<e.el>
340>>
341
342/** Gen ID or ID[args] */
343rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= <<
344Adaptor.AddChild(Root[<treeLevel>], <createRewriteNodeFromElement(...)>);<\n>
345>>
346
347/** Gen $label ... where defined via label=ID */
348rewriteTokenLabelRef(label,elementIndex) ::= <<
349Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode());<\n>
350>>
351
352/** Gen $label ... where defined via label+=ID */
353rewriteTokenListLabelRef(label,elementIndex) ::= <<
354Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode);<\n>
355>>
356
357/** Gen ^($label ...) */
358rewriteTokenLabelRefRoot(label,elementIndex) ::= <<
359Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode(), Root[<treeLevel>]) as I<ASTLabelType>;<\n>
360>>
361
362/** Gen ^($label ...) where label+=... */
363rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot
364
365/** Gen ^(ID ...) or ^(ID[args] ...) */
366rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= <<
367Root[<treeLevel>] := Adaptor.BecomeRoot(<createRewriteNodeFromElement(...)>, Root[<treeLevel>]) as I<ASTLabelType>;<\n>
368>>
369
370rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= <<
371Adaptor.AddChild(Root[<treeLevel>], <createImaginaryNode(tokenType=token, ...)>);<\n>
372>>
373
374rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= <<
375Root[<treeLevel>] := Adaptor.BecomeRoot(<createImaginaryNode(tokenType=token, ...)>, Root[<treeLevel>]) as I<ASTLabelType>;<\n>
376>>
377
378/** plain -> {foo} action */
379rewriteAction(action) ::= <<
380Root[0] = <action>;<\n>
381>>
382
383/** What is the name of the previous value of this rule's root tree?  This
384 *  let's us refer to $rule to mean previous value.  I am reusing the
385 *  variable 'tree' sitting in retval struct to hold the value of Root[0] right
386 *  before I set it during rewrites.  The assign will be to retval.Tree.
387 */
388prevRuleRootRef() ::= "RetVal"
389
390rewriteRuleRef(rule) ::= <<
391Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<rule>'] as IRewriteRuleElementStream).NextTree());<\n>
392>>
393
394rewriteRuleRefRoot(rule) ::= <<
395Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<rule>'] as IRewriteRuleElementStream).NextNode, Root[<treeLevel>]) as I<ASTLabelType>;<\n>
396>>
397
398rewriteNodeAction(action) ::= <<
399Adaptor.AddChild(Root[<treeLevel>], <action>);<\n>
400>>
401
402rewriteNodeActionRoot(action) ::= <<
403Root[<treeLevel>] := Adaptor.BecomeRoot(<action>, Root[<treeLevel>]) as I<ASTLabelType>;<\n>
404>>
405
406/** Gen $ruleLabel ... where defined via ruleLabel=rule */
407rewriteRuleLabelRef(label) ::= <<
408Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextTree());<\n>
409>>
410
411/** Gen $ruleLabel ... where defined via ruleLabel+=rule */
412rewriteRuleListLabelRef(label) ::= <<
413Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextTree());<\n>
414>>
415
416/** Gen ^($ruleLabel ...) where ruleLabel=rule */
417rewriteRuleLabelRefRoot(label) ::= <<
418Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode, Root[<treeLevel>]) as I<ASTLabelType>;<\n>
419>>
420
421/** Gen ^($ruleLabel ...) where ruleLabel+=rule */
422rewriteRuleListLabelRefRoot(label) ::= <<
423Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode, Root[<treeLevel>]) as I<ASTLabelType>;<\n>
424>>
425
426createImaginaryNode(tokenType,terminalOptions,args) ::= <<
427<if(terminalOptions.node)>
428<! new MethodNode(IDLabel, args) !>
429T<terminalOptions.node>.Create(<tokenType><if(args)>, <args; separator=", "><endif>)
430<else>
431Adaptor.CreateNode(<tokenType>, <args; separator=", "><if(!args)>'<tokenType>'<endif>) as I<ASTLabelType>
432<endif>
433>>
434
435createRewriteNodeFromElement(token,terminalOptions,args) ::= <<
436<if(terminalOptions.node)>
437T<terminalOptions.node>.Create((Locals['Stream_<token>'] as IRewriteRuleElementStream).NextToken<if(args)>, <args; separator=", "><endif>)
438<else>
439<if(args)> <! must create new node from old !>
440Adaptor.Create(<token>, <args; separator=", ">)
441<else>
442(Locals['Stream_<token>'] as IRewriteRuleElementStream).NextNode
443<endif>
444<endif>
445>>
446