Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(730)

Side by Side Diff: lib/compiler/implementation/tree/prettyprint.dart

Issue 10914004: Produce better XML, one which cannot be analysed with tools like BaseX. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Pretty-prints Node tree in XML-like format. 6 * Pretty-prints Node tree in XML-like format.
7 * 7 *
8 * TODO(smok): Add main() to run from command-line to print out tree for given 8 * TODO(smok): Add main() to run from command-line to print out tree for given
9 * .dart file. 9 * .dart file.
10 */ 10 */
11 class PrettyPrinter implements Visitor { 11 class PrettyPrinter implements Visitor {
12 12
13 /** String used to represent one level of indent. */ 13 /** String used to represent one level of indent. */
14 static const String INDENT = " "; 14 static const String INDENT = " ";
15 15
16 StringBuffer sb; 16 StringBuffer sb;
17 int depth; 17 Link<String> tagStack;
18 /** Prefix for the type passed to the next [openNode()] call. */
19 String nextTypePrefix;
20 /** Nodes that were opened with [openNode()] calls. */
21 Link<String> currentNodeTypes;
22 18
23 PrettyPrinter() : 19 PrettyPrinter() :
24 sb = new StringBuffer(), 20 sb = new StringBuffer(),
25 depth = 0, 21 tagStack = new EmptyLink<String>();
26 currentNodeTypes = new EmptyLink<String>();
27 22
28 void pushCurrentNodeType(String nodeType) { 23 void pushTag(String tag) {
29 currentNodeTypes = currentNodeTypes.prepend(nodeType); 24 tagStack = tagStack.prepend(tag);
30 } 25 }
31 26
32 String popCurrentNodeType() { 27 String popTag() {
33 assert(!currentNodeTypes.isEmpty()); 28 assert(!tagStack.isEmpty());
34 String currentNodeType = currentNodeTypes.head; 29 String tag = tagStack.head;
35 currentNodeTypes = currentNodeTypes.tail; 30 tagStack = tagStack.tail;
36 return currentNodeType; 31 return tag;
37 } 32 }
38 33
39 /** 34 /**
40 * Adds given string to result string. 35 * Adds given string to result string.
41 */ 36 */
42 void add(SourceString string) { 37 void add(SourceString string) {
43 string.printOn(sb); 38 string.printOn(sb);
44 } 39 }
45 40
46 void addBeginAndEndTokensToParams(Node node, Map params) { 41 void addBeginAndEndTokensToParams(Node node, Map params) {
47 params['getBeginToken'] = tokenToStringOrNull(node.getBeginToken()); 42 params['getBeginToken'] = tokenToStringOrNull(node.getBeginToken());
48 params['getEndToken'] = tokenToStringOrNull(node.getEndToken()); 43 params['getEndToken'] = tokenToStringOrNull(node.getEndToken());
49 } 44 }
50 45
51 /** 46 /**
52 * Adds given node type to result string, increasing current depth by 1. 47 * Adds given node type to result string.
53 * The method "opens" the node, meaning that all output after calling 48 * The method "opens" the node, meaning that all output after calling
54 * this method and before calling closeNode() will represent contents 49 * this method and before calling closeNode() will represent contents
55 * of given node. 50 * of given node.
56 */ 51 */
57 void openNode(Node node, String type, [Map params]) { 52 void openNode(Node node, String type, [Map params]) {
58 if (params === null) params = new Map(); 53 if (params === null) params = new Map();
59 addCurrentIndent(); 54 addCurrentIndent();
60 sb.add("<"); 55 sb.add("<");
61 addBeginAndEndTokensToParams(node, params); 56 addBeginAndEndTokensToParams(node, params);
62 addTypeWithParams(type, params); 57 addTypeWithParams(type, params);
63 sb.add(">\n"); 58 sb.add(">\n");
64 pushCurrentNodeType(type); 59 pushTag(type);
65 depth++;
66 } 60 }
67 61
68 /** 62 /**
69 * Adds given node to result string, depth is not affected. 63 * Adds given node to result string.
70 */ 64 */
71 void openAndCloseNode(Node node, String type, [Map params]) { 65 void openAndCloseNode(Node node, String type, [Map params]) {
72 if (params === null) params = new Map(); 66 if (params === null) params = new Map();
73 addCurrentIndent(); 67 addCurrentIndent();
74 sb.add("<"); 68 sb.add("<");
75 addBeginAndEndTokensToParams(node, params); 69 addBeginAndEndTokensToParams(node, params);
76 addTypeWithParams(type, params); 70 addTypeWithParams(type, params);
77 sb.add("/>\n"); 71 sb.add("/>\n");
78 } 72 }
79 73
80 /** 74 /**
81 * Closes current node type, decreasing current depth by 1. 75 * Closes current node type.
82 */ 76 */
83 void closeNode() { 77 void closeNode() {
84 depth--; 78 String tag = popTag();
85 addCurrentIndent(); 79 addCurrentIndent();
86 sb.add("</"); 80 sb.add("</");
87 addTypeWithParams(popCurrentNodeType()); 81 addTypeWithParams(tag);
88 sb.add(">\n"); 82 sb.add(">\n");
89 } 83 }
90 84
91 void addTypeWithParams(String type, [Map params]) { 85 void addTypeWithParams(String type, [Map params]) {
92 if (params === null) params = new Map(); 86 if (params === null) params = new Map();
93 if (nextTypePrefix !== null) {
94 sb.add(nextTypePrefix);
95 nextTypePrefix = null;
96 }
97 sb.add("${type}"); 87 sb.add("${type}");
98 // TODO(smok): Escape doublequotes in values.
99 params.forEach((k, v) { 88 params.forEach((k, v) {
100 sb.add(' $k='); 89 String value;
101 if (v !== null) { 90 if (v !== null) {
102 sb.add('"$v"'); 91 value = v
92 .replaceAll("<", "&lt;")
93 .replaceAll(">", "&gt;")
94 .replaceAll('"', "'");
103 } else { 95 } else {
104 sb.add('null'); 96 value = "[null]";
105 } 97 }
98 sb.add(' $k="$value"');
106 }); 99 });
107 } 100 }
108 101
109 void addCurrentIndent() { 102 void addCurrentIndent() {
110 for (int i = 0; i < depth; i++) { 103 tagStack.forEach((_) { sb.add(INDENT); });
111 sb.add(INDENT);
112 }
113 } 104 }
114 105
115 /** 106 /**
116 * Pretty-prints given node tree into string. 107 * Pretty-prints given node tree into string.
117 */ 108 */
118 static String prettyPrint(Node node) { 109 static String prettyPrint(Node node) {
119 var p = new PrettyPrinter(); 110 var p = new PrettyPrinter();
120 node.accept(p); 111 node.accept(p);
121 return p.sb.toString(); 112 return p.sb.toString();
122 } 113 }
(...skipping 25 matching lines...) Expand all
148 } 139 }
149 140
150 visitCatchBlock(CatchBlock node) { 141 visitCatchBlock(CatchBlock node) {
151 visitNodeWithChildren(node, "CatchBlock"); 142 visitNodeWithChildren(node, "CatchBlock");
152 } 143 }
153 144
154 visitClassNode(ClassNode node) { 145 visitClassNode(ClassNode node) {
155 openNode(node, "ClassNode", { 146 openNode(node, "ClassNode", {
156 "extendsKeyword" : tokenToStringOrNull(node.extendsKeyword) 147 "extendsKeyword" : tokenToStringOrNull(node.extendsKeyword)
157 }); 148 });
158 visitWithPrefix(node.name, "name:"); 149 visitChildNode(node.name, "name");
159 visitWithPrefix(node.superclass, "superclass:"); 150 visitChildNode(node.superclass, "superclass");
160 visitWithPrefix(node.interfaces, "interfaces:"); 151 visitChildNode(node.interfaces, "interfaces");
161 visitWithPrefix(node.typeParameters, "typeParameters:"); 152 visitChildNode(node.typeParameters, "typeParameters");
162 visitWithPrefix(node.defaultClause, "defaultClause:"); 153 visitChildNode(node.defaultClause, "defaultClause");
163 closeNode(); 154 closeNode();
164 } 155 }
165 156
166 visitConditional(Conditional node) { 157 visitConditional(Conditional node) {
167 visitNodeWithChildren(node, "Conditional"); 158 visitNodeWithChildren(node, "Conditional");
168 } 159 }
169 160
170 visitContinueStatement(ContinueStatement node) { 161 visitContinueStatement(ContinueStatement node) {
171 visitNodeWithChildren(node, "ContinueStatement"); 162 visitNodeWithChildren(node, "ContinueStatement");
172 } 163 }
(...skipping 19 matching lines...) Expand all
192 } 183 }
193 184
194 visitFunctionDeclaration(FunctionDeclaration node) { 185 visitFunctionDeclaration(FunctionDeclaration node) {
195 visitNodeWithChildren(node, "FunctionDeclaration"); 186 visitNodeWithChildren(node, "FunctionDeclaration");
196 } 187 }
197 188
198 visitFunctionExpression(FunctionExpression node) { 189 visitFunctionExpression(FunctionExpression node) {
199 openNode(node, "FunctionExpression", { 190 openNode(node, "FunctionExpression", {
200 "getOrSet" : tokenToStringOrNull(node.getOrSet) 191 "getOrSet" : tokenToStringOrNull(node.getOrSet)
201 }); 192 });
202 visitWithPrefix(node.modifiers, "modifiers:"); 193 visitChildNode(node.modifiers, "modifiers");
203 visitWithPrefix(node.returnType, "returnType:"); 194 visitChildNode(node.returnType, "returnType");
204 visitWithPrefix(node.name, "name:"); 195 visitChildNode(node.name, "name");
205 visitWithPrefix(node.parameters, "parameters:"); 196 visitChildNode(node.parameters, "parameters");
206 visitWithPrefix(node.initializers, "initializers:"); 197 visitChildNode(node.initializers, "initializers");
207 visitWithPrefix(node.body, "body:"); 198 visitChildNode(node.body, "body");
208 closeNode(); 199 closeNode();
209 } 200 }
210 201
211 visitIdentifier(Identifier node) { 202 visitIdentifier(Identifier node) {
212 openAndCloseNode(node, "Identifier", {"token" : node.token.slowToString()}); 203 openAndCloseNode(node, "Identifier", {"token" : node.token.slowToString()});
213 } 204 }
214 205
215 visitIf(If node) { 206 visitIf(If node) {
216 visitNodeWithChildren(node, "If"); 207 visitNodeWithChildren(node, "If");
217 } 208 }
(...skipping 23 matching lines...) Expand all
241 visitLiteral(node, "LiteralInt"); 232 visitLiteral(node, "LiteralInt");
242 } 233 }
243 234
244 /** Returns token string value or [null] if token is [null]. */ 235 /** Returns token string value or [null] if token is [null]. */
245 tokenToStringOrNull(Token token) => token === null ? null : token.stringValue; 236 tokenToStringOrNull(Token token) => token === null ? null : token.stringValue;
246 237
247 visitLiteralList(LiteralList node) { 238 visitLiteralList(LiteralList node) {
248 openNode(node, "LiteralList", { 239 openNode(node, "LiteralList", {
249 "constKeyword" : tokenToStringOrNull(node.constKeyword) 240 "constKeyword" : tokenToStringOrNull(node.constKeyword)
250 }); 241 });
251 visitWithPrefix(node.typeArguments, "typeArguments:"); 242 visitChildNode(node.typeArguments, "typeArguments");
252 visitWithPrefix(node.elements, "elements:"); 243 visitChildNode(node.elements, "elements");
253 closeNode(); 244 closeNode();
254 } 245 }
255 246
256 visitLiteralMap(LiteralMap node) { 247 visitLiteralMap(LiteralMap node) {
257 visitNodeWithChildren(node, "LiteralMap"); 248 visitNodeWithChildren(node, "LiteralMap");
258 } 249 }
259 250
260 visitLiteralMapEntry(LiteralMapEntry node) { 251 visitLiteralMapEntry(LiteralMapEntry node) {
261 visitNodeWithChildren(node, "LiteralMapEntry"); 252 visitNodeWithChildren(node, "LiteralMapEntry");
262 } 253 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 visitOperator(Operator node) { 290 visitOperator(Operator node) {
300 openAndCloseNode(node, "Operator", {"value" : node.token.slowToString()}); 291 openAndCloseNode(node, "Operator", {"value" : node.token.slowToString()});
301 } 292 }
302 293
303 visitParenthesizedExpression(ParenthesizedExpression node) { 294 visitParenthesizedExpression(ParenthesizedExpression node) {
304 visitNodeWithChildren(node, "ParenthesizedExpression"); 295 visitNodeWithChildren(node, "ParenthesizedExpression");
305 } 296 }
306 297
307 visitReturn(Return node) { 298 visitReturn(Return node) {
308 openNode(node, "Return"); 299 openNode(node, "Return");
309 visitWithPrefix(node.expression, "expression:"); 300 visitChildNode(node.expression, "expression");
310 closeNode(); 301 closeNode();
311 } 302 }
312 303
313 visitScriptTag(ScriptTag node) { 304 visitScriptTag(ScriptTag node) {
314 visitNodeWithChildren(node, "ScriptTag"); 305 visitNodeWithChildren(node, "ScriptTag");
315 } 306 }
316 307
317 /** Custom helper to visit given node and print its type with prefix. */ 308 visitChildNode(Node node, String fieldName) {
318 visitWithPrefix(Node node, String prefix) {
319 if (node === null) return; 309 if (node === null) return;
320 nextTypePrefix = prefix; 310 addCurrentIndent();
311 sb.add("<$fieldName>\n");
312 pushTag(fieldName);
321 node.accept(this); 313 node.accept(this);
314 popTag();
315 addCurrentIndent();
316 sb.add("</$fieldName>\n");
322 } 317 }
323 318
324 openSendNodeWithFields(Send node, String type) { 319 openSendNodeWithFields(Send node, String type) {
325 openNode(node, type, { 320 openNode(node, type, {
326 "isPrefix" : "${node.isPrefix}", 321 "isPrefix" : "${node.isPrefix}",
327 "isPostfix" : "${node.isPostfix}", 322 "isPostfix" : "${node.isPostfix}",
328 "isIndex" : "${node.isIndex}" 323 "isIndex" : "${node.isIndex}"
329 }); 324 });
330 visitWithPrefix(node.receiver, "receiver:"); 325 visitChildNode(node.receiver, "receiver");
331 visitWithPrefix(node.selector, "selector:"); 326 visitChildNode(node.selector, "selector");
332 visitWithPrefix(node.argumentsNode, "argumentsNode:"); 327 visitChildNode(node.argumentsNode, "argumentsNode");
333 } 328 }
334 329
335 visitSend(Send node) { 330 visitSend(Send node) {
336 openSendNodeWithFields(node, "Send"); 331 openSendNodeWithFields(node, "Send");
337 closeNode(); 332 closeNode();
338 } 333 }
339 334
340 visitSendSet(SendSet node) { 335 visitSendSet(SendSet node) {
341 openSendNodeWithFields(node, "SendSet"); 336 openSendNodeWithFields(node, "SendSet");
342 visitWithPrefix(node.assignmentOperator, "assignmentOperator:"); 337 visitChildNode(node.assignmentOperator, "assignmentOperator");
343 closeNode(); 338 closeNode();
344 } 339 }
345 340
346 visitStringInterpolation(StringInterpolation node) { 341 visitStringInterpolation(StringInterpolation node) {
347 visitNodeWithChildren(node, "StringInterpolation"); 342 visitNodeWithChildren(node, "StringInterpolation");
348 } 343 }
349 344
350 visitStringInterpolationPart(StringInterpolationPart node) { 345 visitStringInterpolationPart(StringInterpolationPart node) {
351 visitNodeWithChildren(node, "StringInterpolationPart"); 346 visitNodeWithChildren(node, "StringInterpolationPart");
352 } 347 }
(...skipping 13 matching lines...) Expand all
366 visitThrow(Throw node) { 361 visitThrow(Throw node) {
367 visitNodeWithChildren(node, "Throw"); 362 visitNodeWithChildren(node, "Throw");
368 } 363 }
369 364
370 visitTryStatement(TryStatement node) { 365 visitTryStatement(TryStatement node) {
371 visitNodeWithChildren(node, "TryStatement"); 366 visitNodeWithChildren(node, "TryStatement");
372 } 367 }
373 368
374 visitTypeAnnotation(TypeAnnotation node) { 369 visitTypeAnnotation(TypeAnnotation node) {
375 openNode(node, "TypeAnnotation"); 370 openNode(node, "TypeAnnotation");
376 visitWithPrefix(node.typeName, "typeName:"); 371 visitChildNode(node.typeName, "typeName");
377 visitWithPrefix(node.typeArguments, "typeArguments:"); 372 visitChildNode(node.typeArguments, "typeArguments");
378 closeNode(); 373 closeNode();
379 } 374 }
380 375
381 visitTypedef(Typedef node) { 376 visitTypedef(Typedef node) {
382 visitNodeWithChildren(node, "Typedef"); 377 visitNodeWithChildren(node, "Typedef");
383 } 378 }
384 379
385 visitTypeVariable(TypeVariable node) { 380 visitTypeVariable(TypeVariable node) {
386 openNode(node, "TypeVariable"); 381 openNode(node, "TypeVariable");
387 visitWithPrefix(node.name, "name:"); 382 visitChildNode(node.name, "name");
388 visitWithPrefix(node.bound, "bound:"); 383 visitChildNode(node.bound, "bound");
389 closeNode(); 384 closeNode();
390 } 385 }
391 386
392 visitVariableDefinitions(VariableDefinitions node) { 387 visitVariableDefinitions(VariableDefinitions node) {
393 openNode(node, "VariableDefinitions"); 388 openNode(node, "VariableDefinitions");
394 visitWithPrefix(node.type, "type:"); 389 visitChildNode(node.type, "type");
395 visitWithPrefix(node.modifiers, "modifiers:"); 390 visitChildNode(node.modifiers, "modifiers");
396 visitWithPrefix(node.definitions, "definitions:"); 391 visitChildNode(node.definitions, "definitions");
397 closeNode(); 392 closeNode();
398 } 393 }
399 394
400 visitWhile(While node) { 395 visitWhile(While node) {
401 visitNodeWithChildren(node, "While"); 396 visitNodeWithChildren(node, "While");
402 } 397 }
403 } 398 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698