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: 1.13 $
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
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.ELIST:
94 case GroovyTokenTypes.PARAMETERS:
95 case GroovyTokenTypes.STRING_CONSTRUCTOR:
96 accept_v_FirstChild_v_SecondChild_v___LastChild_v(t);
97 break;
98
99 case GroovyTokenTypes.INDEX_OP:
100 accept_FirstChild_v_SecondChild_v(t);
101 break;
102
103 case GroovyTokenTypes.EXPR:
104 case GroovyTokenTypes.IMPORT:
105 case GroovyTokenTypes.PACKAGE_DEF:
106 case GroovyTokenTypes.VARIABLE_DEF:
107 case GroovyTokenTypes.METHOD_DEF:
108 case GroovyTokenTypes.OBJBLOCK:
109 case GroovyTokenTypes.PARAMETER_DEF:
110 case GroovyTokenTypes.SLIST:
111 accept_v_AllChildren_v(t);
112 break;
113
114 case GroovyTokenTypes.ASSIGN:
115 case GroovyTokenTypes.EQUAL:
116 case GroovyTokenTypes.NOT_EQUAL:
117 if (t.childAt(1) != null) {
118 accept_FirstChild_v_RestOfTheChildren(t);
119 } else {
120 accept_v_FirstChild_v_RestOfTheChildren(t);
121 }
122 break;
123
124 case GroovyTokenTypes.CLASS_DEF:
125 case GroovyTokenTypes.CTOR_IDENT:
126 case GroovyTokenTypes.DOT:
127 case GroovyTokenTypes.GT:
128 case GroovyTokenTypes.LABELED_ARG:
129 case GroovyTokenTypes.LAND:
130 case GroovyTokenTypes.LT:
131 case GroovyTokenTypes.MEMBER_POINTER:
132 case GroovyTokenTypes.MINUS:
133 case GroovyTokenTypes.PLUS:
134 case GroovyTokenTypes.RANGE_EXCLUSIVE:
135 case GroovyTokenTypes.RANGE_INCLUSIVE:
136 case GroovyTokenTypes.STAR:
137 accept_FirstChild_v_RestOfTheChildren(t);
138 break;
139
140 case GroovyTokenTypes.METHOD_CALL:
141 if (t.getNumberOfChildren() == 2 && t.childAt(1) != null && t.childAt(1).getType() == GroovyTokenTypes.CLOSED_BLOCK ) {
142
143 accept_FirstChild_v_SecondChild(t);
144 } else {
145 GroovySourceAST lastChild = t.childAt(t.getNumberOfChildren() -1);
146 if (lastChild != null && lastChild.getType() == GroovyTokenTypes.CLOSED_BLOCK) {
147
148 accept_FirstChild_v_RestOfTheChildren_v_LastChild(t);
149 } else {
150
151 accept_FirstChild_v_RestOfTheChildren_v(t);
152 }
153 }
154 break;
155
156 case GroovyTokenTypes.LITERAL_while:
157 case GroovyTokenTypes.TYPECAST:
158 accept_v_FirstChildsFirstChild_v_RestOfTheChildren(t);
159 break;
160
161 case GroovyTokenTypes.LITERAL_if:
162 accept_v_FirstChildsFirstChild_v_Child2_Child3_v_Child4_v___v_LastChild(t);
163 break;
164
165 case GroovyTokenTypes.CLOSED_BLOCK:
166 if (t.childAt(0) != null && t.childAt(0).getType() == GroovyTokenTypes.IMPLICIT_PARAMETERS) {
167 accept_v_AllChildren_v(t);
168 } else {
169 accept_v_FirstChild_v_RestOfTheChildren_v(t);
170 }
171 break;
172
173 case GroovyTokenTypes.FOR_IN_ITERABLE:
174 case GroovyTokenTypes.LITERAL_for:
175 case GroovyTokenTypes.LITERAL_new:
176 case GroovyTokenTypes.LITERAL_switch:
177 accept_v_FirstChild_v_RestOfTheChildren_v(t);
178 break;
179
180 case GroovyTokenTypes.LITERAL_catch:
181 case GroovyTokenTypes.LITERAL_try:
182 accept_v_FirstChild_v_RestOfTheChildren(t);
183 break;
184
185 default:
186 accept_v_FirstChild_v(t);
187 break;
188 }
189 }
190 }
191 }