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