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

Side by Side Diff: frog/leg/tree/nodes.dart

Issue 9873021: Move frog/leg to lib/compiler/implementation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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 | « frog/leg/tree/dartstring.dart ('k') | frog/leg/tree/tree.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 interface Visitor<R> {
6 R visitBlock(Block node);
7 R visitBreakStatement(BreakStatement node);
8 R visitCatchBlock(CatchBlock node);
9 R visitClassNode(ClassNode node);
10 R visitConditional(Conditional node);
11 R visitContinueStatement(ContinueStatement node);
12 R visitDoWhile(DoWhile node);
13 R visitEmptyStatement(EmptyStatement node);
14 R visitExpressionStatement(ExpressionStatement node);
15 R visitFor(For node);
16 R visitForInStatement(ForInStatement node);
17 R visitFunctionDeclaration(FunctionDeclaration node);
18 R visitFunctionExpression(FunctionExpression node);
19 R visitIdentifier(Identifier node);
20 R visitIf(If node);
21 R visitLabeledStatement(LabeledStatement node);
22 R visitLiteralBool(LiteralBool node);
23 R visitLiteralDouble(LiteralDouble node);
24 R visitLiteralInt(LiteralInt node);
25 R visitLiteralList(LiteralList node);
26 R visitLiteralMap(LiteralMap node);
27 R visitLiteralMapEntry(LiteralMapEntry node);
28 R visitLiteralNull(LiteralNull node);
29 R visitLiteralString(LiteralString node);
30 R visitStringJuxtaposition(StringJuxtaposition node);
31 R visitModifiers(Modifiers node);
32 R visitNamedArgument(NamedArgument node);
33 R visitNewExpression(NewExpression node);
34 R visitNodeList(NodeList node);
35 R visitOperator(Operator node);
36 R visitParenthesizedExpression(ParenthesizedExpression node);
37 R visitReturn(Return node);
38 R visitScriptTag(ScriptTag node);
39 R visitSend(Send node);
40 R visitSendSet(SendSet node);
41 R visitStringInterpolation(StringInterpolation node);
42 R visitStringInterpolationPart(StringInterpolationPart node);
43 R visitSwitchCase(SwitchCase node);
44 R visitSwitchStatement(SwitchStatement node);
45 R visitThrow(Throw node);
46 R visitTryStatement(TryStatement node);
47 R visitTypeAnnotation(TypeAnnotation node);
48 R visitTypedef(Typedef node);
49 R visitTypeVariable(TypeVariable node);
50 R visitVariableDefinitions(VariableDefinitions node);
51 R visitWhile(While node);
52 }
53
54 Token firstBeginToken(Node first, Node second) {
55 if (first !== null) return first.getBeginToken();
56 if (second !== null) return second.getBeginToken();
57 return null;
58 }
59
60 class NodeAssertionFailure implements Exception {
61 final Node node;
62 final String message;
63 NodeAssertionFailure(this.node, this.message);
64 }
65
66 /**
67 * A node in a syntax tree.
68 *
69 * The abstract part of "abstract syntax tree" is invalidated when
70 * supporting tools such as code formatting. These tools need concrete
71 * syntax such as parentheses and no constant folding.
72 *
73 * We support these tools by storing additional references back to the
74 * token stream. These references are stored in fields ending with
75 * "Token".
76 */
77 class Node implements Hashable {
78 final int _hashCode;
79 static int _HASH_COUNTER = 0;
80
81 Node() : _hashCode = ++_HASH_COUNTER;
82
83 hashCode() => _hashCode;
84
85 abstract accept(Visitor visitor);
86
87 abstract visitChildren(Visitor visitor);
88
89 toString() => unparse(false);
90
91 toDebugString() => unparse(true);
92
93 String getObjectDescription() => super.toString();
94
95 String unparse(bool printDebugInfo) {
96 Unparser unparser = new Unparser(printDebugInfo);
97 try {
98 return unparser.unparse(this);
99 } catch (var e, var trace) {
100 print(trace);
101 return '<<unparse error: ${getObjectDescription()}: ${unparser.sb}>>';
102 }
103 }
104
105 abstract Token getBeginToken();
106
107 abstract Token getEndToken();
108
109 Block asBlock() => null;
110 BreakStatement asBreakStatement() => null;
111 CatchBlock asCatchBlock() => null;
112 ClassNode asClassNode() => null;
113 Conditional asConditional() => null;
114 ContinueStatement asContinueStatement() => null;
115 DoWhile asDoWhile() => null;
116 EmptyStatement asEmptyStatement() => null;
117 Expression asExpression() => null;
118 ExpressionStatement asExpressionStatement() => null;
119 For asFor() => null;
120 ForInStatement asForInStatement() => null;
121 FunctionDeclaration asFunctionDeclaration() => null;
122 FunctionExpression asFunctionExpression() => null;
123 Identifier asIdentifier() => null;
124 If asIf() => null;
125 LabeledStatement asLabeledStatement() => null;
126 LiteralBool asLiteralBool() => null;
127 LiteralDouble asLiteralDouble() => null;
128 LiteralInt asLiteralInt() => null;
129 LiteralList asLiteralList() => null;
130 LiteralMap asLiteralMap() => null;
131 LiteralMapEntry asLiteralMapEntry() => null;
132 LiteralNull asLiteralNull() => null;
133 LiteralString asLiteralString() => null;
134 Modifiers asModifiers() => null;
135 NamedArgument asNamedArgument() => null;
136 NodeList asNodeList() => null;
137 Operator asOperator() => null;
138 ParenthesizedExpression asParenthesizedExpression() => null;
139 Return asReturn() => null;
140 ScriptTag asScriptTag() => null;
141 Send asSend() => null;
142 SendSet asSendSet() => null;
143 Statement asStatement() => null;
144 StringInterpolation asStringInterpolation() => null;
145 StringInterpolationPart asStringInterpolationPart() => null;
146 StringJuxtaposition asStringJuxtaposition() => null;
147 SwitchCase asSwitchCase() => null;
148 SwitchStatement asSwitchStatement() => null;
149 Throw asThrow() => null;
150 TryStatement asTryStatement() => null;
151 TypeAnnotation asTypeAnnotation() => null;
152 Typedef asTypedef() => null;
153 TypeVariable asTypeVariable() => null;
154 VariableDefinitions asVariableDefinitions() => null;
155 While asWhile() => null;
156
157 bool isValidBreakTarget() => false;
158 bool isValidContinueTarget() => false;
159 }
160
161 class ClassNode extends Node {
162 final Identifier name;
163 final TypeAnnotation superclass;
164 final NodeList interfaces;
165 final NodeList typeParameters;
166
167 // TODO(ahe, karlklose): the default keyword is not recorded.
168 final TypeAnnotation defaultClause;
169
170 final Token beginToken;
171 final Token extendsKeyword;
172 final Token endToken;
173
174 ClassNode(this.name, this.typeParameters, this.superclass, this.interfaces,
175 this.defaultClause, this.beginToken, this.extendsKeyword,
176 this.endToken);
177
178 ClassNode asClassNode() => this;
179
180 accept(Visitor visitor) => visitor.visitClassNode(this);
181
182 visitChildren(Visitor visitor) {
183 if (name !== null) name.accept(visitor);
184 if (superclass !== null) superclass.accept(visitor);
185 if (interfaces !== null) interfaces.accept(visitor);
186 }
187
188 bool get isInterface() => beginToken.stringValue === 'interface';
189
190 bool get isClass() => !isInterface;
191
192 Token getBeginToken() => beginToken;
193
194 Token getEndToken() => endToken;
195 }
196
197 class Expression extends Node {
198 Expression();
199
200 Expression asExpression() => this;
201
202 // TODO(ahe): make class abstract instead of adding an abstract method.
203 abstract accept(Visitor visitor);
204 }
205
206 class Statement extends Node {
207 Statement();
208
209 Statement asStatement() => this;
210
211 // TODO(ahe): make class abstract instead of adding an abstract method.
212 abstract accept(Visitor visitor);
213
214 bool isValidBreakTarget() => true;
215 }
216
217 /**
218 * A message send aka method invocation. In Dart, most operations can
219 * (and should) be considered as message sends. Getters and setters
220 * are just methods with a special syntax. Consequently, we model
221 * property access, assignment, operators, and method calls with this
222 * one node.
223 */
224 class Send extends Expression {
225 final Node receiver;
226 final Node selector;
227 final NodeList argumentsNode;
228 Link<Node> get arguments() => argumentsNode.nodes;
229
230 Send([this.receiver, this.selector, this.argumentsNode]);
231 Send.postfix(this.receiver, this.selector, [Node argument = null])
232 : argumentsNode = (argument === null)
233 ? new Postfix()
234 : new Postfix.singleton(argument);
235 Send.prefix(this.receiver, this.selector, [Node argument = null])
236 : argumentsNode = (argument === null)
237 ? new Prefix()
238 : new Prefix.singleton(argument);
239
240 Send asSend() => this;
241
242 accept(Visitor visitor) => visitor.visitSend(this);
243
244 visitChildren(Visitor visitor) {
245 if (receiver !== null) receiver.accept(visitor);
246 if (selector !== null) selector.accept(visitor);
247 if (argumentsNode !== null) argumentsNode.accept(visitor);
248 }
249
250 int argumentCount() => argumentsNode.length();
251
252 bool get isSuperCall() {
253 return receiver !== null &&
254 receiver.asIdentifier() !== null &&
255 receiver.asIdentifier().isSuper();
256 }
257 bool get isOperator() => selector is Operator;
258 bool get isPropertyAccess() => argumentsNode === null;
259 bool get isFunctionObjectInvocation() => selector === null;
260 bool get isPrefix() => argumentsNode is Prefix;
261 bool get isPostfix() => argumentsNode is Postfix;
262 bool get isIndex() =>
263 isOperator && selector.asOperator().source.stringValue === '[]';
264
265 Token getBeginToken() {
266 if (isPrefix && !isIndex) return selector.getBeginToken();
267 return firstBeginToken(receiver, selector);
268 }
269
270 Token getEndToken() {
271 if (isPrefix) {
272 if (receiver !== null) return receiver.getEndToken();
273 if (selector !== null) return selector.getEndToken();
274 return null;
275 }
276 if (!isPostfix && argumentsNode !== null) {
277 return argumentsNode.getEndToken();
278 }
279 if (selector !== null) return selector.getEndToken();
280 return receiver.getBeginToken();
281 }
282
283 Send copyWithReceiver(Node newReceiver) {
284 assert(receiver === null);
285 return new Send(newReceiver, selector, argumentsNode);
286 }
287 }
288
289 class Postfix extends NodeList {
290 Postfix() : super(nodes: const EmptyLink<Node>());
291 Postfix.singleton(Node argument) : super.singleton(argument);
292 }
293
294 class Prefix extends NodeList {
295 Prefix() : super(nodes: const EmptyLink<Node>());
296 Prefix.singleton(Node argument) : super.singleton(argument);
297 }
298
299 class SendSet extends Send {
300 final Operator assignmentOperator;
301 SendSet(receiver, selector, this.assignmentOperator, argumentsNode)
302 : super(receiver, selector, argumentsNode);
303 SendSet.postfix(receiver,
304 selector,
305 this.assignmentOperator,
306 [Node argument = null])
307 : super.postfix(receiver, selector, argument);
308 SendSet.prefix(receiver,
309 selector,
310 this.assignmentOperator,
311 [Node argument = null])
312 : super.prefix(receiver, selector, argument);
313
314 SendSet asSendSet() => this;
315
316 accept(Visitor visitor) => visitor.visitSendSet(this);
317
318 visitChildren(Visitor visitor) {
319 super.visitChildren(visitor);
320 if (assignmentOperator !== null) assignmentOperator.accept(visitor);
321 }
322
323 Send copyWithReceiver(Node newReceiver) {
324 assert(receiver === null);
325 return new SendSet(newReceiver, selector, assignmentOperator,
326 argumentsNode);
327 }
328 }
329
330 class NewExpression extends Expression {
331 /** The token NEW or CONST */
332 final Token newToken;
333
334 // Note: we expect that send.receiver is null.
335 final Send send;
336
337 NewExpression([this.newToken, this.send]);
338
339 accept(Visitor visitor) => visitor.visitNewExpression(this);
340
341 visitChildren(Visitor visitor) {
342 if (send !== null) send.accept(visitor);
343 }
344
345 bool isConst() => newToken.stringValue === 'const';
346
347 Token getBeginToken() => newToken;
348
349 Token getEndToken() => send.getEndToken();
350 }
351
352 class NodeList extends Node implements Iterable<Node> {
353 final Link<Node> nodes;
354 final Token beginToken;
355 final Token endToken;
356 final SourceString delimiter;
357 bool isEmpty() => nodes.isEmpty();
358
359 NodeList([this.beginToken, this.nodes, this.endToken, this.delimiter]);
360
361 Iterator<Node> iterator() => nodes.iterator();
362
363 NodeList.singleton(Node node) : this(null, new Link<Node>(node));
364 NodeList.empty() : this(null, const EmptyLink<Node>());
365
366 NodeList asNodeList() => this;
367
368 int length() {
369 int result = 0;
370 for (Link<Node> cursor = nodes; !cursor.isEmpty(); cursor = cursor.tail) {
371 result++;
372 }
373 return result;
374 }
375
376 accept(Visitor visitor) => visitor.visitNodeList(this);
377
378 visitChildren(Visitor visitor) {
379 if (nodes === null) return;
380 for (Link<Node> link = nodes; !link.isEmpty(); link = link.tail) {
381 if (link.head !== null) link.head.accept(visitor);
382 }
383 }
384
385 Token getBeginToken() {
386 if (beginToken !== null) return beginToken;
387 if (nodes !== null) {
388 for (Link<Node> link = nodes; !link.isEmpty(); link = link.tail) {
389 if (link.head.getBeginToken() !== null) {
390 return link.head.getBeginToken();
391 }
392 if (link.head.getEndToken() !== null) {
393 return link.head.getEndToken();
394 }
395 }
396 }
397 return endToken;
398 }
399
400 Token getEndToken() {
401 if (endToken !== null) return endToken;
402 if (nodes !== null) {
403 Link<Node> link = nodes;
404 if (link.isEmpty()) return beginToken;
405 while (!link.tail.isEmpty()) link = link.tail;
406 if (link.head.getEndToken() !== null) return link.head.getEndToken();
407 if (link.head.getBeginToken() !== null) return link.head.getBeginToken();
408 }
409 return beginToken;
410 }
411 }
412
413 class Block extends Statement {
414 final NodeList statements;
415
416 Block(this.statements);
417
418 Block asBlock() => this;
419
420 accept(Visitor visitor) => visitor.visitBlock(this);
421
422 visitChildren(Visitor visitor) {
423 if (statements !== null) statements.accept(visitor);
424 }
425
426 Token getBeginToken() => statements.getBeginToken();
427
428 Token getEndToken() => statements.getEndToken();
429 }
430
431 class If extends Statement {
432 final ParenthesizedExpression condition;
433 final Statement thenPart;
434 final Statement elsePart;
435
436 final Token ifToken;
437 final Token elseToken;
438
439 If(this.condition, this.thenPart, this.elsePart,
440 this.ifToken, this.elseToken);
441
442 If asIf() => this;
443
444 bool get hasElsePart() => elsePart !== null;
445
446 void validate() {
447 // TODO(ahe): Check that condition has size one.
448 }
449
450 accept(Visitor visitor) => visitor.visitIf(this);
451
452 visitChildren(Visitor visitor) {
453 if (condition !== null) condition.accept(visitor);
454 if (thenPart !== null) thenPart.accept(visitor);
455 if (elsePart !== null) elsePart.accept(visitor);
456 }
457
458 Token getBeginToken() => ifToken;
459
460 Token getEndToken() {
461 if (elsePart === null) return thenPart.getEndToken();
462 return elsePart.getEndToken();
463 }
464 }
465
466 class Conditional extends Expression {
467 final Expression condition;
468 final Expression thenExpression;
469 final Expression elseExpression;
470
471 final Token questionToken;
472 final Token colonToken;
473
474 Conditional(this.condition, this.thenExpression,
475 this.elseExpression, this.questionToken, this.colonToken);
476
477 Conditional asConditional() => this;
478
479 accept(Visitor visitor) => visitor.visitConditional(this);
480
481 visitChildren(Visitor visitor) {
482 condition.accept(visitor);
483 thenExpression.accept(visitor);
484 elseExpression.accept(visitor);
485 }
486
487 Token getBeginToken() => condition.getBeginToken();
488
489 Token getEndToken() => elseExpression.getEndToken();
490 }
491
492 class For extends Loop {
493 /** Either a variable declaration or an expression. */
494 final Node initializer;
495 /** Either an expression statement or an empty statement. */
496 final Statement conditionStatement;
497 final NodeList update;
498
499 final Token forToken;
500
501 For(this.initializer, this.conditionStatement, this.update, body,
502 this.forToken) : super(body);
503
504 For asFor() => this;
505
506 Expression get condition() {
507 if (conditionStatement is ExpressionStatement) {
508 return conditionStatement.asExpressionStatement().expression;
509 } else {
510 return null;
511 }
512 }
513
514 accept(Visitor visitor) => visitor.visitFor(this);
515
516 visitChildren(Visitor visitor) {
517 if (initializer !== null) initializer.accept(visitor);
518 if (conditionStatement !== null) conditionStatement.accept(visitor);
519 if (update !== null) update.accept(visitor);
520 if (body !== null) body.accept(visitor);
521 }
522
523 Token getBeginToken() => forToken;
524
525 Token getEndToken() {
526 return body.getEndToken();
527 }
528 }
529
530 class FunctionDeclaration extends Statement {
531 final FunctionExpression function;
532
533 FunctionDeclaration(this.function);
534
535 FunctionDeclaration asFunctionDeclaration() => this;
536
537 accept(Visitor visitor) => visitor.visitFunctionDeclaration(this);
538
539 visitChildren(Visitor visitor) => function.accept(visitor);
540
541 Token getBeginToken() => function.getBeginToken();
542 Token getEndToken() => function.getEndToken();
543 }
544
545 class FunctionExpression extends Expression {
546 final Node name;
547
548 /**
549 * List of VariableDefinitions or NodeList.
550 *
551 * A NodeList can only occur at the end and holds named parameters.
552 */
553 final NodeList parameters;
554
555 final Statement body;
556 final TypeAnnotation returnType;
557 final Modifiers modifiers;
558 final NodeList initializers;
559
560 final Token getOrSet;
561
562 FunctionExpression(this.name, this.parameters, this.body, this.returnType,
563 this.modifiers, this.initializers, this.getOrSet);
564
565 FunctionExpression asFunctionExpression() => this;
566
567 accept(Visitor visitor) => visitor.visitFunctionExpression(this);
568
569 visitChildren(Visitor visitor) {
570 if (modifiers !== null) modifiers.accept(visitor);
571 if (returnType !== null) returnType.accept(visitor);
572 if (name !== null) name.accept(visitor);
573 if (parameters !== null) parameters.accept(visitor);
574 if (initializers !== null) initializers.accept(visitor);
575 if (body !== null) body.accept(visitor);
576 }
577
578 bool hasBody() {
579 // TODO(karlklose,ahe): refactor AST nodes (issue 1713).
580 if (body.asReturn() !== null) return true;
581 NodeList statements = body.asBlock().statements;
582 return (!statements.nodes.isEmpty() ||
583 statements.getBeginToken().kind !== $SEMICOLON);
584 }
585
586 Token getBeginToken() {
587 Token token = firstBeginToken(modifiers, returnType);
588 if (token !== null) return token;
589 if (getOrSet !== null) return getOrSet;
590 return firstBeginToken(name, parameters);
591 }
592
593 Token getEndToken() {
594 Token token = (body === null) ? null : body.getEndToken();
595 token = (token === null) ? parameters.getEndToken() : token;
596 return (token === null) ? name.getEndToken() : token;
597 }
598 }
599
600 typedef void DecodeErrorHandler(Token token, var error);
601
602 class Literal<T> extends Expression {
603 final Token token;
604 final DecodeErrorHandler handler;
605
606 Literal(Token this.token, DecodeErrorHandler this.handler);
607
608 abstract T get value();
609
610 visitChildren(Visitor visitor) {}
611
612 Token getBeginToken() => token;
613
614 Token getEndToken() => token;
615 }
616
617 class LiteralInt extends Literal<int> {
618 LiteralInt(Token token, DecodeErrorHandler handler) : super(token, handler);
619
620 LiteralInt asLiteralInt() => this;
621
622 int get value() {
623 try {
624 Token token = this.token;
625 if (token.kind === PLUS_TOKEN) token = token.next;
626 return Math.parseInt(token.value.slowToString());
627 } catch (BadNumberFormatException ex) {
628 (this.handler)(token, ex);
629 }
630 }
631
632 accept(Visitor visitor) => visitor.visitLiteralInt(this);
633 }
634
635 class LiteralDouble extends Literal<double> {
636 LiteralDouble(Token token, DecodeErrorHandler handler)
637 : super(token, handler);
638
639 LiteralDouble asLiteralDouble() => this;
640
641 double get value() {
642 try {
643 Token token = this.token;
644 if (token.kind === PLUS_TOKEN) token = token.next;
645 return Math.parseDouble(token.value.slowToString());
646 } catch (BadNumberFormatException ex) {
647 (this.handler)(token, ex);
648 }
649 }
650
651 accept(Visitor visitor) => visitor.visitLiteralDouble(this);
652 }
653
654 class LiteralBool extends Literal<bool> {
655 LiteralBool(Token token, DecodeErrorHandler handler) : super(token, handler);
656
657 LiteralBool asLiteralBool() => this;
658
659 bool get value() {
660 switch (token.value) {
661 case Keyword.TRUE: return true;
662 case Keyword.FALSE: return false;
663 default:
664 (this.handler)(token, "not a bool ${token.value}");
665 }
666 }
667
668 accept(Visitor visitor) => visitor.visitLiteralBool(this);
669 }
670
671
672 class StringQuoting {
673 static final StringQuoting SINGLELINE_DQ =
674 const StringQuoting($DQ, raw: false, leftQuoteLength: 1);
675 static final StringQuoting RAW_SINGLELINE_DQ =
676 const StringQuoting($DQ, raw: true, leftQuoteLength: 1);
677 static final StringQuoting MULTILINE_DQ =
678 const StringQuoting($DQ, raw: false, leftQuoteLength: 3);
679 static final StringQuoting RAW_MULTILINE_DQ =
680 const StringQuoting($DQ, raw: true, leftQuoteLength: 3);
681 static final StringQuoting MULTILINE_NL_DQ =
682 const StringQuoting($DQ, raw: false, leftQuoteLength: 4);
683 static final StringQuoting RAW_MULTILINE_NL_DQ =
684 const StringQuoting($DQ, raw: true, leftQuoteLength: 4);
685 static final StringQuoting MULTILINE_NL2_DQ =
686 const StringQuoting($DQ, raw: false, leftQuoteLength: 5);
687 static final StringQuoting RAW_MULTILINE_NL2_DQ =
688 const StringQuoting($DQ, raw: true, leftQuoteLength: 5);
689 static final StringQuoting SINGLELINE_SQ =
690 const StringQuoting($SQ, raw: false, leftQuoteLength: 1);
691 static final StringQuoting RAW_SINGLELINE_SQ =
692 const StringQuoting($SQ, raw: true, leftQuoteLength: 1);
693 static final StringQuoting MULTILINE_SQ =
694 const StringQuoting($SQ, raw: false, leftQuoteLength: 3);
695 static final StringQuoting RAW_MULTILINE_SQ =
696 const StringQuoting($SQ, raw: true, leftQuoteLength: 3);
697 static final StringQuoting MULTILINE_NL_SQ =
698 const StringQuoting($SQ, raw: false, leftQuoteLength: 4);
699 static final StringQuoting RAW_MULTILINE_NL_SQ =
700 const StringQuoting($SQ, raw: true, leftQuoteLength: 4);
701 static final StringQuoting MULTILINE_NL2_SQ =
702 const StringQuoting($SQ, raw: false, leftQuoteLength: 5);
703 static final StringQuoting RAW_MULTILINE_NL2_SQ =
704 const StringQuoting($SQ, raw: true, leftQuoteLength: 5);
705
706
707 static final List<StringQuoting> mapping = const <StringQuoting>[
708 SINGLELINE_DQ,
709 RAW_SINGLELINE_DQ,
710 MULTILINE_DQ,
711 RAW_MULTILINE_DQ,
712 MULTILINE_NL_DQ,
713 RAW_MULTILINE_NL_DQ,
714 MULTILINE_NL2_DQ,
715 RAW_MULTILINE_NL2_DQ,
716 SINGLELINE_SQ,
717 RAW_SINGLELINE_SQ,
718 MULTILINE_SQ,
719 RAW_MULTILINE_SQ,
720 MULTILINE_NL_SQ,
721 RAW_MULTILINE_NL_SQ,
722 MULTILINE_NL2_SQ,
723 RAW_MULTILINE_NL2_SQ
724 ];
725 final bool raw;
726 final int leftQuoteCharCount;
727 final int quote;
728 const StringQuoting(this.quote, [bool raw, int leftQuoteLength])
729 : this.raw = raw, this.leftQuoteCharCount = leftQuoteLength;
730 String get quoteChar() => quote === $DQ ? '"' : "'";
731
732 int get leftQuoteLength() => (raw ? 1 : 0) + leftQuoteCharCount;
733 int get rightQuoteLength() => (leftQuoteCharCount > 2) ? 3 : 1;
734 static StringQuoting getQuoting(int quote, bool raw, int quoteLength) {
735 int index = quoteLength - 1;
736 if (quoteLength > 2) index -= 1;
737 return mapping[(raw ? 1 : 0) + index * 2 + (quote === $SQ ? 8 : 0)];
738 }
739 }
740
741 /**
742 * Superclass for classes representing string literals.
743 */
744 class StringNode extends Expression {
745 abstract DartString get dartString();
746 abstract bool get isInterpolation();
747 }
748
749 class LiteralString extends StringNode {
750 final Token token;
751 /** Non-null on validated string literals. */
752 final DartString dartString;
753
754 LiteralString(this.token, this.dartString);
755
756 LiteralString asLiteralString() => this;
757
758 void visitChildren(Visitor visitor) {}
759
760 bool get isInterpolation() => false;
761 bool isValidated() => dartString !== null;
762
763 Token getBeginToken() => token;
764 Token getEndToken() => token;
765
766 accept(Visitor visitor) => visitor.visitLiteralString(this);
767 }
768
769 class LiteralNull extends Literal<SourceString> {
770 LiteralNull(Token token) : super(token, null);
771
772 LiteralNull asLiteralNull() => this;
773
774 SourceString get value() => null;
775
776 accept(Visitor visitor) => visitor.visitLiteralNull(this);
777 }
778
779 class LiteralList extends Expression {
780 final TypeAnnotation type;
781 final NodeList elements;
782
783 final Token constKeyword;
784
785 LiteralList(this.type, this.elements, this.constKeyword);
786
787 bool isConst() => constKeyword !== null;
788
789 LiteralList asLiteralList() => this;
790 accept(Visitor visitor) => visitor.visitLiteralList(this);
791
792 visitChildren(Visitor visitor) {
793 if (type !== null) type.accept(visitor);
794 elements.accept(visitor);
795 }
796
797 Token getBeginToken() {
798 if (constKeyword !== null) return constKeyword;
799 return firstBeginToken(type, elements);
800 }
801
802 Token getEndToken() => elements.getEndToken();
803 }
804
805 class Identifier extends Expression {
806 final Token token;
807
808 SourceString get source() => token.value;
809
810 Identifier(Token this.token);
811
812 bool isThis() => source.stringValue === 'this';
813
814 bool isSuper() => source.stringValue === 'super';
815
816 Identifier asIdentifier() => this;
817
818 accept(Visitor visitor) => visitor.visitIdentifier(this);
819
820 visitChildren(Visitor visitor) {}
821
822 Token getBeginToken() => token;
823
824 Token getEndToken() => token;
825 }
826
827 class Operator extends Identifier {
828 Operator(Token token) : super(token);
829
830 Operator asOperator() => this;
831
832 accept(Visitor visitor) => visitor.visitOperator(this);
833 }
834
835 class Return extends Statement {
836 final Expression expression;
837 final Token beginToken;
838 final Token endToken;
839
840 Return(this.beginToken, this.endToken, this.expression);
841
842 Return asReturn() => this;
843
844 bool get hasExpression() => expression !== null;
845
846 accept(Visitor visitor) => visitor.visitReturn(this);
847
848 visitChildren(Visitor visitor) {
849 if (expression !== null) expression.accept(visitor);
850 }
851
852 Token getBeginToken() => beginToken;
853
854 Token getEndToken() {
855 if (endToken === null) return expression.getEndToken();
856 return endToken;
857 }
858 }
859
860 class ExpressionStatement extends Statement {
861 final Expression expression;
862 final Token endToken;
863
864 ExpressionStatement(this.expression, this.endToken);
865
866 ExpressionStatement asExpressionStatement() => this;
867
868 accept(Visitor visitor) => visitor.visitExpressionStatement(this);
869
870 visitChildren(Visitor visitor) {
871 if (expression !== null) expression.accept(visitor);
872 }
873
874 Token getBeginToken() => expression.getBeginToken();
875
876 Token getEndToken() => endToken;
877 }
878
879 class Throw extends Statement {
880 final Expression expression;
881
882 final Token throwToken;
883 final Token endToken;
884
885 Throw(this.expression, this.throwToken, this.endToken);
886
887 Throw asThrow() => this;
888
889 accept(Visitor visitor) => visitor.visitThrow(this);
890
891 visitChildren(Visitor visitor) {
892 if (expression !== null) expression.accept(visitor);
893 }
894
895 Token getBeginToken() => throwToken;
896
897 Token getEndToken() => endToken;
898 }
899
900 class TypeAnnotation extends Node {
901 final Expression typeName;
902 final NodeList typeArguments;
903
904 TypeAnnotation(Expression this.typeName, NodeList this.typeArguments);
905
906 TypeAnnotation asTypeAnnotation() => this;
907
908 accept(Visitor visitor) => visitor.visitTypeAnnotation(this);
909
910 visitChildren(Visitor visitor) {
911 typeName.accept(visitor);
912 if (typeArguments !== null) typeArguments.accept(visitor);
913 }
914
915 Token getBeginToken() => typeName.getBeginToken();
916
917 Token getEndToken() => typeName.getEndToken();
918 }
919
920 class TypeVariable extends Node {
921 final Identifier name;
922 final TypeAnnotation bound;
923 TypeVariable(Identifier this.name, TypeAnnotation this.bound);
924
925 accept(Visitor visitor) => visitor.visitTypeVariable(this);
926
927 visitChildren(Visitor visitor) {
928 name.accept(visitor);
929 if (bound !== null) {
930 bound.accept(visitor);
931 }
932 }
933
934 TypeVariable asTypeVariable() => this;
935
936 Token getBeginToken() => name.getBeginToken();
937
938 Token getEndToken() {
939 return (bound !== null) ? bound.getEndToken() : name.getEndToken();
940 }
941 }
942
943 class VariableDefinitions extends Statement {
944 final Token endToken;
945 final TypeAnnotation type;
946 final Modifiers modifiers;
947 final NodeList definitions;
948 VariableDefinitions(this.type, this.modifiers, this.definitions,
949 this.endToken);
950
951 VariableDefinitions asVariableDefinitions() => this;
952
953 accept(Visitor visitor) => visitor.visitVariableDefinitions(this);
954
955 visitChildren(Visitor visitor) {
956 if (type !== null) type.accept(visitor);
957 if (definitions !== null) definitions.accept(visitor);
958 }
959
960 Token getBeginToken() {
961 return firstBeginToken(type, definitions);
962 }
963
964 Token getEndToken() => endToken;
965 }
966
967 class Loop extends Statement {
968 abstract Expression get condition();
969 final Statement body;
970
971 Loop(this.body);
972
973 bool isValidContinueTarget() => true;
974 }
975
976 class DoWhile extends Loop {
977 final Token doKeyword;
978 final Token whileKeyword;
979 final Token endToken;
980
981 final Expression condition;
982
983 DoWhile(Statement body, Expression this.condition,
984 Token this.doKeyword, Token this.whileKeyword, Token this.endToken)
985 : super(body);
986
987 DoWhile asDoWhile() => this;
988
989 accept(Visitor visitor) => visitor.visitDoWhile(this);
990
991 visitChildren(Visitor visitor) {
992 if (condition !== null) condition.accept(visitor);
993 if (body !== null) body.accept(visitor);
994 }
995
996 Token getBeginToken() => doKeyword;
997
998 Token getEndToken() => endToken;
999 }
1000
1001 class While extends Loop {
1002 final Token whileKeyword;
1003 final Expression condition;
1004
1005 While(Expression this.condition, Statement body,
1006 Token this.whileKeyword) : super(body);
1007
1008 While asWhile() => this;
1009
1010 accept(Visitor visitor) => visitor.visitWhile(this);
1011
1012 visitChildren(Visitor visitor) {
1013 if (condition !== null) condition.accept(visitor);
1014 if (body !== null) body.accept(visitor);
1015 }
1016
1017 Token getBeginToken() => whileKeyword;
1018
1019 Token getEndToken() => body.getEndToken();
1020 }
1021
1022 class ParenthesizedExpression extends Expression {
1023 final Expression expression;
1024 final BeginGroupToken beginToken;
1025
1026 ParenthesizedExpression(Expression this.expression,
1027 BeginGroupToken this.beginToken);
1028
1029 ParenthesizedExpression asParenthesizedExpression() => this;
1030
1031 accept(Visitor visitor) => visitor.visitParenthesizedExpression(this);
1032
1033 visitChildren(Visitor visitor) {
1034 if (expression !== null) expression.accept(visitor);
1035 }
1036
1037 Token getBeginToken() => beginToken;
1038
1039 Token getEndToken() => beginToken.endGroup;
1040 }
1041
1042 /** Representation of modifiers such as static, abstract, final, etc. */
1043 class Modifiers extends Node {
1044 /* TODO(ahe): The following should be validated relating to modifiers:
1045 * 1. The nodes must come in a certain order.
1046 * 2. The keywords "var" and "final" may not be used at the same time.
1047 * 3. The type of an element must be null if isVar() is true.
1048 */
1049
1050 final NodeList nodes;
1051 /** Bit pattern to easy check what modifiers are present. */
1052 final int flags;
1053
1054 static final int FLAG_STATIC = 1;
1055 static final int FLAG_ABSTRACT = FLAG_STATIC << 1;
1056 static final int FLAG_FINAL = FLAG_ABSTRACT << 1;
1057 static final int FLAG_VAR = FLAG_FINAL << 1;
1058 static final int FLAG_CONST = FLAG_VAR << 1;
1059 static final int FLAG_FACTORY = FLAG_CONST << 1;
1060
1061 Modifiers(NodeList nodes)
1062 : this.nodes = nodes, flags = computeFlags(nodes.nodes);
1063
1064 Modifiers.empty() : this(new NodeList.empty());
1065
1066 static int computeFlags(Link<Node> nodes) {
1067 int flags = 0;
1068 for (; !nodes.isEmpty(); nodes = nodes.tail) {
1069 String value = nodes.head.asIdentifier().source.stringValue;
1070 if (value === 'static') flags += FLAG_STATIC;
1071 else if (value === 'abstract') flags += FLAG_ABSTRACT;
1072 else if (value === 'final') flags += FLAG_FINAL;
1073 else if (value === 'var') flags += FLAG_VAR;
1074 else if (value === 'const') flags += FLAG_CONST;
1075 else if (value === 'factory') flags += FLAG_FACTORY;
1076 else throw 'internal error: ${nodes.head}';
1077 }
1078 return flags;
1079 }
1080
1081 Modifiers asModifiers() => this;
1082 Token getBeginToken() => nodes.getBeginToken();
1083 Token getEndToken() => nodes.getEndToken();
1084 accept(Visitor visitor) => visitor.visitModifiers(this);
1085 visitChildren(Visitor visitor) => nodes.accept(visitor);
1086
1087 bool isStatic() => (flags & FLAG_STATIC) != 0;
1088 bool isAbstract() => (flags & FLAG_ABSTRACT) != 0;
1089 bool isFinal() => (flags & FLAG_FINAL) != 0;
1090 bool isVar() => (flags & FLAG_VAR) != 0;
1091 bool isConst() => (flags & FLAG_CONST) != 0;
1092 bool isFactory() => (flags & FLAG_FACTORY) != 0;
1093 }
1094
1095 class StringInterpolation extends StringNode {
1096 final LiteralString string;
1097 final NodeList parts;
1098
1099 StringInterpolation(this.string, this.parts);
1100
1101 StringInterpolation asStringInterpolation() => this;
1102
1103 DartString get dartString() => null;
1104 bool get isInterpolation() => true;
1105
1106 accept(Visitor visitor) => visitor.visitStringInterpolation(this);
1107
1108 visitChildren(Visitor visitor) {
1109 string.accept(visitor);
1110 parts.accept(visitor);
1111 }
1112
1113 Token getBeginToken() => string.getBeginToken();
1114 Token getEndToken() => parts.getEndToken();
1115 }
1116
1117 class StringInterpolationPart extends Node {
1118 final Expression expression;
1119 final LiteralString string;
1120
1121 StringInterpolationPart(this.expression, this.string);
1122
1123 StringInterpolationPart asStringInterpolationPart() => this;
1124
1125 accept(Visitor visitor) => visitor.visitStringInterpolationPart(this);
1126
1127 visitChildren(Visitor visitor) {
1128 expression.accept(visitor);
1129 string.accept(visitor);
1130 }
1131
1132 Token getBeginToken() => expression.getBeginToken();
1133
1134 Token getEndToken() => string.getEndToken();
1135 }
1136
1137 /**
1138 * A class representing juxtaposed string literals.
1139 * The string literals can be both plain literals and string interpolations.
1140 */
1141 class StringJuxtaposition extends StringNode {
1142 final Expression first;
1143 final Expression second;
1144
1145 /**
1146 * Caches the check for whether this juxtaposition contains a string
1147 * interpolation
1148 */
1149 bool isInterpolationCache = null;
1150
1151 /**
1152 * Caches a Dart string representation of the entire juxtaposition's
1153 * content. Only juxtapositions that don't (transitively) contains
1154 * interpolations have a static representation.
1155 */
1156 DartString dartStringCache = null;
1157
1158 StringJuxtaposition(this.first, this.second);
1159
1160 StringJuxtaposition asStringJuxtaposition() => this;
1161
1162 bool get isInterpolation() {
1163 if (isInterpolationCache === null) {
1164 isInterpolationCache = (first.accept(const IsInterpolationVisitor()) ||
1165 second.accept(const IsInterpolationVisitor()));
1166 }
1167 return isInterpolationCache;
1168 }
1169
1170 /**
1171 * Retrieve a single DartString that represents this entire juxtaposition
1172 * of string literals.
1173 * Should only be called if [isInterpolation] returns false.
1174 */
1175 DartString get dartString() {
1176 if (isInterpolation) {
1177 throw new NodeAssertionFailure(this,
1178 "Getting dartString on interpolation;");
1179 }
1180 if (dartStringCache === null) {
1181 DartString firstString = first.accept(const GetDartStringVisitor());
1182 DartString secondString = second.accept(const GetDartStringVisitor());
1183 if (firstString === null || secondString === null) {
1184 return null;
1185 }
1186 dartStringCache = new DartString.concat(firstString, secondString);
1187 }
1188 return dartStringCache;
1189 }
1190
1191 accept(Visitor visitor) => visitor.visitStringJuxtaposition(this);
1192
1193 void visitChildren(Visitor visitor) {
1194 first.accept(visitor);
1195 second.accept(visitor);
1196 }
1197
1198 Token getBeginToken() => first.getBeginToken();
1199
1200 Token getEndToken() => second.getEndToken();
1201 }
1202
1203 class EmptyStatement extends Statement {
1204 final Token semicolonToken;
1205
1206 EmptyStatement(this.semicolonToken);
1207
1208 EmptyStatement asEmptyStatement() => this;
1209
1210 accept(Visitor visitor) => visitor.visitEmptyStatement(this);
1211
1212 visitChildren(Visitor visitor) {}
1213
1214 Token getBeginToken() => semicolonToken;
1215
1216 Token getEndToken() => semicolonToken;
1217 }
1218
1219 class LiteralMap extends Expression {
1220 final NodeList typeArguments;
1221 final NodeList entries;
1222
1223 LiteralMap(this.typeArguments, this.entries);
1224
1225 bool isConst() => false; // TODO(ahe): Store constness.
1226
1227 LiteralMap asLiteralMap() => this;
1228
1229 accept(Visitor visitor) => visitor.visitLiteralMap(this);
1230
1231 visitChildren(Visitor visitor) {
1232 if (typeArguments != null) typeArguments.accept(visitor);
1233 entries.accept(visitor);
1234 }
1235
1236 Token getBeginToken() => firstBeginToken(typeArguments, entries);
1237
1238 Token getEndToken() => entries.getEndToken();
1239 }
1240
1241 class LiteralMapEntry extends Node {
1242 final Expression key;
1243 final Expression value;
1244
1245 final Token colonToken;
1246
1247 LiteralMapEntry(this.key, this.colonToken, this.value);
1248
1249 LiteralMapEntry asLiteralMapEntry() => this;
1250
1251 accept(Visitor visitor) => visitor.visitLiteralMapEntry(this);
1252
1253 visitChildren(Visitor visitor) {
1254 key.accept(visitor);
1255 value.accept(visitor);
1256 }
1257
1258 Token getBeginToken() => key.getBeginToken();
1259
1260 Token getEndToken() => value.getEndToken();
1261 }
1262
1263 class NamedArgument extends Expression {
1264 final Identifier name;
1265 final Expression expression;
1266
1267 final Token colonToken;
1268
1269 NamedArgument(this.name, this.colonToken, this.expression);
1270
1271 NamedArgument asNamedArgument() => this;
1272
1273 accept(Visitor visitor) => visitor.visitNamedArgument(this);
1274
1275 visitChildren(Visitor visitor) {
1276 name.accept(visitor);
1277 expression.accept(visitor);
1278 }
1279
1280 Token getBeginToken() => name.getBeginToken();
1281
1282 Token getEndToken() => expression.getEndToken();
1283 }
1284
1285 class SwitchStatement extends Statement {
1286 final ParenthesizedExpression parenthesizedExpression;
1287 final NodeList cases;
1288
1289 final Token switchKeyword;
1290
1291 SwitchStatement(this.parenthesizedExpression, this.cases,
1292 this.switchKeyword);
1293
1294 SwitchStatement asSwitchStatement() => this;
1295
1296 Expression get expression() => parenthesizedExpression.expression;
1297
1298 accept(Visitor visitor) => visitor.visitSwitchStatement(this);
1299
1300 visitChildren(Visitor visitor) {
1301 parenthesizedExpression.accept(visitor);
1302 cases.accept(visitor);
1303 }
1304
1305 Token getBeginToken() => switchKeyword;
1306
1307 Token getEndToken() => cases.getEndToken();
1308 }
1309
1310 class SwitchCase extends Node {
1311 // Represents the grammar:
1312 // label? ('case' expression ':')* ('default' ':')? statement*
1313 // Each expression is collected in [expressions].
1314 // The 'case' keywords can be obtained using [caseKeywords()].
1315 // Any actual switch case must have at least one 'case' or 'default'
1316 // clause.
1317 final Identifier label;
1318 final NodeList expressions;
1319 final Token defaultKeyword;
1320 final NodeList statements;
1321
1322 final Token startToken;
1323
1324 SwitchCase(this.label, this.expressions, this.defaultKeyword,
1325 this.statements, this.startToken);
1326
1327 SwitchCase asSwitchCase() => this;
1328
1329 bool get isDefaultCase() => defaultKeyword !== null;
1330
1331 accept(Visitor visitor) => visitor.visitSwitchCase(this);
1332
1333 visitChildren(Visitor visitor) {
1334 if (label !== null) label.accept(visitor);
1335 expressions.accept(visitor);
1336 statements.accept(visitor);
1337 }
1338
1339 Token getBeginToken() {
1340 return startToken;
1341 }
1342
1343 Token getEndToken() {
1344 if (statements.nodes.isEmpty()) {
1345 // All cases must have at least one expression or be the default.
1346 if (defaultKeyword !== null) {
1347 // The colon after 'default'.
1348 return defaultKeyword.next;
1349 }
1350 // The colon after the expression.
1351 return expressions.getEndToken().next;
1352 } else {
1353 return statements.getEndToken();
1354 }
1355 }
1356
1357 Link<Token> caseKeywords() {
1358 Token token = startToken;
1359 if (label !== null) {
1360 // Skip past the label: <Identifier> ':'.
1361 token = token.next.next;
1362 }
1363 Link<Token> recursiveGetCases(Token token, Link<Expression> expressions) {
1364 if (token.stringValue === 'case') {
1365 Token colon = expressions.head.getEndToken().next;
1366 return new Link<Token>(token,
1367 recursiveGetCases(colon.next, expressions.tail));
1368 }
1369 return const EmptyLink<Token>();
1370 }
1371 return recursiveGetCases(token, expressions);
1372 }
1373 }
1374
1375 class GotoStatement extends Statement {
1376 final Identifier target;
1377 final Token keywordToken;
1378 final Token semicolonToken;
1379
1380 GotoStatement(this.target, this.keywordToken, this.semicolonToken);
1381
1382 visitChildren(Visitor visitor) {
1383 if (target !== null) target.accept(visitor);
1384 }
1385
1386 Token getBeginToken() => keywordToken;
1387
1388 Token getEndToken() => semicolonToken;
1389
1390 // TODO(ahe): make class abstract instead of adding an abstract method.
1391 abstract accept(Visitor visitor);
1392 }
1393
1394 class BreakStatement extends GotoStatement {
1395 BreakStatement(Identifier target, Token keywordToken, Token semicolonToken)
1396 : super(target, keywordToken, semicolonToken);
1397
1398 BreakStatement asBreakStatement() => this;
1399
1400 accept(Visitor visitor) => visitor.visitBreakStatement(this);
1401 }
1402
1403 class ContinueStatement extends GotoStatement {
1404 ContinueStatement(Identifier target, Token keywordToken, Token semicolonToken)
1405 : super(target, keywordToken, semicolonToken);
1406
1407 ContinueStatement asContinueStatement() => this;
1408
1409 accept(Visitor visitor) => visitor.visitContinueStatement(this);
1410 }
1411
1412 class ForInStatement extends Loop {
1413 final Node declaredIdentifier;
1414 final Expression expression;
1415
1416 final Token forToken;
1417 final Token inToken;
1418
1419 ForInStatement(this.declaredIdentifier, this.expression,
1420 Statement body, this.forToken, this.inToken) : super(body);
1421
1422 Expression get condition() => null;
1423
1424 ForInStatement asForInStatement() => this;
1425
1426 accept(Visitor visitor) => visitor.visitForInStatement(this);
1427
1428 visitChildren(Visitor visitor) {
1429 declaredIdentifier.accept(visitor);
1430 expression.accept(visitor);
1431 body.accept(visitor);
1432 }
1433
1434 Token getBeginToken() => forToken;
1435
1436 Token getEndToken() => body.getEndToken();
1437 }
1438
1439 class LabeledStatement extends Statement {
1440 final Identifier label;
1441 final Token colonToken;
1442 final Statement statement;
1443
1444 LabeledStatement(this.label, this.colonToken, this.statement);
1445
1446 LabeledStatement asLabeledStatement() => this;
1447
1448 accept(Visitor visitor) => visitor.visitLabeledStatement(this);
1449
1450 visitChildren(Visitor visitor) {
1451 label.accept(visitor);
1452 statement.accept(visitor);
1453 }
1454
1455 Token getBeginToken() => label.getBeginToken();
1456
1457 Token getEndToken() => statement.getEndToken();
1458
1459 bool isValidContinueTarget() => statement.isValidContinueTarget();
1460
1461 Node getBody() {
1462 if (statement is! LabeledStatement) return statement;
1463 LabeledStatement labeled = statement;
1464 return labeled.getBody();
1465 }
1466 }
1467
1468 class ScriptTag extends Node {
1469 final Identifier tag;
1470 final StringNode argument;
1471 final Identifier prefixIdentifier;
1472 final StringNode prefix;
1473
1474 final Token beginToken;
1475 final Token endToken;
1476
1477 ScriptTag(this.tag, this.argument, this.prefixIdentifier, this.prefix,
1478 this.beginToken, this.endToken);
1479
1480 bool isImport() => tag.source == const SourceString("import");
1481 bool isSource() => tag.source == const SourceString("source");
1482 bool isLibrary() => tag.source == const SourceString("library");
1483 bool isResource() => tag.source == const SourceString("resource");
1484
1485 ScriptTag asScriptTag() => this;
1486
1487 accept(Visitor visitor) => visitor.visitScriptTag(this);
1488
1489 visitChildren(Visitor visitor) {
1490 tag.accept(visitor);
1491 argument.accept(visitor);
1492 if (prefixIdentifier !== null) prefixIdentifier.accept(visitor);
1493 if (prefix !== null) prefix.accept(visitor);
1494 }
1495
1496 Token getBeginToken() => beginToken;
1497
1498 Token getEndToken() => endToken;
1499 }
1500
1501 class Typedef extends Node {
1502 final TypeAnnotation returnType;
1503 final Identifier name;
1504 final NodeList typeParameters;
1505 final NodeList formals;
1506
1507 final Token typedefKeyword;
1508 final Token endToken;
1509
1510 Typedef(this.returnType, this.name, this.typeParameters, this.formals,
1511 this.typedefKeyword, this.endToken);
1512
1513 Typedef asTypedef() => this;
1514
1515 accept(Visitor visitor) => visitor.visitTypedef(this);
1516
1517 visitChildren(Visitor visitor) {
1518 if (returnType !== null) returnType.accept(visitor);
1519 name.accept(visitor);
1520 if (typeParameters !== null) typeParameters.accept(visitor);
1521 formals.accept(visitor);
1522 }
1523
1524 Token getBeginToken() => typedefKeyword;
1525
1526 Token getEndToken() => endToken;
1527 }
1528
1529 class TryStatement extends Statement {
1530 final Block tryBlock;
1531 final NodeList catchBlocks;
1532 final Block finallyBlock;
1533
1534 final Token tryKeyword;
1535 final Token finallyKeyword;
1536
1537 TryStatement(this.tryBlock, this.catchBlocks, this.finallyBlock,
1538 this.tryKeyword, this.finallyKeyword);
1539
1540 TryStatement asTryStatement() => this;
1541
1542 accept(Visitor visitor) => visitor.visitTryStatement(this);
1543
1544 visitChildren(Visitor visitor) {
1545 tryBlock.accept(visitor);
1546 catchBlocks.accept(visitor);
1547 if (finallyBlock !== null) finallyBlock.accept(visitor);
1548 }
1549
1550 Token getBeginToken() => tryKeyword;
1551
1552 Token getEndToken() {
1553 if (finallyBlock !== null) return finallyBlock.getEndToken();
1554 if (!catchBlocks.isEmpty()) return catchBlocks.getEndToken();
1555 return tryBlock.getEndToken();
1556 }
1557 }
1558
1559 class CatchBlock extends Node {
1560 final NodeList formals;
1561 final Block block;
1562
1563 final catchKeyword;
1564
1565 CatchBlock(this.formals, this.block, this.catchKeyword);
1566
1567 CatchBlock asCatchBlock() => this;
1568
1569 accept(Visitor visitor) => visitor.visitCatchBlock(this);
1570
1571 Node get exception() {
1572 if (formals.nodes.isEmpty()) return null;
1573 VariableDefinitions declarations = formals.nodes.head;
1574 return declarations.definitions.nodes.head;
1575 }
1576
1577 Node get trace() {
1578 if (formals.nodes.isEmpty()) return null;
1579 Link<Node> declarations = formals.nodes.tail;
1580 if (declarations.isEmpty()) return null;
1581 VariableDefinitions head = declarations.head;
1582 return head.definitions.nodes.head;
1583 }
1584
1585 visitChildren(Visitor visitor) {
1586 formals.accept(visitor);
1587 block.accept(visitor);
1588 }
1589
1590 Token getBeginToken() => catchKeyword;
1591
1592 Token getEndToken() => block.getEndToken();
1593 }
1594
1595 class Initializers {
1596 static bool isSuperConstructorCall(Send node) {
1597 return (node.receiver === null &&
1598 node.selector.asIdentifier() !== null &&
1599 node.selector.asIdentifier().isSuper()) ||
1600 (node.receiver !== null &&
1601 node.receiver.asIdentifier() !== null &&
1602 node.receiver.asIdentifier().isSuper() &&
1603 node.selector.asIdentifier() !== null);
1604 }
1605
1606 static bool isConstructorRedirect(Send node) {
1607 return (node.receiver === null &&
1608 node.selector.asIdentifier() !== null &&
1609 node.selector.asIdentifier().isThis()) ||
1610 (node.receiver !== null &&
1611 node.receiver.asIdentifier() !== null &&
1612 node.receiver.asIdentifier().isThis() &&
1613 node.selector.asIdentifier() !== null);
1614 }
1615 }
1616
1617 class GetDartStringVisitor extends AbstractVisitor<DartString> {
1618 const GetDartStringVisitor();
1619 DartString visitNode(Node node) => null;
1620 DartString visitStringJuxtaposition(StringJuxtaposition node)
1621 => node.dartString;
1622 DartString visitLiteralString(LiteralString node) => node.dartString;
1623 }
1624
1625 class IsInterpolationVisitor extends AbstractVisitor<bool> {
1626 const IsInterpolationVisitor();
1627 bool visitNode(Node node) => false;
1628 bool visitStringInterpolation(StringInterpolation node) => true;
1629 bool visitStringJuxtaposition(StringJuxtaposition node)
1630 => node.isInterpolation;
1631 }
1632
1633 /**
1634 * If the given node is a send set, it visits its initializer (first
1635 * argument).
1636 *
1637 * TODO(ahe): This method is controversial, the team needs to discuss
1638 * if top-level methods are acceptable and what naming conventions to
1639 * use.
1640 */
1641 initializerDo(Node node, f(Node node)) {
1642 SendSet send = node.asSendSet();
1643 if (send !== null) return f(send.arguments.head);
1644 }
OLDNEW
« no previous file with comments | « frog/leg/tree/dartstring.dart ('k') | frog/leg/tree/tree.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698