1/*
2 [The "BSD license"]
3 Copyright (c) 2008 Erik van Bilsen
4 Copyright (c) 2007-2008 Johannes Luber
5 Copyright (c) 2005-2007 Kunle Odutola
6 Copyright (c) 2005-2006 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 normal 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 *  The situation is not too bad as rewrite (->) usage makes ^ and !
41 *  invalid. There is no huge explosion of combinations.
42 */
43group ASTParser;
44
45@rule.setErrorReturnValue() ::= <<
46RetVal.Tree := Adaptor.ErrorNode(Input, RetVal.Start as IToken,
47  Input.LT(-1), RE) as I<ASTLabelType>;
48>>
49
50// TOKEN AST STUFF
51
52/** ID and output=AST */
53tokenRef(token,label,elementIndex,terminalOptions) ::= <<
54<super.tokenRef(...)>
55<if(backtracking)>
56if (State.Backtracking = 0) then
57begin<\n>
58<endif>
59<label>_tree := <createNodeFromToken(...)>;
60Adaptor.AddChild(Root[0], <label>_tree);
61<if(backtracking)>
62end;
63<endif>
64>>
65
66/** ID! and output=AST (same as plain tokenRef) */
67tokenRefBang(token,label,elementIndex) ::= "<super.tokenRef(...)>"
68
69/** ID^ and output=AST */
70tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= <<
71<super.tokenRef(...)>
72<if(backtracking)>
73if (State.Backtracking = 0) then
74begin
75<endif>
76<label>_tree := <createNodeFromToken(...)>;
77Root[0] := Adaptor.BecomeRoot(<label>_tree, Root[0]) as I<ASTLabelType>;
78<if(backtracking)>
79end;
80<endif>
81>>
82
83/** ids+=ID! and output=AST */
84tokenRefBangAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
85<tokenRefBang(...)>
86<listLabel(elem=label,...)>
87>>
88
89/** label+=TOKEN when output=AST but not rewrite alt */
90tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
91<tokenRef(...)>
92<listLabel(elem=label,...)>
93>>
94
95/** Match label+=TOKEN^ when output=AST but not rewrite alt */
96tokenRefRuleRootAndListLabel(token,label,terminalOptions,elementIndex) ::= <<
97<tokenRefRuleRoot(...)>
98<listLabel(elem=label,...)>
99>>
100
101// SET AST
102
103// the match set stuff is interesting in that it uses an argument list
104// to pass code to the default matchSet; another possible way to alter
105// inherited code.  I don't use the region stuff because I need to pass
106// different chunks depending on the operator.  I don't like making
107// the template name have the operator as the number of templates gets
108// large but this is the most flexible--this is as opposed to having
109// the code generator call matchSet then add root code or ruleroot code
110// plus list label plus ...  The combinations might require complicated
111// rather than just added on code.  Investigate that refactoring when
112// I have more time.
113
114matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
115<super.matchSet(..., postmatchCode={<if(backtracking)>if (State.Backtracking = 0) then <endif>Adaptor.AddChild(Root[0], <createNodeFromToken(...)>);})>
116>>
117
118matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= <<
119<matchSet(...)>
120>>
121
122matchSetBang(s,label,elementIndex,postmatchCode) ::= "<super.matchSet(...)>"
123
124// note there is no matchSetTrack because -> rewrites force sets to be
125// plain old blocks of alts: (A|B|...|C)
126
127matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= <<
128<if(label)>
129<label> := Input.LT(1) as I<labelType>;<\n>
130<endif>
131<super.matchSet(..., postmatchCode={<if(backtracking)>if (State.Backtracking = 0) then <endif>Root[0] := Adaptor.BecomeRoot(<createNodeFromToken(...)>, Root[0]) as I<ASTLabelType>;})>
132>>
133
134// RULE REF AST
135
136/** rule when output=AST */
137ruleRef(rule,label,elementIndex,args,scope) ::= <<
138<super.ruleRef(...)>
139<if(backtracking)>if (State.Backtracking = 0) then <endif>Adaptor.AddChild(Root[0], <label>.Tree);
140>>
141
142/** rule! is same as normal rule ref */
143ruleRefBang(rule,label,elementIndex,args,scope) ::= "<super.ruleRef(...)>"
144
145/** rule^ */
146ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= <<
147<super.ruleRef(...)>
148<if(backtracking)>if (State.Backtracking = 0) then <endif>Root[0] := Adaptor.BecomeRoot(<label>.Tree, Root[0]) as I<ASTLabelType>;
149>>
150
151/** x+=rule when output=AST */
152ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= <<
153<ruleRef(...)>
154<listLabel(elem=label+".Tree",...)>
155>>
156
157/** x+=rule! when output=AST is a rule ref with list addition */
158ruleRefBangAndListLabel(rule,label,elementIndex,args,scope) ::= <<
159<ruleRefBang(...)>
160<listLabel(elem=label+".Tree",...)>
161>>
162
163/** x+=rule^ */
164ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= <<
165<ruleRefRuleRoot(...)>
166<listLabel(elem=label+".Tree",...)>
167>>
168
169// WILDCARD AST
170
171wildcard(label,elementIndex) ::= <<
172<super.wildcard(...)>
173<if(backtracking)>
174if (State.Backtracking = 0) then
175begin
176<endif>
177	<label>_tree := Adaptor.CreateNode(<label>) as I<ASTLabelType>;
178	Adaptor.AddChild(Root[0], <label>_tree);
179<if(backtracking)>
180end;
181<endif>
182>>
183
184wildcardBang(label,elementIndex) ::= "<super.wildcard(...)>"
185
186wildcardRuleRoot(label,elementIndex) ::= <<
187<super.wildcard(...)>
188<if(backtracking)>
189if (State.Backtracking = 0) then
190begin
191<endif>
192	<label>_tree := Adaptor.CreateNode(<label>) as I<ASTLabelType>;
193	Root[0] := Adaptor.BecomeRoot(<label>_tree, Root[0]) as I<ASTLabelType>;
194<if(backtracking)>
195end;
196<endif>
197>>
198
199createNodeFromToken(label,terminalOptions) ::= <<
200<if(terminalOptions.node)>
201T<terminalOptions.node>.Create(<label>) <! new MethodNode(IDLabel) !>
202<else>
203Adaptor.CreateNode(<label>) as I<ASTLabelType>
204<endif>
205>>
206
207ruleCleanUp() ::= <<
208<super.ruleCleanUp()>
209<if(backtracking)>
210if (State.Backtracking = 0) then
211begin<\n>
212<endif>
213RetVal.Tree := Adaptor.RulePostProcessing(Root[0]) as I<ASTLabelType>;
214<if(!TREE_PARSER)>
215Adaptor.SetTokenBoundaries(RetVal.Tree, RetVal.Start as IToken, RetVal.Stop as IToken);
216<endif>
217<if(backtracking)>
218<\n>end;
219<endif>
220>>
221