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