001: /*=============================================================================
002: * Copyright Texas Instruments 2003. All Rights Reserved.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
019: */
020:
021: package oscript.translator;
022:
023: import oscript.syntaxtree.*;
024: import oscript.parser.*;
025:
026: /**
027: * A translator to implement one part of the language in terms of another.
028: * This simplifies the compiler/interpreter implementation. This translates
029: * from:
030: * <pre>
031: * "for" "(" PreLoopStatement ":" Expression ")"
032: * EvaluationUnit
033: * </pre>
034: * to
035: * <pre>
036: * "{"
037: * "var" "$itr$" = "(" Expression ")" "." "iterator" "(" ")" ";"
038: * "while" "(" "$itr$" "." "hasNext" "(" ")" ")"
039: * "{"
040: * PreLoopStatement "=" "$itr$" "." "next" "(" ")" ";"
041: * EvaluationUnit
042: * "}"
043: * "}"
044: * </pre>
045: *
046: * <!--
047: * Note that current implementation substitutes NodeToken-s for the most
048: * similar NodeToken in the input. This makes row/col #'s the most sane,
049: * but the string representation may be wrong, for example "for" instead
050: * of "while". I did it this way since it is the least overhead, which
051: * matters for the interpreter. That should work find with the current
052: * interpreter and compiler implementations
053: * -->
054: *
055: * @author Rob Clark
056: * @version 0.1
057: */
058: public class CollectionForLoopStatementTranslator {
059: private final static NodeToken ITR_ID = makeIdNt("$itr$");
060: private final static NodeToken ITERATOR_ID = makeIdNt("iterator");
061: private final static NodeToken NEXT_ID = makeIdNt("next");
062: private final static NodeToken HAS_NEXT_ID = makeIdNt("hasNext");
063:
064: /**
065: * Convert a {@link CollectionForLoopStatement} production in the syntaxtree
066: * into an equivalent production.
067: * <PRE>
068: * f0 -> "for"
069: * f1 -> "("
070: * f2 -> PreLoopStatement()
071: * f3 -> ":"
072: * f4 -> Expression()
073: * f5 -> ")"
074: * f6 -> EvaluationUnit()
075: * </PRE>
076: */
077: public static Node translate(CollectionForLoopStatement n) {
078: if (n.translated == null) {
079: n.translated = new ScopeBlock(nt(n, "{"), // "{"
080: makeProgram(n), // Program
081: nt(n, "}"), // "}"
082: true, n.hasFxnInScope);
083:
084: // System.err.println("-- From: --------------");
085: // n.accept( new oscript.visitor.TreeDumper(System.err) );
086: // System.err.println("-- To: ----------------");
087: // n.translated.accept( new oscript.visitor.TreeDumper(System.err) );
088: }
089: return n.translated;
090: }
091:
092: private static Program makeProgram(CollectionForLoopStatement n) {
093: NodeListOptional nlo = new NodeListOptional();
094:
095: nlo.addNode(new VariableDeclarationBlock(
096: makeVariableDeclaration(n), nt(n, ";") // ";"
097: ));
098: nlo.addNode(makeWhileLoopStatement(n));
099:
100: return new Program(nlo, false);
101: }
102:
103: private static VariableDeclaration makeVariableDeclaration(
104: CollectionForLoopStatement n) {
105: NodeSequence ns = new NodeSequence(2);
106:
107: ns.addNode(nt(n, "=")); // "="
108:
109: NodeListOptional nlo = new NodeListOptional();
110:
111: nlo.addNode(new PrimaryPostfix(new NodeChoice(
112: new PropertyIdentifierPrimaryPostfix(nt(n, "."), // "."
113: ITERATOR_ID // "iterator"
114: ))));
115:
116: nlo.addNode(new PrimaryPostfix(new NodeChoice(
117: new FunctionCallPrimaryPostfix(
118: new FunctionCallExpressionList(nt(n, "("), // "("
119: new NodeOptional(),// (FunctionCallExpressionListBody)?
120: nt(n, ")") // ")"
121: )))));
122:
123: ns.addNode(new PrimaryExpression(new PrimaryPrefix(
124: new NodeChoice(new ParenPrimaryPrefix(nt(n, "("), // "("
125: n.f4, // Expression
126: nt(n, ")") // ")"
127: ))), nlo // "." "iterator" "(" ")"
128: ));
129:
130: return new VariableDeclaration(new Permissions(
131: new NodeListOptional()), nt(n, "var"), // "var"
132: ITR_ID, // "$itr$"
133: new NodeOptional(ns) // "=" Expression
134: );
135: }
136:
137: private static WhileLoopStatement makeWhileLoopStatement(
138: CollectionForLoopStatement n) {
139: return new WhileLoopStatement(nt(n, "while"), // "while"
140: nt(n, "("), // "("
141: makeWhileLoopExpression(n), nt(n, ")"), // ")"
142: new EvaluationUnit(new NodeChoice(new ScopeBlock(nt(n,
143: "{"), // "{"
144: makeWhileLoopProgram(n), nt(n, "}"), // "}"
145: n.hasVarInScope, n.hasFxnInScope))));
146: }
147:
148: private final static NodeListOptional EMPTY_NLO = new NodeListOptional();
149: private final static NodeOptional EMPTY_NO = new NodeOptional();
150:
151: private static Expression makeWhileLoopExpression(
152: CollectionForLoopStatement n) {
153: // "$itr$" "." "hasNext" "(" ")"
154: NodeListOptional nlo = new NodeListOptional();
155:
156: nlo.addNode(new PrimaryPostfix(new NodeChoice(
157: new PropertyIdentifierPrimaryPostfix(nt(n, "."), // "."
158: HAS_NEXT_ID // "hasNext"
159: ))));
160:
161: nlo.addNode(new PrimaryPostfix(new NodeChoice(
162: new FunctionCallPrimaryPostfix(
163: new FunctionCallExpressionList(nt(n, "("), // "("
164: new NodeOptional(),// (FunctionCallExpressionListBody)?
165: nt(n, ")") // ")"
166: )))));
167:
168: return new Expression(
169: new AssignmentExpression(
170: new ConditionalExpression(
171: new LogicalOrExpression(
172: new LogicalAndExpression(
173: new BitwiseOrExpression(
174: new BitwiseXorExpression(
175: new BitwiseAndExpression(
176: new EqualityExpression(
177: new RelationalExpression(
178: new ShiftExpression(
179: new AdditiveExpression(
180: new MultiplicativeExpression(
181: new UnaryExpression(
182: EMPTY_NO,
183: new PostfixExpression(
184: new TypeExpression(
185: new NodeChoice(
186: new PrimaryExpression(
187: new PrimaryPrefix(
188: new NodeChoice(
189: new IdentifierPrimaryPrefix(
190: ITR_ID // "$itr$"
191: ))),
192: nlo // "." "hasNext" "(" ")"
193: ))),
194: EMPTY_NO)),
195: EMPTY_NLO),
196: EMPTY_NLO),
197: EMPTY_NLO),
198: EMPTY_NLO),
199: EMPTY_NLO),
200: EMPTY_NLO),
201: EMPTY_NLO),
202: EMPTY_NLO),
203: EMPTY_NLO), EMPTY_NLO),
204: EMPTY_NO), EMPTY_NLO), EMPTY_NLO);
205: }
206:
207: private static Program makeWhileLoopProgram(
208: CollectionForLoopStatement n) {
209: NodeListOptional nlo = new NodeListOptional();
210:
211: nlo.addNode(makeExpression(n));
212: nlo.addNode(n.f6); // EvaluationUnit
213:
214: return new Program(nlo, false);
215: }
216:
217: private static Node makeExpression(CollectionForLoopStatement n) {
218: // PreLoopStatement "=" "$itr$" "." "next" "(" ")" ";"
219: NodeListOptional nlo = new NodeListOptional();
220:
221: nlo.addNode(new PrimaryPostfix(new NodeChoice(
222: new PropertyIdentifierPrimaryPostfix(nt(n, "."), // "."
223: NEXT_ID // "next"
224: ))));
225:
226: nlo.addNode(new PrimaryPostfix(new NodeChoice(
227: new FunctionCallPrimaryPostfix(
228: new FunctionCallExpressionList(nt(n, "("), // "("
229: new NodeOptional(),// (FunctionCallExpressionListBody)?
230: nt(n, ")") // ")"
231: )))));
232:
233: ConditionalExpression ce = new ConditionalExpression(
234: new LogicalOrExpression(
235: new LogicalAndExpression(
236: new BitwiseOrExpression(
237: new BitwiseXorExpression(
238: new BitwiseAndExpression(
239: new EqualityExpression(
240: new RelationalExpression(
241: new ShiftExpression(
242: new AdditiveExpression(
243: new MultiplicativeExpression(
244: new UnaryExpression(
245: EMPTY_NO,
246: new PostfixExpression(
247: new TypeExpression(
248: new NodeChoice(
249: new PrimaryExpression(
250: new PrimaryPrefix(
251: new NodeChoice(
252: new IdentifierPrimaryPrefix(
253: ITR_ID // "$itr$"
254: ))),
255: nlo // "." "next" "(" ")"
256: ))),
257: EMPTY_NO)),
258: EMPTY_NLO),
259: EMPTY_NLO),
260: EMPTY_NLO),
261: EMPTY_NLO),
262: EMPTY_NLO),
263: EMPTY_NLO),
264: EMPTY_NLO), EMPTY_NLO),
265: EMPTY_NLO), EMPTY_NLO), EMPTY_NO);
266:
267: Node node;
268:
269: if (n.f2.f0.choice instanceof VariableDeclaration) {
270: VariableDeclaration vd = (VariableDeclaration) (n.f2.f0.choice);
271:
272: if (vd.f3.present())
273: throw new oscript.exceptions.ProgrammingErrorException(
274: "the parser shouldn't let this happen!");
275:
276: NodeSequence ns = new NodeSequence(2);
277:
278: ns.addNode(nt(n, "=")); // "="
279: ns.addNode(ce);
280:
281: node = new VariableDeclarationBlock(
282: new VariableDeclaration(new Permissions(
283: new NodeListOptional()), vd.f1, // "var"
284: vd.f2, // <IDENTIFIER>
285: new NodeOptional(ns)// "=" Expression
286: ), nt(n, ";") // ";"
287: );
288: } else {
289: node = new ExpressionBlock(makeAssignmentExpression(n,
290: (Expression) (n.f2.f0.choice), ce), nt(n, ";") // ";"
291: );
292: }
293:
294: return new EvaluationUnit(new NodeChoice(node));
295: }
296:
297: private static Expression makeAssignmentExpression(
298: CollectionForLoopStatement n, Expression e,
299: ConditionalExpression ce) {
300: NodeListOptional nlo = new NodeListOptional();
301: NodeSequence ns = new NodeSequence(2);
302:
303: Token eqToken = new Token();
304: eqToken.kind = OscriptParserConstants.ASSIGN;
305: ns.addNode(new NodeChoice(new NodeToken("=", null, eqToken,
306: null)));
307: ns.addNode(ce);
308:
309: nlo.addNode(ns);
310:
311: return new Expression(
312: new AssignmentExpression(
313: new ConditionalExpression(
314: new LogicalOrExpression(
315: new LogicalAndExpression(
316: new BitwiseOrExpression(
317: new BitwiseXorExpression(
318: new BitwiseAndExpression(
319: new EqualityExpression(
320: new RelationalExpression(
321: new ShiftExpression(
322: new AdditiveExpression(
323: new MultiplicativeExpression(
324: new UnaryExpression(
325: EMPTY_NO,
326: new PostfixExpression(
327: new TypeExpression(
328: new NodeChoice(
329: new PrimaryExpression(
330: new PrimaryPrefix(
331: new NodeChoice(
332: new ParenPrimaryPrefix(
333: nt(
334: n,
335: "("), // "("
336: e, // Expression
337: nt(
338: n,
339: ")") // ")"
340: ))),
341: EMPTY_NLO))),
342: EMPTY_NO)),
343: EMPTY_NLO),
344: EMPTY_NLO),
345: EMPTY_NLO),
346: EMPTY_NLO),
347: EMPTY_NLO),
348: EMPTY_NLO),
349: EMPTY_NLO),
350: EMPTY_NLO),
351: EMPTY_NLO), EMPTY_NLO),
352: EMPTY_NO), nlo), EMPTY_NLO);
353: }
354:
355: private static final NodeToken nt(CollectionForLoopStatement n,
356: String img) {
357: return n.f0;
358: //return new NodeToken(img);
359: }
360:
361: private static final NodeToken makeIdNt(String img) {
362: Token token = new Token();
363: token.kind = OscriptParserConstants.IDENTIFIER;
364: return new NodeToken(img, oscript.data.OString.makeString(img),
365: token, null);
366: }
367: }
368:
369: /*
370: * Local Variables:
371: * tab-width: 2
372: * indent-tabs-mode: nil
373: * mode: java
374: * c-indentation-style: java
375: * c-basic-offset: 2
376: * eval: (c-set-offset 'substatement-open '0)
377: * eval: (c-set-offset 'case-label '+)
378: * eval: (c-set-offset 'inclass '+)
379: * eval: (c-set-offset 'inline-open '0)
380: * End:
381: */
|