View Javadoc

1   /*
2    * ASTStatementList.java
3    * 
4    * Copyright (c) 2006-2008 David Holroyd
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package uk.co.badgersinfoil.metaas.impl;
20  
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  import org.asdt.core.internal.antlr.AS3Parser;
25  import uk.co.badgersinfoil.metaas.dom.ASBlock;
26  import uk.co.badgersinfoil.metaas.dom.ASBreakStatement;
27  import uk.co.badgersinfoil.metaas.dom.ASContinueStatement;
28  import uk.co.badgersinfoil.metaas.dom.ASDeclarationStatement;
29  import uk.co.badgersinfoil.metaas.dom.ASDefaultXMLNamespaceStatement;
30  import uk.co.badgersinfoil.metaas.dom.ASDoWhileStatement;
31  import uk.co.badgersinfoil.metaas.dom.Expression;
32  import uk.co.badgersinfoil.metaas.dom.ASExpressionStatement;
33  import uk.co.badgersinfoil.metaas.dom.ASForEachInStatement;
34  import uk.co.badgersinfoil.metaas.dom.ASForInStatement;
35  import uk.co.badgersinfoil.metaas.dom.ASForStatement;
36  import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
37  import uk.co.badgersinfoil.metaas.dom.ASReturnStatement;
38  import uk.co.badgersinfoil.metaas.dom.ASSuperStatement;
39  import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
40  import uk.co.badgersinfoil.metaas.dom.ASThrowStatement;
41  import uk.co.badgersinfoil.metaas.dom.ASTryStatement;
42  import uk.co.badgersinfoil.metaas.dom.ASWhileStatement;
43  import uk.co.badgersinfoil.metaas.dom.ASWithStatement;
44  import uk.co.badgersinfoil.metaas.dom.Statement;
45  import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListToken;
46  import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree;
47  
48  // TODO: make the ASBlock implementation independent of the StatementContainer implementation
49  
50  /**
51   * Implements the behaviour of StatementContainer.  May be managing statements
52   * for either be a block, or a switch-statement label.
53   */
54  public class ASTStatementList extends ASTScriptElement implements ASBlock {
55  
56  	public ASTStatementList(LinkedListTree ast) {
57  		super(ast);
58  		assertBlockAST(ast);
59  	}
60  
61  	private void assertBlockAST(LinkedListTree ast) {
62  		switch (ast.getType()) {
63  		    case AS3Parser.BLOCK:
64  		    case AS3Parser.SWITCH_STATEMENT_LIST:
65  			break;
66  		    default:
67  			throw new IllegalArgumentException("statement is not a block: "+ASTUtils.tokenName(ast));
68  		}
69  	}
70  
71  	public Statement addStmt(String statement) {
72  		LinkedListTree stmt = AS3FragmentParser.parseStatement(statement);
73  		stmt.getStopToken().setNext(null);
74  		addStatement(stmt);
75  		return StatementBuilder.build(stmt);
76  	}
77  
78  	public ASExpressionStatement newExprStmt(String expr) {
79  		LinkedListTree stmt = AS3FragmentParser.parseExprStatement(expr);
80  		addStatement(stmt);
81  		return new ASTASExpressionStatement(stmt);
82  	}
83  	public ASExpressionStatement newExprStmt(Expression expr) {
84  		LinkedListTree stmt = ASTBuilder.newExprStmt(ast(expr));
85  		addStatement(stmt);
86  		return new ASTASExpressionStatement(stmt);
87  	}
88  
89  	public void addComment(String text) {
90  		LinkedListToken comment = TokenBuilder.newSLComment("//" + text);
91  		String indent = findIndentForComment();
92  		ast.appendToken(TokenBuilder.newNewline());
93  		ast.appendToken(TokenBuilder.newWhiteSpace(indent));
94  		ast.appendToken(comment);
95  	}
96  
97  	private String findIndentForComment() {
98  		LinkedListTree last = ast.getLastChild();
99  		String indent;
100 		if (last == null) {
101 			indent = "\t" + ASTUtils.findIndent(ast);
102 		} else {
103 			indent = ASTUtils.findIndent(last);
104 		}
105 		return indent;
106 	}
107 
108 	public ASIfStatement newIf(String condition) {
109 		LinkedListTree ifStmt = ASTBuilder.newIf(condition);
110 		addStatement(ifStmt);
111 		return new ASTASIfStatement(ifStmt);
112 	}
113 	public ASIfStatement newIf(Expression condition) {
114 		LinkedListTree ifStmt = ASTBuilder.newIf(ast(condition));
115 		addStatement(ifStmt);
116 		return new ASTASIfStatement(ifStmt);
117 	}
118 
119 	public ASForStatement newFor(String init, String condition, String iterate) {
120 		LinkedListTree forStmt = ASTBuilder.newFor(init, condition, iterate);
121 		appendBlock(forStmt);
122 		addStatement(forStmt);
123 		return new ASTASForStatement(forStmt);
124 	}
125 	public ASForStatement newFor(Expression init, Expression condition, Expression iterate) {
126 		LinkedListTree forStmt = ASTBuilder.newFor(ast(init),
127 		                                           ast(condition),
128 		                                           ast(iterate));
129 		appendBlock(forStmt);
130 		addStatement(forStmt);
131 		return new ASTASForStatement(forStmt);
132 	}
133 
134 	public ASForInStatement newForIn(String declaration, String expression) {
135 		LinkedListTree forStmt = ASTBuilder.newForIn(declaration, expression);
136 		appendBlock(forStmt);
137 		addStatement(forStmt);
138 		return new ASTASForInStatement(forStmt);
139 	}
140 	public ASForInStatement newForIn(Expression declaration, Expression expression) {
141 		LinkedListTree forStmt = ASTBuilder.newForIn(ast(declaration),
142 		                                             ast(expression));
143 		appendBlock(forStmt);
144 		addStatement(forStmt);
145 		return new ASTASForInStatement(forStmt);
146 	}
147 
148 	public ASForEachInStatement newForEachIn(String declaration, String expression) {
149 		LinkedListTree forStmt = ASTBuilder.newForEachIn(declaration, expression);
150 		appendBlock(forStmt);
151 		addStatement(forStmt);
152 		return new ASTASForEachInStatement(forStmt);
153 	}
154 	public ASForEachInStatement newForEachIn(Expression declaration, Expression expression) {
155 		LinkedListTree forStmt = ASTBuilder.newForEachIn(ast(declaration),
156 		                                                 ast(expression));
157 		appendBlock(forStmt);
158 		addStatement(forStmt);
159 		return new ASTASForEachInStatement(forStmt);
160 	}
161 
162 	public ASWhileStatement newWhile(String condition) {
163 		LinkedListTree whileStmt = ASTBuilder.newWhile(condition);
164 		appendBlock(whileStmt);
165 		addStatement(whileStmt);
166 		return new ASTASWhileStatement(whileStmt);
167 	}
168 	public ASWhileStatement newWhile(Expression condition) {
169 		LinkedListTree whileStmt = ASTBuilder.newWhile(ast(condition));
170 		appendBlock(whileStmt);
171 		addStatement(whileStmt);
172 		return new ASTASWhileStatement(whileStmt);
173 	}
174 
175 	public ASDoWhileStatement newDoWhile(String condition) {
176 		LinkedListTree doWhileStmt = ASTBuilder.newDoWhile(condition);
177 		addStatement(doWhileStmt);
178 		return new ASTASDoWhileStatement(doWhileStmt);
179 	}
180 	public ASDoWhileStatement newDoWhile(Expression condition) {
181 		LinkedListTree doWhileStmt = ASTBuilder.newDoWhile(ast(condition));
182 		addStatement(doWhileStmt);
183 		return new ASTASDoWhileStatement(doWhileStmt);
184 	}
185 
186 	public ASSwitchStatement newSwitch(String condition) {
187 		LinkedListTree switchStmt = ASTBuilder.newSwitch(condition);
188 		addStatement(switchStmt);
189 		return new ASTASSwitchStatement(switchStmt);
190 	}
191 	public ASSwitchStatement newSwitch(Expression condition) {
192 		LinkedListTree switchStmt = ASTBuilder.newSwitch(ast(condition));
193 		addStatement(switchStmt);
194 		return new ASTASSwitchStatement(switchStmt);
195 	}
196 
197 	public ASWithStatement newWith(String expr) {
198 		LinkedListTree withStmt = ASTBuilder.newWith(expr);
199 		appendBlock(withStmt);
200 		addStatement(withStmt);
201 		return new ASTASWithStatement(withStmt);
202 	}
203 	public ASWithStatement newWith(Expression expr) {
204 		LinkedListTree withStmt = ASTBuilder.newWith(ast(expr));
205 		appendBlock(withStmt);
206 		addStatement(withStmt);
207 		return new ASTASWithStatement(withStmt);
208 	}
209 
210 	public ASDeclarationStatement newDeclaration(String assignment) {
211 		LinkedListTree declStmt = ASTBuilder.newDeclaration(assignment);
212 		addStatement(declStmt);
213 		return new ASTASDeclarationStatement(declStmt);
214 	}
215 	public ASDeclarationStatement newDeclaration(Expression assignment) {
216 		LinkedListTree declStmt = ASTBuilder.newDeclaration(ast(assignment));
217 		addStatement(declStmt);
218 		return new ASTASDeclarationStatement(declStmt);
219 	}
220 
221 	public ASReturnStatement newReturn(String expr) {
222 		LinkedListTree returnStmt = ASTBuilder.newReturn(expr);
223 		addStatement(returnStmt);
224 		return new ASTASReturnStatement(returnStmt);
225 	}
226 	public ASReturnStatement newReturn(Expression expr) {
227 		LinkedListTree returnStmt = ASTBuilder.newReturn(ast(expr));
228 		addStatement(returnStmt);
229 		return new ASTASReturnStatement(returnStmt);
230 	}
231 	public ASReturnStatement newReturn() {
232 		LinkedListTree returnStmt = ASTBuilder.newReturn((String)null);
233 		addStatement(returnStmt);
234 		return new ASTASReturnStatement(returnStmt);
235 	}
236 
237 	public ASSuperStatement newSuper(List args) {
238 		LinkedListTree superStmt = ASTBuilder.newSuperStatement(args);
239 		addStatement(superStmt);
240 		return new ASTASSuperStatement(superStmt);
241 	}
242 
243 	public ASBreakStatement newBreak() {
244 		LinkedListTree breakStmt = ASTBuilder.newBreakStatement();
245 		addStatement(breakStmt);
246 		return new ASTASBreakStatement(breakStmt);
247 	}
248 
249 	public ASTryStatement newTryCatch(String var, String type) {
250 		LinkedListTree tryStmt = ASTBuilder.newTryStatement();
251 		tryStmt.appendToken(TokenBuilder.newSpace());
252 		tryStmt.addChildWithTokens(ASTBuilder.newCatchClause(var, type));
253 		addStatement(tryStmt);
254 		return new ASTASTryStatement(tryStmt);
255 	}
256 
257 	public ASTryStatement newTryFinally() {
258 		LinkedListTree tryStmt = ASTBuilder.newTryStatement();
259 		tryStmt.appendToken(TokenBuilder.newSpace());
260 		tryStmt.addChildWithTokens(ASTBuilder.newFinallyClause());
261 		addStatement(tryStmt);
262 		return new ASTASTryStatement(tryStmt);
263 	}
264 
265 	public ASContinueStatement newContinue() {
266 		LinkedListTree breakStmt = ASTBuilder.newContinueStatement();
267 		addStatement(breakStmt);
268 		return new ASTASContinueStatement(breakStmt);
269 	}
270 
271 	public ASThrowStatement newThrow(Expression t) {
272 		LinkedListTree throwStmt = ASTBuilder.newThrowStatement(ast(t));
273 		addStatement(throwStmt);
274 		return new ASTASThrowStatement(throwStmt);
275 	}
276 
277 	public ASDefaultXMLNamespaceStatement newDefaultXMLNamespace(String namespace) {
278 		LinkedListTree nsStmt = ASTBuilder.newDefaultXMLNamespace(ASTBuilder.newString(namespace));
279 		addStatement(nsStmt);
280 		return new ASTASDefaultXMLNamespaceStatement(nsStmt);
281 	}
282 
283 	private void addStatement(LinkedListTree stmt) {
284 		ASTUtils.addChildWithIndentation(ast, stmt);
285 	}
286 
287 	public boolean containsCode() {
288 		return ast.getFirstChild() != null;
289 	}
290 
291 	public LinkedListTree getAST() {
292 		return ast;
293 	}
294 
295 	/**
296 	 * Appends a block node as a child of the given node (preceeding it
297 	 * with a space token) and returns a reference to the new block.
298 	 * 
299 	 * NB doesn't do indentation properly, so add the block to the statement
300 	 * before the statement is added to its container.
301 	 */
302 	private static LinkedListTree appendBlock(LinkedListTree ast) {
303 		ast.appendToken(TokenBuilder.newSpace());
304 		LinkedListTree block = ASTBuilder.newBlock();
305 		ast.addChildWithTokens(block);
306 		return block;
307 	}
308 
309 	/**
310 	 * Returns the first BLOCK child of the given node
311 	 */
312 	private static LinkedListTree findBlock(LinkedListTree ast) {
313 		return (LinkedListTree)ast.getFirstChildWithType(AS3Parser.BLOCK);
314 	}
315 
316 	public List getStatementList() {
317 		List result = new ArrayList();
318 		ASTIterator i = new ASTIterator(ast);
319 		while (i.hasNext()) {
320 			result.add(StatementBuilder.build(i.next()));
321 		}
322 		return Collections.unmodifiableList(result);
323 	}
324 
325 }