1/*
2 * [The "BSD license"]
3 * Copyright (c) 2007-2008 Johannes Luber
4 * Copyright (c) 2005-2007 Kunle Odutola
5 * Copyright (c) 2011 Sam Harwell
6 * Copyright (c) 2011 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 */
31
32@outputFile.imports() ::= <<
33<@super.imports()>
34
35<if(!TREE_PARSER)>
36<! tree parser would already have imported !>
37using Antlr.Runtime.Tree;
38using RewriteRuleITokenStream = Antlr.Runtime.Tree.RewriteRuleTokenStream;
39<endif>
40>>
41
42@genericParser.members() ::= <<
43<@super.members()>
44<parserMembers()>
45>>
46
47parserCtorBody() ::= <%
48<super.parserCtorBody()><\n>
49TreeAdaptor =
50<if(actions.(actionScope).treeAdaptorInitializer)>
51	<actions.(actionScope).treeAdaptorInitializer>
52<else>
53	new <actions.(actionScope).treeAdaptorType; null="CommonTreeAdaptor">()
54<end>
55;
56%>
57
58/** Add an adaptor property that knows how to build trees */
59parserMembers() ::= <<
60private <treeAdaptorType()> adaptor;
61
62public <treeAdaptorType()> TreeAdaptor
63{
64	get
65	{
66		return adaptor;
67	}
68
69	set
70	{
71		this.adaptor = value;
72		<grammar.directDelegates:{g|<g:delegateName()>.TreeAdaptor = this.adaptor;}>
73	}
74}
75>>
76
77treeAdaptorType() ::= <<
78<actions.(actionScope).treeAdaptorType; null="ITreeAdaptor">
79>>
80
81ruleReturnBaseType() ::= <%
82Ast<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope\<<ASTLabelType>, <labelType>>
83%>
84
85/** Add a variable to track rule's return AST */
86ruleDeclarations() ::= <<
87<super.ruleDeclarations()>
88<ASTLabelType> root_0 = default(<ASTLabelType>);<\n>
89>>
90
91ruleLabelDefs() ::= <<
92<super.ruleLabelDefs()>
93<[ruleDescriptor.tokenLabels,ruleDescriptor.wildcardTreeLabels,ruleDescriptor.wildcardTreeListLabels]
94	:{it|<ASTLabelType> <it.label.text>_tree = default(<ASTLabelType>);}; separator="\n">
95<ruleDescriptor.tokenListLabels:{it|<ASTLabelType> <it.label.text>_tree = default(<ASTLabelType>);}; separator="\n">
96<ruleDescriptor.allTokenRefsInAltsWithRewrites
97	:{it|RewriteRule<rewriteElementType>Stream stream_<it>=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>");}; separator="\n">
98<ruleDescriptor.allRuleRefsInAltsWithRewrites
99	:{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"rule <it>");}; separator="\n">
100>>
101
102/** When doing auto AST construction, we must define some variables;
103 *  These should be turned off if doing rewrites.  This must be a "mode"
104 *  as a rule could have both rewrite and AST within the same alternative
105 *  block.
106 */
107@alt.declarations() ::= <<
108<if(autoAST)>
109<if(outerAlt)>
110<if(!rewriteMode)>
111root_0 = (<ASTLabelType>)adaptor.Nil();
112<endif>
113<endif>
114<endif>
115>>
116
117// T r a c k i n g  R u l e  E l e m e n t s
118
119/** ID and track it for use in a rewrite rule */
120tokenRefTrack(token,label,elementIndex,terminalOptions) ::= <<
121<tokenRefBang(...)> <! Track implies no auto AST construction!>
122<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<token>.Add(<label>);<\n>
123>>
124
125/** ids+=ID and track it for use in a rewrite rule; adds to ids *and*
126 *  to the tracking list stream_ID for use in the rewrite.
127 */
128tokenRefTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
129<tokenRefTrack(...)>
130<listLabelElem(elem=label,elemType=labelType,...)>
131>>
132
133/** ^(ID ...) track for rewrite */
134tokenRefRuleRootTrack(token,label,elementIndex,terminalOptions) ::= <<
135<tokenRefBang(...)>
136<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<token>.Add(<label>);
137>>
138
139/** Match ^(label+=TOKEN ...) track for rewrite */
140tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
141<tokenRefRuleRootTrack(...)>
142<listLabelElem(elem=label,elemType=labelType,...)>
143>>
144
145/** rule when output=AST and tracking for rewrite */
146ruleRefTrack(rule,label,elementIndex,args,scope) ::= <<
147<super.ruleRef(...)>
148<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<rule.name>.Add(<label>.Tree);
149>>
150
151/** x+=rule when output=AST and tracking for rewrite */
152ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
153<ruleRefTrack(...)>
154<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)>
155>>
156
157/** ^(rule ...) rewrite */
158ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= <<
159<ruleRefRuleRoot(...)>
160<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<rule>.Add(<label>.Tree);
161>>
162
163/** ^(x+=rule ...) rewrite */
164ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
165<ruleRefRuleRootTrack(...)>
166<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)>
167>>
168
169// R e w r i t e
170
171rewriteCode(
172	alts, description,
173	referencedElementsDeep, // ALL referenced elements to right of ->
174	referencedTokenLabels,
175	referencedTokenListLabels,
176	referencedRuleLabels,
177	referencedRuleListLabels,
178	referencedWildcardLabels,
179	referencedWildcardListLabels,
180	rewriteBlockLevel, enclosingTreeLevel, treeLevel) ::= <<
181<\n>{
182// AST REWRITE
183// elements: <referencedElementsDeep; separator=", ">
184// token labels: <referencedTokenLabels; separator=", ">
185// rule labels: <referencedRuleLabels; separator=", ">
186// token list labels: <referencedTokenListLabels; separator=", ">
187// rule list labels: <referencedRuleListLabels; separator=", ">
188// wildcard labels: <[referencedWildcardLabels,referencedWildcardListLabels]; separator=", ">
189<if(backtracking)>
190if (<actions.(actionScope).synpredgate>) {
191<endif>
192<prevRuleRootRef()>.Tree = root_0;
193<rewriteCodeLabels()>
194root_0 = (<ASTLabelType>)adaptor.Nil();
195<alts:rewriteAlt(); separator="else ">
196<! if tree parser and rewrite=true !>
197<if(TREE_PARSER&&rewriteMode)>
198<prevRuleRootRef()>.Tree = (<ASTLabelType>)adaptor.RulePostProcessing(root_0);
199input.ReplaceChildren(adaptor.GetParent(retval.Start),
200                      adaptor.GetChildIndex(retval.Start),
201                      adaptor.GetChildIndex(_last),
202                      retval.Tree);
203<endif>
204<! if parser or tree-parser && rewrite!=true, we need to set result !>
205<if(!TREE_PARSER||!rewriteMode)>
206<prevRuleRootRef()>.Tree = root_0;
207<endif>
208<if(backtracking)>
209}
210<endif>
211}
212
213>>
214
215rewriteCodeLabels() ::= <<
216<referencedTokenLabels
217    :{it|RewriteRule<rewriteElementType>Stream stream_<it>=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>",<it>);};
218    separator="\n"
219>
220<referencedTokenListLabels
221    :{it|RewriteRule<rewriteElementType>Stream stream_<it>=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>", list_<it>);};
222    separator="\n"
223>
224<referencedWildcardLabels
225	:{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"wildcard <it>",<it>);};
226	separator="\n"
227>
228<referencedWildcardListLabels
229	:{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"wildcard <it>",list_<it>);};
230	separator="\n"
231>
232<referencedRuleLabels
233    :{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"rule <it>",<it>!=null?<it>.Tree:null);};
234    separator="\n"
235>
236<referencedRuleListLabels
237    :{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"token <it>",list_<it>);};
238    separator="\n"
239>
240>>
241
242/** Generate code for an optional rewrite block; note it uses the deep ref'd element
243  *  list rather shallow like other blocks.
244  */
245rewriteOptionalBlock(
246	alt,rewriteBlockLevel,
247	referencedElementsDeep, // all nested refs
248	referencedElements, // elements in immediately block; no nested blocks
249	description) ::=
250<<
251// <fileName>:<description>
252if (<referencedElementsDeep:{el | stream_<el>.HasNext}; separator="||">)
253{
254	<alt>
255}
256<referencedElementsDeep:{el | stream_<el>.Reset();<\n>}>
257>>
258
259rewriteClosureBlock(
260	alt,rewriteBlockLevel,
261	referencedElementsDeep, // all nested refs
262	referencedElements, // elements in immediately block; no nested blocks
263	description) ::=
264<<
265// <fileName>:<description>
266while ( <referencedElements:{el | stream_<el>.HasNext}; separator="||"> )
267{
268	<alt>
269}
270<referencedElements:{el | stream_<el>.Reset();<\n>}>
271>>
272
273rewritePositiveClosureBlock(
274	alt,rewriteBlockLevel,
275	referencedElementsDeep, // all nested refs
276	referencedElements, // elements in immediately block; no nested blocks
277	description) ::=
278<<
279if (!(<referencedElements:{el | stream_<el>.HasNext}; separator="||">))
280{
281	throw new RewriteEarlyExitException();
282}
283while ( <referencedElements:{el | stream_<el>.HasNext}; separator="||"> )
284{
285	<alt>
286}
287<referencedElements:{el | stream_<el>.Reset();<\n>}>
288>>
289
290rewriteAlt(a) ::= <<
291// <a.description>
292<if(a.pred)>
293if (<a.pred>)
294{
295	<a.alt>
296}
297<else>
298{
299	<a.alt>
300}
301<endif>
302>>
303
304/** For empty rewrites: "r : ... -> ;" */
305rewriteEmptyAlt() ::= "root_0 = null;"
306
307rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= <<
308// <fileName>:<description>
309{
310<ASTLabelType> root_<treeLevel> = (<ASTLabelType>)adaptor.Nil();
311<root:rewriteElement()>
312<children:rewriteElement()>
313adaptor.AddChild(root_<enclosingTreeLevel>, root_<treeLevel>);
314}<\n>
315>>
316
317rewriteElementList(elements) ::= "<elements:rewriteElement()>"
318
319rewriteElement(e) ::= <%
320<@pregen()>
321DebugLocation(<e.line>, <e.pos>);<\n>
322<e.el>
323%>
324
325/** Gen ID or ID[args] */
326rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= <<
327adaptor.AddChild(root_<treeLevel>, <createRewriteNodeFromElement(...)>);<\n>
328>>
329
330/** Gen $label ... where defined via label=ID */
331rewriteTokenLabelRef(label,elementIndex) ::= <<
332adaptor.AddChild(root_<treeLevel>, stream_<label>.NextNode());<\n>
333>>
334
335/** Gen $label ... where defined via label+=ID */
336rewriteTokenListLabelRef(label,elementIndex) ::= <<
337adaptor.AddChild(root_<treeLevel>, stream_<label>.NextNode());<\n>
338>>
339
340/** Gen ^($label ...) */
341rewriteTokenLabelRefRoot(label,elementIndex) ::= <<
342root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<label>.NextNode(), root_<treeLevel>);<\n>
343>>
344
345/** Gen ^($label ...) where label+=... */
346rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot
347
348/** Gen ^(ID ...) or ^(ID[args] ...) */
349rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= <<
350root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<createRewriteNodeFromElement(...)>, root_<treeLevel>);<\n>
351>>
352
353rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= <<
354adaptor.AddChild(root_<treeLevel>, <createImaginaryNode(tokenType=token, ...)>);<\n>
355>>
356
357rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= <<
358root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<createImaginaryNode(tokenType=token, ...)>, root_<treeLevel>);<\n>
359>>
360
361/** plain -> {foo} action */
362rewriteAction(action) ::= <<
363root_0 = <action>;<\n>
364>>
365
366/** What is the name of the previous value of this rule's root tree?  This
367 *  let's us refer to $rule to mean previous value.  I am reusing the
368 *  variable 'tree' sitting in retval struct to hold the value of root_0 right
369 *  before I set it during rewrites.  The assign will be to retval.tree.
370 */
371prevRuleRootRef() ::= "retval"
372
373rewriteRuleRef(rule) ::= <<
374adaptor.AddChild(root_<treeLevel>, stream_<rule>.NextTree());<\n>
375>>
376
377rewriteRuleRefRoot(rule) ::= <<
378root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<rule>.NextNode(), root_<treeLevel>);<\n>
379>>
380
381rewriteNodeAction(action) ::= <<
382adaptor.AddChild(root_<treeLevel>, <action>);<\n>
383>>
384
385rewriteNodeActionRoot(action) ::= <<
386root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<action>, root_<treeLevel>);<\n>
387>>
388
389/** Gen $ruleLabel ... where defined via ruleLabel=rule */
390rewriteRuleLabelRef(label) ::= <<
391adaptor.AddChild(root_<treeLevel>, stream_<label>.NextTree());<\n>
392>>
393
394/** Gen $ruleLabel ... where defined via ruleLabel+=rule */
395rewriteRuleListLabelRef(label) ::= <<
396adaptor.AddChild(root_<treeLevel>, stream_<label>.NextTree());<\n>
397>>
398
399/** Gen ^($ruleLabel ...) where ruleLabel=rule */
400rewriteRuleLabelRefRoot(label) ::= <<
401root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<label>.NextNode(), root_<treeLevel>);<\n>
402>>
403
404/** Gen ^($ruleLabel ...) where ruleLabel+=rule */
405rewriteRuleListLabelRefRoot(label) ::= <<
406root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<label>.NextNode(), root_<treeLevel>);<\n>
407>>
408
409rewriteWildcardLabelRef(label) ::= <<
410adaptor.AddChild(root_<treeLevel>, stream_<label>.NextTree());<\n>
411>>
412
413createImaginaryNode(tokenType,terminalOptions,args) ::= <%
414<if(terminalOptions.node)>
415<! new MethodNode(IDLabel, args) !>
416new <terminalOptions.node>(<tokenType><if(args)>, <args; separator=", "><endif>)
417<else>
418(<ASTLabelType>)adaptor.Create(<tokenType>, <args; separator=", "><if(!args)>"<tokenType>"<endif>)
419<endif>
420%>
421
422createRewriteNodeFromElement(token,terminalOptions,args) ::= <%
423<if(terminalOptions.node)>
424new <terminalOptions.node>(stream_<token>.NextToken()<if(args)>, <args; separator=", "><endif>)
425<else>
426<if(args)> <! must create new node from old !>
427adaptor.Create(<token>, <args; separator=", ">)
428<else>
429stream_<token>.NextNode()
430<endif>
431<endif>
432%>
433