ASTTreeParser.stg revision 324c4644fee44b9898524c09511bd33c3f12e2df
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/** Templates for building ASTs during tree parsing.
33 *
34 *  Deal with many combinations.  Dimensions are:
35 *  Auto build or rewrite
36 *    no label, label, list label  (label/no-label handled together)
37 *    child, root
38 *    token, set, rule, wildcard
39 *
40 *  Each combination has its own template except that label/no label
41 *  is combined into tokenRef, ruleRef, ...
42 */
43
44/** Add a variable to track last element matched */
45ruleDeclarations() ::= <<
46<super.ruleDeclarations()>
47<ASTLabelType> _first_0 = default(<ASTLabelType>);
48<ASTLabelType> _last = default(<ASTLabelType>);<\n>
49>>
50
51/** What to emit when there is no rewrite rule.  For auto build
52 *  mode, does nothing.
53 */
54noRewrite(rewriteBlockLevel, treeLevel) ::= <<
55<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
56<if(rewriteMode)>
57retval.Tree = (<ASTLabelType>)_first_0;
58if (adaptor.GetParent(retval.Tree)!=null && adaptor.IsNil(adaptor.GetParent(retval.Tree)))
59    retval.Tree = (<ASTLabelType>)adaptor.GetParent(retval.Tree);
60<endif>
61<if(backtracking)>}<endif>
62>>
63
64/** match ^(root children) in tree parser; override here to
65 *  add tree construction actions.
66 */
67tree(root, actionsAfterRoot, children, nullableChildList,
68     enclosingTreeLevel, treeLevel) ::= <<
69_last = (<ASTLabelType>)input.LT(1);
70{
71<ASTLabelType> _save_last_<treeLevel> = _last;
72<ASTLabelType> _first_<treeLevel> = default(<ASTLabelType>);
73<if(!rewriteMode)>
74<ASTLabelType> root_<treeLevel> = (<ASTLabelType>)adaptor.Nil();
75<endif>
76<root:element()>
77<if(rewriteMode)>
78<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif>
79<if(root.el.rule)>
80if (_first_<enclosingTreeLevel> == null) _first_<enclosingTreeLevel> = <root.el.label>.Tree;
81<else>
82if (_first_<enclosingTreeLevel> == null) _first_<enclosingTreeLevel> = <root.el.label>;
83<endif>
84<endif>
85<actionsAfterRoot:element()>
86<if(nullableChildList)>
87if (input.LA(1) == TokenTypes.Down) {
88    Match(input, TokenTypes.Down, null); <checkRuleBacktrackFailure()>
89    <children:element()>
90    Match(input, TokenTypes.Up, null); <checkRuleBacktrackFailure()>
91}
92<else>
93Match(input, TokenTypes.Down, null); <checkRuleBacktrackFailure()>
94<children:element()>
95Match(input, TokenTypes.Up, null); <checkRuleBacktrackFailure()>
96<endif>
97<if(!rewriteMode)>
98adaptor.AddChild(root_<enclosingTreeLevel>, root_<treeLevel>);
99<endif>
100_last = _save_last_<treeLevel>;
101}<\n>
102>>
103
104// TOKEN AST STUFF
105
106/** ID! and output=AST (same as plain tokenRef) 'cept add
107 *  setting of _last
108 */
109tokenRefBang(token,label,elementIndex,terminalOptions) ::= <<
110_last = (<ASTLabelType>)input.LT(1);
111<super.tokenRef(...)>
112>>
113
114/** ID auto construct */
115tokenRef(token,label,elementIndex,terminalOptions) ::= <<
116_last = (<ASTLabelType>)input.LT(1);
117<super.tokenRef(...)>
118<if(!rewriteMode)>
119<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
120<if(terminalOptions.node)>
121<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
122<else>
123<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
124<endif><\n>
125adaptor.AddChild(root_<treeLevel>, <label>_tree);
126<if(backtracking)>}<endif>
127<else> <! rewrite mode !>
128<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif>
129if (_first_<treeLevel> == null) _first_<treeLevel> = <label>;
130<endif>
131>>
132
133/** label+=TOKEN auto construct */
134tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
135<tokenRef(...)>
136<listLabelElem(elem=label,...)>
137>>
138
139/** ^(ID ...) auto construct */
140tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= <<
141_last = (<ASTLabelType>)input.LT(1);
142<super.tokenRef(...)>
143<if(!rewriteMode)>
144<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
145<if(terminalOptions.node)>
146<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
147<else>
148<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
149<endif><\n>
150root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<label>_tree, root_<treeLevel>);
151<if(backtracking)>}<endif>
152<endif>
153>>
154
155/** Match ^(label+=TOKEN ...) auto construct */
156tokenRefRuleRootAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
157<tokenRefRuleRoot(...)>
158<listLabelElem(elem=label,...)>
159>>
160
161/** Match . wildcard and auto dup the node/subtree */
162wildcard(token,label,elementIndex,terminalOptions) ::= <<
163_last = (<ASTLabelType>)input.LT(1);
164<super.wildcard(...)>
165<if(!rewriteMode)>
166<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
167<label>_tree = (<ASTLabelType>)adaptor.DupTree(<label>);
168adaptor.AddChild(root_<treeLevel>, <label>_tree);
169<if(backtracking)>}<endif>
170<else> <! rewrite mode !>
171<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif>
172if (_first_<treeLevel> == null) _first_<treeLevel> = <label>;
173<endif>
174>>
175
176// SET AST
177
178matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
179_last = (<ASTLabelType>)input.LT(1);
180<super.matchSet(postmatchCode={
181<if(!rewriteMode)>
182<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
183<if(terminalOptions.node)>
184<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
185<else>
186<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
187<endif><\n>
188adaptor.AddChild(root_<treeLevel>, <label>_tree);
189<if(backtracking)>\}<endif>
190<endif>
191}, ...
192)>
193>>
194
195matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= <<
196<matchSet(...)>
197<noRewrite(...)> <! set return tree !>
198>>
199
200matchSetBang(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
201_last = (<ASTLabelType>)input.LT(1);
202<super.matchSet(...)>
203>>
204
205matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= <<
206<super.matchSet(postmatchCode={
207<if(!rewriteMode)>
208<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
209<if(terminalOptions.node)>
210<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
211<else>
212<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>);
213<endif><\n>
214root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<label>_tree, root_<treeLevel>);
215<if(backtracking)>\}<endif>
216<endif>
217}, ...
218)>
219>>
220
221// RULE REF AST
222
223/** rule auto construct */
224ruleRef(rule,label,elementIndex,args,scope) ::= <<
225_last = (<ASTLabelType>)input.LT(1);
226<super.ruleRef(...)>
227<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif>
228<if(!rewriteMode)>
229adaptor.AddChild(root_<treeLevel>, <label>.Tree);
230<else> <! rewrite mode !>
231if (_first_<treeLevel> == null) _first_<treeLevel> = <label>.Tree;
232<endif>
233>>
234
235/** x+=rule auto construct */
236ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= <<
237<ruleRef(...)>
238<listLabelElem(elem={<label>.Tree},...)>
239>>
240
241/** ^(rule ...) auto construct */
242ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= <<
243_last = (<ASTLabelType>)input.LT(1);
244<super.ruleRef(...)>
245<if(!rewriteMode)>
246<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<label>.Tree, root_<treeLevel>);
247<endif>
248>>
249
250/** ^(x+=rule ...) auto construct */
251ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= <<
252<ruleRefRuleRoot(...)>
253<listLabelElem(elem={<label>.Tree},...)>
254>>
255
256/** rule when output=AST and tracking for rewrite */
257ruleRefTrack(rule,label,elementIndex,args,scope) ::= <<
258_last = (<ASTLabelType>)input.LT(1);
259<super.ruleRefTrack(...)>
260>>
261
262/** x+=rule when output=AST and tracking for rewrite */
263ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
264_last = (<ASTLabelType>)input.LT(1);
265<super.ruleRefTrackAndListLabel(...)>
266>>
267
268/** ^(rule ...) rewrite */
269ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= <<
270_last = (<ASTLabelType>)input.LT(1);
271<super.ruleRefRootTrack(...)>
272>>
273
274/** ^(x+=rule ...) rewrite */
275ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
276_last = (<ASTLabelType>)input.LT(1);
277<super.ruleRefRuleRootTrackAndListLabel(...)>
278>>
279
280/** Streams for token refs are tree nodes now; override to
281 *  change NextToken to NextNode.
282 */
283createRewriteNodeFromElement(token,terminalOptions,args) ::= <%
284<if(terminalOptions.node)>
285new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif>stream_<token>.NextNode())
286<else>
287stream_<token>.NextNode()
288<endif>
289%>
290
291ruleCleanUp() ::= <<
292<super.ruleCleanUp()>
293<if(!rewriteMode)>
294<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
295retval.Tree = (<ASTLabelType>)adaptor.RulePostProcessing(root_0);
296<if(backtracking)>}<endif>
297<endif>
298>>
299