1 /***
2 *
3 * Copyright 2005 Jeremy Rayner
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.codehaus.groovy.antlr.treewalker;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22
23 import org.codehaus.groovy.antlr.GroovySourceAST;
24 import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
25
26 /***
27 * A treewalker for the antlr generated AST that attempts to visit the
28 * AST nodes in the order needed to generate valid groovy source code.
29 *
30 * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
31 * @version $Revision: 4538 $
32 */
33 public class SourceCodeTraversal extends TraversalHelper {
34 /***
35 * Constructs a treewalker for the antlr generated AST that attempts to visit the
36 * AST nodes in the order needed to generate valid groovy source code.
37 * @param visitor the visitor implementation to call for each AST node.
38 */
39 public SourceCodeTraversal(Visitor visitor) {
40 super(visitor);
41 }
42
43 /***
44 * gather, sort and process all unvisited nodes
45 * @param t the AST to process
46 */
47 public void setUp(GroovySourceAST t) {
48 super.setUp(t);
49
50
51 unvisitedNodes = new ArrayList();
52 traverse((GroovySourceAST)t);
53 Collections.sort(unvisitedNodes);
54 }
55
56 /***
57 * traverse an AST node
58 * @param t the AST node to traverse
59 */
60 private void traverse(GroovySourceAST t) {
61 if (t == null) { return; }
62 if (unvisitedNodes != null) {
63 unvisitedNodes.add(t);
64 }
65 GroovySourceAST child = (GroovySourceAST)t.getFirstChild();
66 if (child != null) {
67 traverse(child);
68 }
69 GroovySourceAST sibling = (GroovySourceAST)t.getNextSibling();
70 if (sibling != null) {
71 traverse(sibling);
72 }
73 }
74
75 protected void accept(GroovySourceAST currentNode) {
76 if (currentNode != null && unvisitedNodes != null && unvisitedNodes.size() > 0) {
77 GroovySourceAST t = currentNode;
78
79 if (!(unvisitedNodes.contains(currentNode))) {
80 return;
81 }
82 push(t);
83 switch (t.getType()) {
84 case GroovyTokenTypes.QUESTION:
85 accept_FirstChild_v_SecondChild_v_ThirdChild_v(t);
86 break;
87
88 case GroovyTokenTypes.CASE_GROUP:
89 case GroovyTokenTypes.LITERAL_instanceof:
90 accept_FirstChild_v_SecondChildsChildren_v(t);
91 break;
92
93 case GroovyTokenTypes.ANNOTATION:
94 accept_v_FirstChild_2ndv_SecondChild_v___LastChild_v(t);
95 break;
96
97 case GroovyTokenTypes.ELIST:
98 case GroovyTokenTypes.PARAMETERS:
99 case GroovyTokenTypes.TYPE_ARGUMENTS:
100 case GroovyTokenTypes.STRING_CONSTRUCTOR:
101 case GroovyTokenTypes.TYPE_PARAMETER:
102 case GroovyTokenTypes.TYPE_PARAMETERS:
103 case GroovyTokenTypes.TYPE_UPPER_BOUNDS:
104 accept_v_FirstChild_v_SecondChild_v___LastChild_v(t);
105
106 break;
107
108 case GroovyTokenTypes.VARIABLE_PARAMETER_DEF:
109 accept_v_FirstChild_SecondChild_v_ThirdChild_v(t);
110 break;
111
112 case GroovyTokenTypes.INDEX_OP:
113 accept_FirstChild_v_SecondChild_v(t);
114 break;
115
116 case GroovyTokenTypes.ENUM_CONSTANT_DEF:
117 case GroovyTokenTypes.EXPR:
118 case GroovyTokenTypes.IMPORT:
119 case GroovyTokenTypes.VARIABLE_DEF:
120 case GroovyTokenTypes.METHOD_DEF:
121 case GroovyTokenTypes.OBJBLOCK:
122 case GroovyTokenTypes.PARAMETER_DEF:
123 case GroovyTokenTypes.SLIST:
124 accept_v_AllChildren_v(t);
125 break;
126
127 case GroovyTokenTypes.ANNOTATION_MEMBER_VALUE_PAIR:
128 case GroovyTokenTypes.ASSIGN:
129 case GroovyTokenTypes.BAND_ASSIGN:
130 case GroovyTokenTypes.BOR_ASSIGN:
131 case GroovyTokenTypes.BSR_ASSIGN:
132 case GroovyTokenTypes.BXOR_ASSIGN:
133 case GroovyTokenTypes.COMPARE_TO:
134 case GroovyTokenTypes.DIV_ASSIGN:
135 case GroovyTokenTypes.EQUAL:
136 case GroovyTokenTypes.MINUS_ASSIGN:
137 case GroovyTokenTypes.MOD_ASSIGN:
138 case GroovyTokenTypes.NOT_EQUAL:
139 case GroovyTokenTypes.PLUS_ASSIGN:
140 case GroovyTokenTypes.REGEX_FIND:
141 case GroovyTokenTypes.REGEX_MATCH:
142 case GroovyTokenTypes.SL_ASSIGN:
143 case GroovyTokenTypes.SR_ASSIGN:
144 case GroovyTokenTypes.STAR_ASSIGN:
145 case GroovyTokenTypes.STAR_STAR_ASSIGN:
146 if (t.childAt(1) != null) {
147 accept_FirstChild_v_RestOfTheChildren(t);
148 } else {
149 accept_v_FirstChild_v_RestOfTheChildren(t);
150 }
151 break;
152
153 case GroovyTokenTypes.ANNOTATION_FIELD_DEF:
154 accept_FirstSecondAndThirdChild_v_v_ForthChild(t);
155 break;
156
157 case GroovyTokenTypes.ANNOTATION_DEF:
158 case GroovyTokenTypes.BAND:
159 case GroovyTokenTypes.BOR:
160 case GroovyTokenTypes.BSR:
161 case GroovyTokenTypes.BXOR:
162 case GroovyTokenTypes.CLASS_DEF:
163 case GroovyTokenTypes.CTOR_IDENT:
164 case GroovyTokenTypes.DIV:
165 case GroovyTokenTypes.DOT:
166 case GroovyTokenTypes.ENUM_DEF:
167 case GroovyTokenTypes.GE:
168 case GroovyTokenTypes.GT:
169 case GroovyTokenTypes.INTERFACE_DEF:
170 case GroovyTokenTypes.LABELED_ARG:
171 case GroovyTokenTypes.LABELED_STAT:
172 case GroovyTokenTypes.LAND:
173 case GroovyTokenTypes.LE:
174 case GroovyTokenTypes.LITERAL_as:
175 case GroovyTokenTypes.LITERAL_in:
176 case GroovyTokenTypes.LOR:
177 case GroovyTokenTypes.LT:
178 case GroovyTokenTypes.MEMBER_POINTER:
179 case GroovyTokenTypes.MOD:
180 case GroovyTokenTypes.MINUS:
181 case GroovyTokenTypes.OPTIONAL_DOT:
182 case GroovyTokenTypes.PACKAGE_DEF:
183 case GroovyTokenTypes.PLUS:
184 case GroovyTokenTypes.RANGE_EXCLUSIVE:
185 case GroovyTokenTypes.RANGE_INCLUSIVE:
186 case GroovyTokenTypes.SL:
187 case GroovyTokenTypes.SR:
188 case GroovyTokenTypes.STAR:
189 case GroovyTokenTypes.STAR_STAR:
190 accept_FirstChild_v_RestOfTheChildren(t);
191 break;
192
193 case GroovyTokenTypes.CTOR_CALL:
194 case GroovyTokenTypes.METHOD_CALL:
195 if (t.getNumberOfChildren() == 2 && t.childAt(1) != null && t.childAt(1).getType() == GroovyTokenTypes.CLOSABLE_BLOCK) {
196
197 accept_FirstChild_v_SecondChild(t);
198 } else {
199 GroovySourceAST lastChild = t.childAt(t.getNumberOfChildren() -1);
200 if (lastChild != null && lastChild.getType() == GroovyTokenTypes.CLOSABLE_BLOCK) {
201
202 accept_FirstChild_v_RestOfTheChildren_v_LastChild(t);
203 } else {
204
205 accept_FirstChild_v_RestOfTheChildren_v(t);
206 }
207 }
208 break;
209
210 case GroovyTokenTypes.LITERAL_while:
211 case GroovyTokenTypes.LITERAL_with:
212 case GroovyTokenTypes.TYPECAST:
213 accept_v_FirstChildsFirstChild_v_RestOfTheChildren(t);
214 break;
215
216 case GroovyTokenTypes.LITERAL_if:
217 accept_v_FirstChildsFirstChild_v_Child2_Child3_v_Child4_v___v_LastChild(t);
218 break;
219
220 case GroovyTokenTypes.CLOSABLE_BLOCK:
221 if (t.childAt(0) != null && t.childAt(0).getType() == GroovyTokenTypes.IMPLICIT_PARAMETERS) {
222 accept_v_AllChildren_v(t);
223 } else {
224 accept_v_FirstChild_v_RestOfTheChildren_v(t);
225 }
226 break;
227
228 case GroovyTokenTypes.FOR_IN_ITERABLE:
229 case GroovyTokenTypes.LITERAL_for:
230 case GroovyTokenTypes.LITERAL_new:
231 case GroovyTokenTypes.LITERAL_switch:
232 accept_v_FirstChild_v_RestOfTheChildren_v(t);
233 break;
234
235 case GroovyTokenTypes.ANNOTATIONS:
236 case GroovyTokenTypes.LITERAL_assert:
237 case GroovyTokenTypes.LITERAL_catch:
238 case GroovyTokenTypes.LITERAL_synchronized:
239 case GroovyTokenTypes.LITERAL_try:
240 case GroovyTokenTypes.MODIFIERS:
241 accept_v_FirstChild_v_RestOfTheChildren(t);
242 break;
243
244 default:
245 accept_v_FirstChild_v(t);
246 break;
247 }
248 pop();
249 }
250 }
251 }