1/*
2 [The "BSD license"]
3 Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
4 http://www.temporal-wave.com
5 http://www.linkedin.com/in/jimidle
6
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/** Add a variable to track last element matched */
44ruleDeclarations() ::= <<
45<super.ruleDeclarations()>
46<ASTLabelType> _last;<\n>
47<ASTLabelType> _first_0;<\n>
48>>
49
50/** Add a variable to track last element matched */
51ruleInitializations() ::= <<
52<super.ruleInitializations()>
53_last = NULL;<\n>
54_first_0 = NULL;<\n>
55>>
56
57/** What to emit when there is no rewrite rule.  For auto build
58 *  mode, does nothing.
59 */
60noRewrite(rewriteBlockLevel, treeLevel) ::= <<
61<if(backtracking)>if ( BACKTRACKING ==0 ) {<endif>
62<if(rewriteMode)>
63retval.tree = (<ASTLabelType>)_first_0;
64if ( ADAPTOR->getParent(ADAPTOR, retval.tree) != NULL && ADAPTOR->isNilNode(ADAPTOR, ADAPTOR->getParent(ADAPTOR, retval.tree) ) )
65{
66    retval.tree = (<ASTLabelType>)ADAPTOR->getParent(ADAPTOR, retval.tree);
67}
68<endif>
69<if(backtracking)>}<endif>
70>>
71
72/** match ^(root children) in tree parser; override here to
73 *  add tree construction actions.
74 */
75tree(root, actionsAfterRoot, children, nullableChildList,
76     enclosingTreeLevel, treeLevel) ::= <<
77_last = (<ASTLabelType>)LT(1);
78{
79<ASTLabelType> _save_last_<treeLevel>;
80<ASTLabelType> _first_<treeLevel>;
81<if(!rewriteMode)>
82<ASTLabelType> root_<treeLevel>;
83<endif>
84_save_last_<treeLevel> = _last;
85_first_<treeLevel>     = NULL;
86<if(!rewriteMode)>
87root_<treeLevel> = (<ASTLabelType>)(ADAPTOR->nilNode(ADAPTOR));
88<endif>
89<root:element()>
90<if(rewriteMode)>
91<if(backtracking)>if ( BACKTRACKING ==0 ) {<endif>
92<if(root.el.rule)>
93if ( _first_<enclosingTreeLevel> == NULL ) _first_<enclosingTreeLevel> = <root.el.label>.tree;
94<else>
95if ( _first_<enclosingTreeLevel> == NULL ) _first_<enclosingTreeLevel> = <root.el.label>;
96<endif>
97<if(backtracking)>}<endif>
98<endif>
99<actionsAfterRoot:element()>
100<if(nullableChildList)>
101if ( LA(1)==ANTLR3_TOKEN_DOWN ) {
102    MATCHT(ANTLR3_TOKEN_DOWN, NULL);
103    <children:element()>
104    MATCHT(ANTLR3_TOKEN_UP, NULL);
105}
106<else>
107MATCHT(ANTLR3_TOKEN_DOWN, NULL);
108<children:element()>
109MATCHT(ANTLR3_TOKEN_UP, NULL);
110<endif>
111<if(!rewriteMode)>
112ADAPTOR->addChild(ADAPTOR, root_<enclosingTreeLevel>, root_<treeLevel>);
113<endif>
114_last = _save_last_<treeLevel>;
115}<\n>
116>>
117
118// TOKEN AST STUFF
119
120/** ID! and output=AST (same as plain tokenRef) 'cept add
121 *  setting of _last
122 */
123tokenRefBang(token,label,elementIndex,terminalOptions) ::= <<
124_last = (<ASTLabelType>)LT(1);
125<super.tokenRef(...)>
126>>
127
128/** ID auto construct */
129tokenRef(token,label,elementIndex,terminalOptions) ::= <<
130_last = (<ASTLabelType>)LT(1);
131<super.tokenRef(...)>
132<if(!rewriteMode)>
133<if(backtracking)>if ( BACKTRACKING ==0 ) {<endif>
134<if(terminalOptions.node)>
135<label>_tree = <terminalOptions.node>New(<label>);
136<else>
137<label>_tree = (<ASTLabelType>)ADAPTOR->dupNode(ADAPTOR, <label>);
138<endif>
139ADAPTOR->addChild(ADAPTOR, root_<treeLevel>, <label>_tree);
140<if(backtracking)>}<endif>
141<else>
142<if(backtracking)>if ( BACKTRACKING ==0 ) {<endif>
143if ( _first_<treeLevel> == NULL ) _first_<treeLevel> = <label>;
144<if(backtracking)>}<endif>
145<endif>
146>>
147
148/** label+=TOKEN auto construct */
149tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
150<tokenRef(...)>
151<listLabel(elem=label,...)>
152>>
153
154/** ^(ID ...) auto construct */
155tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= <<
156_last = (<ASTLabelType>)LT(1);
157<super.tokenRef(...)>
158<if(!rewriteMode)>
159<if(backtracking)>if ( BACKTRACKING == 0 ) {<endif>
160<if(terminalOptions.node)>
161<label>_tree = <terminalOptions.node>New(<label>);
162<else>
163<label>_tree = (<ASTLabelType>)ADAPTOR->dupNode(ADAPTOR, <label>);
164<endif><\n>
165root_<treeLevel> = (<ASTLabelType>)ADAPTOR->becomeRoot(ADAPTOR, <label>_tree, root_<treeLevel>);
166<if(backtracking)>}<endif>
167<endif>
168>>
169
170/** Match ^(label+=TOKEN ...) auto construct */
171tokenRefRuleRootAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
172<tokenRefRuleRoot(...)>
173<listLabel(elem=label,...)>
174>>
175
176/** Match . wildcard and auto dup the node/subtree */
177wildcard(token,label,elementIndex,terminalOptions) ::= <<
178_last = (<ASTLabelType>)LT(1);
179<super.wildcard(...)>
180<if(!rewriteMode)>
181<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif>
182<label>_tree = (<ASTLabelType>)ADAPTOR->dupTree(ADAPTOR, <label>);
183ADAPTOR->addChild(ADAPTOR, root_<treeLevel>, <label>_tree);
184<if(backtracking)>}<endif>
185<else> <! rewrite mode !>
186<if(backtracking)>if ( <actions.(actionScope).synpredgate> )<endif>
187if ( _first_<treeLevel>==null ) _first_<treeLevel> = <label>;
188<endif>
189>>
190
191// SET AST
192
193matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
194_last = (<ASTLabelType>)LT(1);
195<super.matchSet(postmatchCode={
196<if(!rewriteMode)>
197<if(backtracking)>if ( BACKTRACKING == 0 ) {<endif>
198<if(terminalOptions.node)>
199<label>_tree = <terminalOptions.node>New(<label>);
200<else>
201<label>_tree = (<ASTLabelType>)ADAPTOR->dupNode(ADAPTOR, <label>);
202<endif><\n>
203ADAPTOR->addChild(ADAPTOR, root_<treeLevel>, <label>_tree);
204<if(backtracking)>\}<endif>
205<endif>
206}
207,...)>
208>>
209
210matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= <<
211<matchSet(...)>
212<noRewrite()> <! set return tree !>
213>>
214
215matchSetBang(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
216_last = (<ASTLabelType>)LT(1);
217<super.matchSet(...)>
218>>
219
220matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= <<
221<super.matchSet(postmatchCode={
222<if(!rewriteMode)>
223<if(backtracking)>if ( <actions.(actionScope).synpredgate> ){<endif>
224<if(terminalOptions.node)>
225<label>_tree = <terminalOptions.node>New(<label>);
226<else>
227<label>_tree = (<ASTLabelType>)ADAPTOR->dupNode(ADAPTOR, <label>);
228<endif>
229root_<treeLevel> = (<ASTLabelType>)ADAPTOR->becomeRoot(ADAPTOR, <label>_tree, root_<treeLevel>);
230<if(backtracking)>\}<endif>
231<endif>
232}, ...
233)>
234>>
235
236// RULE REF AST
237
238/** rule auto construct */
239ruleRef(rule,label,elementIndex,args,scope) ::= <<
240_last = (<ASTLabelType>)LT(1);
241<super.ruleRef(...)>
242<if(backtracking)>if ( <actions.(actionScope).synpredgate> )
243{
244<endif>
245<if(!rewriteMode)>
246	ADAPTOR->addChild(ADAPTOR, root_<treeLevel>, <label>.tree);
247<else>
248	if ( _first_<treeLevel> == NULL ) _first_<treeLevel> = <label>.tree;
249<endif>
250<if(backtracking)>}<endif>
251>>
252
253/** x+=rule auto construct */
254ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= <<
255<ruleRef(...)>
256<super.listLabelAST(elem=label,...)>
257>>
258
259/** ^(rule ...) auto construct */
260ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= <<
261_last = (<ASTLabelType>)LT(1);
262<super.ruleRef(...)>
263<if(!rewriteMode)>
264<if(backtracking)>if ( ( <actions.(actionScope).synpredgate> ) ) <endif>root_<treeLevel> = (<ASTLabelType>)(ADAPTOR->becomeRoot(ADAPTOR, <label>.tree, root_<treeLevel>));
265<endif>
266>>
267
268/** ^(x+=rule ...) auto construct */
269ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= <<
270<ruleRefRuleRoot(...)>
271<super.listLabelAST(elem=label,...)>
272>>
273
274/** rule when output=AST and tracking for rewrite */
275ruleRefTrack(rule,label,elementIndex,args,scope) ::= <<
276_last = (<ASTLabelType>)LT(1);
277<super.ruleRefTrack(...)>
278>>
279
280/** x+=rule when output=AST and tracking for rewrite */
281ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
282_last = (<ASTLabelType>)LT(1);
283<super.ruleRefTrackAndListLabel(...)>
284>>
285/** ^(rule ...) rewrite */
286ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= <<
287_last = (<ASTLabelType>)LT(1);
288<super.ruleRefRootTrack(...)>
289>>
290
291/** ^(x+=rule ...) rewrite */
292ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
293_last = (<ASTLabelType>)LT(1);
294<super.ruleRefRuleRootTrackAndListLabel(...)>
295>>
296
297
298/** Streams for token refs are tree nodes now; override to
299 *  change nextToken to nextNode.
300 */
301createRewriteNodeFromElement(token,terminalOptions,scope) ::= <<
302<if(terminalOptions.node)>
303<terminalOptions.node>New(stream_<token>->nextNode(stream_<token>))
304<else>
305stream_<token>->nextNode(stream_<token>)
306<endif>
307>>
308
309ruleCleanUp() ::= <<
310<super.ruleCleanUp(...)>
311<if(backtracking)>
312if ( <actions.(actionScope).synpredgate> ) {<\n>
313<endif>
314<if(!ruleDescriptor.isSynPred)>
315	retval.stop = LT(-1);<\n>
316<endif>
317	retval.tree = (<ASTLabelType>)ADAPTOR->rulePostProcessing(ADAPTOR, root_0);
318<if(backtracking)>
319}
320<endif>
321<ruleDescriptor.allTokenRefsInAltsWithRewrites
322    :{if (stream_<it> != NULL) stream_<it>->free(stream_<it>);}; separator="\n">
323<ruleDescriptor.allRuleRefsInAltsWithRewrites
324    :{if (stream_<it> != NULL) stream_<it>->free(stream_<it>);}; separator="\n">
325>>
326