001: package xtc.lang.jeannie;
002:
003: import java.util.Stack;
004:
005: import xtc.lang.JavaEntities;
006: import xtc.tree.GNode;
007: import xtc.tree.Node;
008: import xtc.tree.Visitor;
009: import xtc.util.Runtime;
010:
011: public final class DebuggerAstAnalyzer extends Visitor {
012: enum Language {
013: C, JAVA, DEBUGGER
014: };
015:
016: private static class MiniVisitor_allNodesHaveLanguage extends
017: Visitor {
018: public final void visit(final Node n) {
019: assert null != DebuggerAstAnalyzer.getNodeLanguage(n) : n
020: .toString();
021: for (int i = 0; i < n.size(); i++)
022: if (n.get(i) instanceof Node)
023: dispatch(n.getNode(i));
024: }
025: }
026:
027: public static void assertAllNodesHaveLanguage(final Node n) {
028: new MiniVisitor_allNodesHaveLanguage().dispatch(n);
029: }
030:
031: public static Language getNodeLanguage(final Node n) {
032: return (Language) n.getProperty("language");
033: }
034:
035: public static Object getNodeVariableRemap(final Node n) {
036: return (Object) n.getProperty("variableRemap");
037: }
038:
039: private static Language setNodeLanguage(final Node n,
040: final Language language) {
041: n.setProperty("language", language);
042: return language;
043: }
044:
045: private static Object setNodeVariableRemap(final Node n,
046: final Object variableRemap) {
047: n.setProperty("variableRemap", variableRemap);
048: return variableRemap;
049: }
050:
051: final DebuggerSymbolMapper _symbolMapper;
052: final Runtime _runtime;
053: private final Stack<Language> _stack;
054:
055: public DebuggerAstAnalyzer(final Runtime runtime,
056: final DebuggerSymbolMapper symbolMapper) {
057: assert null != runtime && null != symbolMapper;
058: _runtime = runtime;
059: _stack = new Stack<Language>();
060: _stack.push(Language.DEBUGGER);
061: _symbolMapper = symbolMapper;
062: }
063:
064: private boolean assrt(final Node n, final boolean cond,
065: final String msgFormat, final Object... msgArgs) {
066: return JavaEntities.runtimeAssrt(_runtime, n, cond, msgFormat,
067: msgArgs);
068: }
069:
070: private final Language currentLanguage() {
071: return _stack.peek();
072: }
073:
074: private final Object dispatchInLanguage(final Node n,
075: final Language language) {
076: enterLanguage(language);
077: final Object result = dispatch(n);
078: exitLanguage(language);
079: return result;
080: }
081:
082: private final void enterLanguage(final Language language) {
083: _stack.push(language);
084: }
085:
086: private final void exitLanguage(final Language language) {
087: assert currentLanguage() == language;
088: _stack.pop();
089: }
090:
091: private boolean setAndAssrtLanguage(final Node n,
092: final Language language) {
093: setNodeLanguage(n, language);
094: return assrt(n, language == currentLanguage(),
095: "expected language %s, current %s", language,
096: currentLanguage());
097: }
098:
099: public final void visit(final GNode n) {
100: assrt(n, false,
101: "the Jeannie debugger does not support the %s feature",
102: n.getName());
103: }
104:
105: /** Visit an AdditiveExpression = Expression ("+" / "-") Expression. */
106: public final void visitAdditiveExpression(final GNode n) {
107: final Language curr = currentLanguage();
108: if (assrt(n, curr == Language.C || curr == Language.JAVA,
109: "expected language C or Java, current %s", curr)) {
110: setNodeLanguage(n, curr);
111: dispatch(n.getNode(0));
112: dispatch(n.getNode(2));
113: }
114: }
115:
116: /** Visit an AddressExpression = Expression. */
117: public final void visitAddressExpression(final GNode n) {
118: if (setAndAssrtLanguage(n, Language.C))
119: dispatch(n.getNode(0));
120: }
121:
122: /** Visit Arguments = Expression*. */
123: public final void visitArguments(final GNode n) {
124: if (setAndAssrtLanguage(n, Language.JAVA))
125: for (int i = 0; i < n.size(); i++)
126: dispatch(n.getNode(i));
127: }
128:
129: /** Visit an AssignmentExpression = Expression ("=" / "+=" / "-=" / "*=" / "/=" / "%=" / "<<=" / ">>=" / "&=" / "^=" / "|=") Expression. */
130: public final void visitAssignmentExpression(final GNode n) {
131: if (setAndAssrtLanguage(n, Language.C)) {
132: dispatch(n.getNode(0));
133: dispatch(n.getNode(2));
134: }
135: }
136:
137: /** Visit a BreakClassCommand = QualifiedIdentifier LineNumber. */
138: public final void visitBreakClassCommand(final GNode n) {
139: if (setAndAssrtLanguage(n, Language.DEBUGGER)) {
140: @SuppressWarnings("unused")
141: final String className = (String) dispatchInLanguage(n
142: .getNode(0), Language.JAVA);
143: }
144: }
145:
146: /** Visit a BreakFileCommand = FileName LineNumber. */
147: public final void visitBreakFileCommand(final GNode n) {
148: setAndAssrtLanguage(n, Language.DEBUGGER);
149: }
150:
151: /** Visit a C2jCommand = (no children). */
152: public final void visitC2jCommand(final GNode n) {
153: setAndAssrtLanguage(n, Language.DEBUGGER);
154: }
155:
156: /** Visit a CallExpression = [Expression] null MethodName Arguments. */
157: public final void visitCallExpression(final GNode n) {
158: if (setAndAssrtLanguage(n, Language.JAVA)) {
159: if (null != n.get(0))
160: dispatch(n.getNode(0));
161: @SuppressWarnings("unused")
162: final String methodName = n.getString(2);
163: dispatch(n.getNode(3));
164: }
165: }
166:
167: /** Visit a CInJavaExpression = C.UnaryExpression. */
168: public final void visitCInJavaExpression(final GNode n) {
169: if (setAndAssrtLanguage(n, Language.JAVA))
170: dispatchInLanguage(n.getNode(0), Language.C);
171: }
172:
173: /** Visit a ContinueCommand = (no children). */
174: public final void visitContinueCommand(final GNode n) {
175: setAndAssrtLanguage(n, Language.DEBUGGER);
176: }
177:
178: /** Visit a DeleteCommand = IntegerLiteral. */
179: public final void visitDeleteCommand(final GNode n) {
180: if (setAndAssrtLanguage(n, Language.DEBUGGER))
181: dispatchInLanguage(n.getNode(0), Language.JAVA);
182: }
183:
184: /** Visit a DirectComponentSelection = Expression String. */
185: public final void visitDirectComponentSelection(final GNode n) {
186: if (setAndAssrtLanguage(n, Language.C))
187: dispatch(n.getNode(0));
188: }
189:
190: /** Visit a DownCommand = IntegerLiteral. */
191: public final void visitDownCommand(final GNode n) {
192: if (setAndAssrtLanguage(n, Language.DEBUGGER))
193: dispatchInLanguage(n.getNode(0), Language.JAVA);
194: }
195:
196: /** Visit a EqualityExpression = Expression ("==" / "!=") Expression. */
197: public final void visitEqualityExpression(final GNode n) {
198: final Language curr = currentLanguage();
199: if (assrt(n, curr == Language.C || curr == Language.JAVA,
200: "expected language C or Java, current %s", curr)) {
201: setNodeLanguage(n, curr);
202: dispatch(n.getNode(0));
203: dispatch(n.getNode(2));
204: }
205: }
206:
207: /** Visit a ExitCommand = (no children). */
208: public final void visitExitCommand(final GNode n) {
209: setAndAssrtLanguage(n, Language.DEBUGGER);
210: }
211:
212: /** Visit a Expression = Expression ("=" / "+=" / "-=" / "*=" / "/=" / "&=" / "|=" / "^=" / "%=" / "<<=" / ">>=" / ">>>=") Expression. */
213: public final void visitExpression(final GNode n) {
214: if (setAndAssrtLanguage(n, Language.JAVA)) {
215: dispatch(n.getNode(0));
216: dispatch(n.getNode(2));
217: }
218: }
219:
220: /** Visit ExpressionList = Expression+. */
221: public final void visitExpressionList(final GNode n) {
222: if (setAndAssrtLanguage(n, Language.C))
223: for (int i = 0; i < n.size(); i++)
224: dispatch(n.getNode(i));
225: }
226:
227: /** Visit a FunctionCall = Expression [ExpressionList]. */
228: public final void visitFunctionCall(final GNode n) {
229: if (setAndAssrtLanguage(n, Language.C)) {
230: dispatch(n.getNode(0));
231: if (null != n.get(1))
232: dispatch(n.getNode(1));
233: }
234: }
235:
236: /** Visit a GdbCommand = RestOfLine. */
237: public final void visitGdbCommand(final GNode n) {
238: setAndAssrtLanguage(n, Language.DEBUGGER);
239: }
240:
241: /** Visit a HelpCommand = (no children). */
242: public final void visitHelpCommand(final GNode n) {
243: setAndAssrtLanguage(n, Language.DEBUGGER);
244: }
245:
246: /** Visit an IndirectionExpression = Expression. */
247: public final void visitIndirectionExpression(final GNode n) {
248: if (setAndAssrtLanguage(n, Language.C))
249: dispatch(n.getNode(0));
250: }
251:
252: /** Visit a InfoBreakCommand = (no children). */
253: public final void visitInfoBreakCommand(final GNode n) {
254: setAndAssrtLanguage(n, Language.DEBUGGER);
255: }
256:
257: /** Visit a InfoWatchCommand = (no children). */
258: public final void visitInfoWatchCommand(final GNode n) {
259: setAndAssrtLanguage(n, Language.DEBUGGER);
260: }
261:
262: /** Visit an InitJCommand = (no children). */
263: public final void visitInitJCommand(final GNode n) {
264: setAndAssrtLanguage(n, Language.DEBUGGER);
265: }
266:
267: /** Visit an IntegerConstant = String. */
268: public final void visitIntegerConstant(final GNode n) {
269: setAndAssrtLanguage(n, Language.C);
270: }
271:
272: /** Visit an IntegerLiteral = String. */
273: public final void visitIntegerLiteral(final GNode n) {
274: setAndAssrtLanguage(n, Language.JAVA);
275: }
276:
277: /** Visit a J2cCommand = (no children). */
278: public final void visitJ2cCommand(final GNode n) {
279: setAndAssrtLanguage(n, Language.DEBUGGER);
280: }
281:
282: /** Visit a JavaInCExpression = Java.UnaryExpression. */
283: public final void visitJavaInCExpression(final GNode n) {
284: if (setAndAssrtLanguage(n, Language.C))
285: dispatchInLanguage(n.getNode(0), Language.JAVA);
286: }
287:
288: /** Visit a JdbCommand = RestOfLine. */
289: public final void visitJdbCommand(final GNode n) {
290: setAndAssrtLanguage(n, Language.DEBUGGER);
291: }
292:
293: /** Visit a JRetCommand = (no children). */
294: public final void visitJRetCommand(final GNode n) {
295: setAndAssrtLanguage(n, Language.DEBUGGER);
296: }
297:
298: /** Visit a ListCommand = (no children). */
299: public final void visitListCommand(final GNode n) {
300: setAndAssrtLanguage(n, Language.DEBUGGER);
301: }
302:
303: /** Visit a LocalsCommand = (no children). */
304: public final void visitLocalsCommand(final GNode n) {
305: setAndAssrtLanguage(n, Language.DEBUGGER);
306: }
307:
308: /** Visit a MetaVariable = Identifier. */
309: public final void visitMetaVariable(final GNode n) {
310: setNodeLanguage(n, Language.DEBUGGER);
311: final Language curr = currentLanguage();
312: assrt(n, curr == Language.C || curr == Language.JAVA,
313: "expected language C or Java, current %s", curr);
314: }
315:
316: /** Visit a NextCommand = (no children). */
317: public final void visitNextCommand(final GNode n) {
318: setAndAssrtLanguage(n, Language.DEBUGGER);
319: }
320:
321: /** Visit a RunCommand = (no children). */
322: public final void visitRunCommand(final GNode n) {
323: setAndAssrtLanguage(n, Language.DEBUGGER);
324: }
325:
326: /** Visit an StringLiteral = (no children). */
327: public final void visitNullLiteral(final GNode n) {
328: setAndAssrtLanguage(n, Language.JAVA);
329: }
330:
331: /** Visit a PrimaryIdentifier = String. */
332: public void visitPrimaryIdentifier(final GNode n) {
333: final Language curr = currentLanguage();
334: if (assrt(n, curr == Language.C || curr == Language.JAVA,
335: "expected language C or Java, current %s", curr)) {
336: setNodeLanguage(n, curr);
337: final String identifier = n.getString(0);
338: final DebuggerSymbolMapper.SourceFileAndLine sourceFileAndLine = _symbolMapper
339: .getCurrentSourceFileAndLine();
340: final DebuggerSymbolMapper.VariableRemapEntry variableRemap = _symbolMapper
341: .lookUpVariableRemap(identifier, sourceFileAndLine
342: .getSourceFile(), sourceFileAndLine
343: .getSourceLine());
344: if (null != variableRemap)
345: setNodeVariableRemap(n, variableRemap);
346: }
347: }
348:
349: /** Visit a PrintCExpressionCommand = C.Expression. */
350: public final void visitPrintCExpressionCommand(final GNode n) {
351: if (setAndAssrtLanguage(n, Language.DEBUGGER))
352: dispatchInLanguage(n.getNode(0), Language.C);
353: }
354:
355: /** Visit a PrintJavaExpressionCommand = Java.Expression. */
356: public final void visitPrintJavaExpressionCommand(final GNode n) {
357: if (setAndAssrtLanguage(n, Language.DEBUGGER))
358: dispatchInLanguage(n.getNode(0), Language.JAVA);
359: }
360:
361: /** Visit a QualifiedIdentifier = Identifier+. */
362: public final String visitQualifiedIdentifier(final GNode n) {
363: if (!setAndAssrtLanguage(n, Language.JAVA))
364: return null;
365: return Utilities.qualifiedIdentifierToString(n);
366: }
367:
368: /** Visit a SelectionExpression = Expression Identifier. */
369: public final void visitSelectionExpression(final GNode n) {
370: setAndAssrtLanguage(n, Language.JAVA);
371: dispatch(n.getNode(0));
372: dispatch(n.getNode(1));
373: }
374:
375: /** Visit a StatCommand = (no children). */
376: public final void visitStatCommand(final GNode n) {
377: setAndAssrtLanguage(n, Language.DEBUGGER);
378: }
379:
380: /** Visit a StepCommand = (no children). */
381: public final void visitStepCommand(final GNode n) {
382: setAndAssrtLanguage(n, Language.DEBUGGER);
383: }
384:
385: /** Visit an StringConstant = String. */
386: public final void visitStringConstant(final GNode n) {
387: setAndAssrtLanguage(n, Language.JAVA);
388: }
389:
390: /** Visit an StringLiteral = String. */
391: public final void visitStringLiteral(final GNode n) {
392: setAndAssrtLanguage(n, Language.JAVA);
393: }
394:
395: /** Visit a SubscriptExpression = Expression Expression. */
396: public final void visitSubscriptExpression(final GNode n) {
397: final Language curr = currentLanguage();
398: if (assrt(n, curr == Language.C || curr == Language.JAVA,
399: "expected language C or Java, current %s", curr)) {
400: setNodeLanguage(n, curr);
401: dispatch(n.getNode(0));
402: dispatch(n.getNode(1));
403: }
404: }
405:
406: /** Visit a ThisExpression = [Expression]. */
407: public final void visitThisExpression(final GNode n) {
408: setAndAssrtLanguage(n, Language.JAVA);
409: assrt(n, null == n.get(0),
410: "the Jeannie debugger does not support qualified this in Java expressions");
411: }
412:
413: /** Visit an UpCommand = IntegerLiteral. */
414: public final void visitUpCommand(final GNode n) {
415: if (setAndAssrtLanguage(n, Language.DEBUGGER))
416: dispatchInLanguage(n.getNode(0), Language.JAVA);
417: }
418:
419: /** Visit a WatchCExpressionCommand = C.Expression. */
420: public final void visitWatchCExpressionCommand(final GNode n) {
421: if (setAndAssrtLanguage(n, Language.DEBUGGER))
422: dispatchInLanguage(n, Language.C);
423: }
424:
425: /** Visit a WatchJavaFieldCommand = [WatchKind] QualifiedIdentifier. */
426: public final void visitWatchJavaFieldCommand(final GNode n) {
427: if (setAndAssrtLanguage(n, Language.DEBUGGER)) {
428: @SuppressWarnings("unused")
429: final String className = (String) dispatchInLanguage(n
430: .getNode(1), Language.JAVA);
431: }
432: }
433:
434: /** Visit a WhereCommand = (no children). */
435: public final void visitWhereCommand(final GNode n) {
436: setAndAssrtLanguage(n, Language.DEBUGGER);
437: }
438: }
|