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

Side by Side Diff: frog/leg/scanner/parser.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, 9 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/scanner/node_scanner_bench.dart ('k') | frog/leg/scanner/parser_bench.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 /**
6 * An event generating parser of Dart programs. This parser expects
7 * all tokens in a linked list.
8 */
9 class Parser {
10 final Listener listener;
11 bool mayParseFunctionExpressions = true;
12
13 Parser(Listener this.listener);
14
15 void parseUnit(Token token) {
16 while (token.kind !== EOF_TOKEN) {
17 token = parseTopLevelDeclaration(token);
18 }
19 }
20
21 Token parseTopLevelDeclaration(Token token) {
22 final String value = token.stringValue;
23 if (value === 'interface') {
24 return parseInterface(token);
25 } else if ((value === 'abstract') || (value === 'class')) {
26 return parseClass(token);
27 } else if (value === 'typedef') {
28 return parseNamedFunctionAlias(token);
29 } else if (value === '#') {
30 return parseScriptTags(token);
31 } else {
32 return parseTopLevelMember(token);
33 }
34 }
35
36 Token parseInterface(Token token) {
37 Token interfaceKeyword = token;
38 listener.beginInterface(token);
39 token = parseIdentifier(token.next);
40 token = parseTypeVariablesOpt(token);
41 int supertypeCount = 0;
42 Token extendsKeyword = null;
43 if (optional('extends', token)) {
44 extendsKeyword = token;
45 do {
46 token = parseType(token.next);
47 ++supertypeCount;
48 } while (optional(',', token));
49 }
50 token = parseDefaultClauseOpt(token);
51 token = parseInterfaceBody(token);
52 listener.endInterface(supertypeCount, interfaceKeyword,
53 extendsKeyword, token);
54 return token.next;
55 }
56
57 Token parseInterfaceBody(Token token) {
58 return parseClassBody(token);
59 }
60
61 Token parseNamedFunctionAlias(Token token) {
62 Token typedefKeyword = token;
63 listener.beginFunctionTypeAlias(token);
64 token = parseReturnTypeOpt(token.next);
65 token = parseIdentifier(token);
66 token = parseTypeVariablesOpt(token);
67 token = parseFormalParameters(token);
68 listener.endFunctionTypeAlias(typedefKeyword, token);
69 return expect(';', token);
70 }
71
72 Token parseReturnTypeOpt(Token token) {
73 if (token.stringValue === 'void') {
74 listener.handleVoidKeyword(token);
75 return token.next;
76 } else {
77 return parseTypeOpt(token);
78 }
79 }
80
81 Token parseFormalParameters(Token token) {
82 Token begin = token;
83 listener.beginFormalParameters(begin);
84 expect('(', token);
85 int parameterCount = 0;
86 if (optional(')', token.next)) {
87 listener.endFormalParameters(parameterCount, begin, token.next);
88 return token.next.next;
89 }
90 do {
91 ++parameterCount;
92 token = token.next;
93 if (optional('[', token)) {
94 token = parseOptionalFormalParameters(token);
95 break;
96 }
97 token = parseFormalParameter(token);
98 } while (optional(',', token));
99 listener.endFormalParameters(parameterCount, begin, token);
100 return expect(')', token);
101 }
102
103 Token parseFormalParameter(Token token) {
104 listener.beginFormalParameter(token);
105 token = parseModifiers(token);
106 // TODO(ahe): Validate that there are formal parameters if void.
107 token = parseReturnTypeOpt(token);
108 Token thisKeyword = null;
109 if (optional('this', token)) {
110 thisKeyword = token;
111 // TODO(ahe): Validate field initializers are only used in
112 // constructors, and not for function-typed arguments.
113 token = expect('.', token.next);
114 }
115 token = parseIdentifier(token);
116 if (optional('(', token)) {
117 token = parseFormalParameters(token);
118 listener.handleFunctionTypedFormalParameter(token);
119 }
120 if (optional('=', token)) {
121 // TODO(ahe): Validate that these are only used for optional parameters.
122 Token equal = token;
123 token = parseExpression(token.next);
124 listener.handleValuedFormalParameter(equal, token);
125 }
126 listener.endFormalParameter(token, thisKeyword);
127 return token;
128 }
129
130 Token parseOptionalFormalParameters(Token token) {
131 Token begin = token;
132 listener.beginOptionalFormalParameters(begin);
133 assert(optional('[', token));
134 int parameterCount = 0;
135 do {
136 token = token.next;
137 token = parseFormalParameter(token);
138 ++parameterCount;
139 } while (optional(',', token));
140 listener.endOptionalFormalParameters(parameterCount, begin, token);
141 return expect(']', token);
142 }
143
144 Token parseTypeOpt(Token token) {
145 String value = token.stringValue;
146 if (value === 'var') return parseType(token);
147 if (value !== 'this') {
148 Token peek = peekAfterType(token);
149 if (isIdentifier(peek) || optional('this', peek)) {
150 return parseType(token);
151 }
152 }
153 listener.handleNoType(token);
154 return token;
155 }
156
157 bool isIdentifier(Token token) {
158 final kind = token.kind;
159 if (kind === IDENTIFIER_TOKEN) return true;
160 if (kind === KEYWORD_TOKEN) return token.value.isPseudo;
161 return false;
162 }
163
164 Token parseDefaultClauseOpt(Token token) {
165 if (isDefaultKeyword(token)) {
166 // TODO(ahe): Remove support for 'factory' in this position.
167 Token defaultKeyword = token;
168 listener.beginDefaultClause(defaultKeyword);
169 token = parseIdentifier(token.next);
170 token = parseQualifiedRestOpt(token);
171 token = parseTypeVariablesOpt(token);
172 listener.endDefaultClause(defaultKeyword);
173 } else {
174 listener.handleNoDefaultClause(token);
175 }
176 return token;
177 }
178
179 Token parseQualifiedRestOpt(Token token) {
180 if (optional('.', token)) {
181 Token period = token;
182 token = parseIdentifier(token.next);
183 listener.handleQualified(period);
184 }
185 return token;
186 }
187
188 bool isDefaultKeyword(Token token) {
189 String value = token.stringValue;
190 if (value === 'default') return true;
191 if (value === 'factory') {
192 listener.recoverableError("expected 'default'", token: token);
193 return true;
194 }
195 return false;
196 }
197
198 Token skipBlock(Token token) {
199 if (!optional('{', token)) {
200 return listener.expectedBlockToSkip(token);
201 }
202 BeginGroupToken beginGroupToken = token;
203 assert(beginGroupToken.endGroup === null ||
204 beginGroupToken.endGroup.kind === $CLOSE_CURLY_BRACKET);
205 return beginGroupToken.endGroup;
206 }
207
208 Token parseClass(Token token) {
209 Token begin = token;
210 listener.beginClassDeclaration(token);
211 if (optional('abstract', token)) {
212 // TODO(ahe): Notify listener about abstract modifier.
213 token = token.next;
214 }
215 token = parseIdentifier(token.next);
216 token = parseTypeVariablesOpt(token);
217 Token extendsKeyword;
218 if (optional('extends', token)) {
219 extendsKeyword = token;
220 token = parseType(token.next);
221 } else {
222 extendsKeyword = null;
223 listener.handleNoType(token);
224 }
225 Token implementsKeyword;
226 int interfacesCount = 0;
227 if (optional('implements', token)) {
228 do {
229 token = parseType(token.next);
230 ++interfacesCount;
231 } while (optional(',', token));
232 }
233 token = parseClassBody(token);
234 listener.endClassDeclaration(interfacesCount, begin, extendsKeyword,
235 implementsKeyword, token);
236 return token.next;
237 }
238
239
240 Token parseStringPart(Token token) {
241 if (token.kind === STRING_TOKEN) {
242 listener.handleStringPart(token);
243 return token.next;
244 } else {
245 return listener.expected('string', token);
246 }
247 }
248
249 Token parseIdentifier(Token token) {
250 if (isIdentifier(token)) {
251 listener.handleIdentifier(token);
252 } else {
253 listener.expectedIdentifier(token);
254 }
255 return token.next;
256 }
257
258 Token expect(String string, Token token) {
259 if (string !== token.stringValue) {
260 if (string === '>') {
261 if (token.stringValue === '>>') {
262 Token gt = new Token(GT_INFO, token.charOffset + 1);
263 gt.next = token.next;
264 return gt;
265 } else if (token.stringValue === '>>>') {
266 Token gtgt = new Token(GT_GT_INFO, token.charOffset + 1);
267 gtgt.next = token.next;
268 return gtgt;
269 }
270 }
271 return listener.expected(string, token);
272 }
273 return token.next;
274 }
275
276 Token parseTypeVariable(Token token) {
277 listener.beginTypeVariable(token);
278 token = parseIdentifier(token);
279 if (optional('extends', token)) {
280 token = parseType(token.next);
281 } else {
282 listener.handleNoType(token);
283 }
284 listener.endTypeVariable(token);
285 return token;
286 }
287
288 bool optional(String value, Token token) => value === token.stringValue;
289
290 bool notEofOrValue(String value, Token token) {
291 return token.kind !== EOF_TOKEN && value !== token.stringValue;
292 }
293
294 Token parseType(Token token) {
295 Token begin = token;
296 if (isIdentifier(token)) {
297 token = parseIdentifier(token);
298 token = parseQualifiedRestOpt(token);
299 } else {
300 token = listener.expectedType(token);
301 }
302 token = parseTypeArgumentsOpt(token);
303 listener.endType(begin, token);
304 return token;
305 }
306
307 Token parseTypeArgumentsOpt(Token token) {
308 return parseStuff(token,
309 (t) => listener.beginTypeArguments(t),
310 (t) => parseType(t),
311 (c, bt, et) => listener.endTypeArguments(c, bt, et),
312 (t) => listener.handleNoTypeArguments(t));
313 }
314
315 Token parseTypeVariablesOpt(Token token) {
316 return parseStuff(token,
317 (t) => listener.beginTypeVariables(t),
318 (t) => parseTypeVariable(t),
319 (c, bt, et) => listener.endTypeVariables(c, bt, et),
320 (t) => listener.handleNoTypeVariables(t));
321 }
322
323 // TODO(ahe): Clean this up.
324 Token parseStuff(Token token, Function beginStuff, Function stuffParser,
325 Function endStuff, Function handleNoStuff) {
326 if (optional('<', token)) {
327 Token begin = token;
328 beginStuff(begin);
329 int count = 0;
330 do {
331 token = stuffParser(token.next);
332 ++count;
333 } while (optional(',', token));
334 endStuff(count, begin, token);
335 return expect('>', token);
336 }
337 handleNoStuff(token);
338 return token;
339 }
340
341 Token parseTopLevelMember(Token token) {
342 Token start = token;
343 listener.beginTopLevelMember(token);
344 token = parseModifiers(token);
345 Token getOrSet = findGetOrSet(token);
346 if (token === getOrSet) token = token.next;
347 Token peek = peekAfterType(token);
348 if (isIdentifier(peek)) {
349 // Skip type.
350 token = peek;
351 }
352 if (token === getOrSet) token = token.next;
353 token = parseIdentifier(token);
354 bool isField;
355 while (true) {
356 // Loop to allow the listener to rewrite the token stream for
357 // error handling.
358 final String value = token.stringValue;
359 if (value === '(') {
360 isField = false;
361 break;
362 } else if ((value === '=') || (value === ';') || (value === ',')) {
363 isField = true;
364 break;
365 } else {
366 token = listener.unexpected(token);
367 if (token.kind === EOF_TOKEN) {
368 // TODO(ahe): This is a hack. It would be better to tell the
369 // listener more explicitly that it must pop an identifier.
370 listener.endTopLevelFields(1, start, token);
371 return token;
372 }
373 }
374 }
375 if (isField) {
376 int fieldCount = 1;
377 token = parseVariableInitializerOpt(token);
378 while (optional(',', token)) {
379 token = parseIdentifier(token.next);
380 token = parseVariableInitializerOpt(token);
381 ++fieldCount;
382 }
383 expectSemicolon(token);
384 listener.endTopLevelFields(fieldCount, start, token);
385 } else {
386 token = parseFormalParameters(token);
387 token = parseFunctionBody(token, false);
388 listener.endTopLevelMethod(start, getOrSet, token);
389 }
390 return token.next;
391 }
392
393 Token parseVariableInitializerOpt(Token token) {
394 if (optional('=', token)) {
395 Token assignment = token;
396 listener.beginInitializer(token);
397 token = parseExpression(token.next);
398 listener.endInitializer(assignment);
399 }
400 return token;
401 }
402
403 Token parseInitializersOpt(Token token) {
404 if (optional(':', token)) {
405 return parseInitializers(token);
406 } else {
407 listener.handleNoInitializers();
408 return token;
409 }
410 }
411
412 Token parseInitializers(Token token) {
413 Token begin = token;
414 listener.beginInitializers(begin);
415 expect(':', token);
416 int count = 0;
417 bool old = mayParseFunctionExpressions;
418 mayParseFunctionExpressions = false;
419 do {
420 token = parseExpression(token.next);
421 ++count;
422 } while (optional(',', token));
423 mayParseFunctionExpressions = old;
424 listener.endInitializers(count, begin, token);
425 return token;
426 }
427
428 Token parseScriptTags(Token token) {
429 Token begin = token;
430 listener.beginScriptTag(token);
431 token = parseIdentifier(token.next);
432 token = expect('(', token);
433 token = parseLiteralStringOrRecoverExpression(token);
434 bool hasPrefix = false;
435 if (optional(',', token)) {
436 hasPrefix = true;
437 token = parseIdentifier(token.next);
438 token = expect(':', token);
439 token = parseLiteralStringOrRecoverExpression(token);
440 }
441 token = expect(')', token);
442 listener.endScriptTag(hasPrefix, begin, token);
443 return expectSemicolon(token);
444 }
445
446 Token parseLiteralStringOrRecoverExpression(Token token) {
447 if (token.kind === STRING_TOKEN) {
448 return parseLiteralString(token);
449 } else {
450 listener.recoverableError("unexpected", token: token);
451 return parseExpression(token);
452 }
453 }
454
455 Token expectSemicolon(Token token) {
456 return expect(';', token);
457 }
458
459 Token parseModifier(Token token) {
460 assert(('final' === token.stringValue) ||
461 ('var' === token.stringValue) ||
462 ('const' === token.stringValue) ||
463 ('abstract' === token.stringValue) ||
464 ('static' === token.stringValue));
465 listener.handleModifier(token);
466 return token.next;
467 }
468
469 Token parseModifiers(Token token) {
470 int count = 0;
471 while (token.kind === KEYWORD_TOKEN) {
472 final String value = token.stringValue;
473 if (('final' !== value) &&
474 ('var' !== value) &&
475 ('const' !== value) &&
476 ('abstract' !== value) &&
477 ('static' !== value))
478 break;
479 token = parseModifier(token);
480 count++;
481 }
482 listener.handleModifiers(count);
483 return token;
484 }
485
486 Token peekAfterType(Token token) {
487 // TODO(ahe): Also handle var?
488 if ('void' !== token.stringValue && !isIdentifier(token)) {
489 listener.unexpected(token);
490 }
491 // We are looking at "identifier ...".
492 Token peek = token.next;
493 if (peek.kind === PERIOD_TOKEN) {
494 if (isIdentifier(peek.next)) {
495 // Look past a library prefix.
496 peek = peek.next.next;
497 }
498 }
499 // We are looking at "qualified ...".
500 if (peek.kind === LT_TOKEN) {
501 // Possibly generic type.
502 // We are looking at "qualified '<'".
503 BeginGroupToken beginGroupToken = peek;
504 Token gtToken = beginGroupToken.endGroup;
505 if (gtToken !== null) {
506 // We are looking at "qualified '<' ... '>' ...".
507 return gtToken.next;
508 }
509 }
510 return peek;
511 }
512
513 Token parseClassBody(Token token) {
514 Token begin = token;
515 listener.beginClassBody(token);
516 if (!optional('{', token)) {
517 token = listener.expectedClassBody(token);
518 }
519 token = token.next;
520 int count = 0;
521 while (notEofOrValue('}', token)) {
522 token = parseMember(token);
523 ++count;
524 }
525 listener.endClassBody(count, begin, token);
526 return token;
527 }
528
529 bool isGetOrSet(Token token) {
530 final String value = token.stringValue;
531 return (value === 'get') || (value === 'set');
532 }
533
534 Token findGetOrSet(Token token) {
535 if (isGetOrSet(token)) {
536 if (optional('<', token.next)) {
537 // For example: get<T> ...
538 final Token peek = peekAfterType(token);
539 if (isGetOrSet(peek) && isIdentifier(peek.next)) {
540 // For example: get<T> get identifier
541 return peek;
542 }
543 } else {
544 // For example: get ...
545 if (isGetOrSet(token.next) && isIdentifier(token.next.next)) {
546 // For example: get get identifier
547 return token.next;
548 } else {
549 // For example: get identifier
550 return token;
551 }
552 }
553 } else if (token.stringValue !== 'operator') {
554 final Token peek = peekAfterType(token);
555 if (isGetOrSet(peek) && isIdentifier(peek.next)) {
556 // type? get identifier
557 return peek;
558 }
559 }
560 return null;
561 }
562
563 Token parseMember(Token token) {
564 if (optional('factory', token)) {
565 return parseFactoryMethod(token);
566 }
567 Token start = token;
568 listener.beginMember(token);
569 token = parseModifiers(token);
570 Token getOrSet = findGetOrSet(token);
571 if (token === getOrSet) token = token.next;
572 Token peek = peekAfterType(token);
573 if (isIdentifier(peek) && token.stringValue !== 'operator') {
574 // Skip type.
575 token = peek;
576 }
577 if (token === getOrSet) token = token.next;
578 if (optional('operator', token)) {
579 token = parseOperatorName(token);
580 } else {
581 token = parseIdentifier(token);
582 }
583 bool isField;
584 while (true) {
585 // Loop to allow the listener to rewrite the token stream for
586 // error handling.
587 final String value = token.stringValue;
588 if ((value === '(') || (value === '.')) {
589 isField = false;
590 break;
591 } else if ((value === '=') || (value === ';') || (value === ',')) {
592 isField = true;
593 break;
594 } else {
595 token = listener.unexpected(token);
596 if (token.kind === EOF_TOKEN) {
597 // TODO(ahe): This is a hack, see parseTopLevelMember.
598 listener.endFields(1, start, token);
599 return token;
600 }
601 }
602 }
603 if (isField) {
604 int fieldCount = 1;
605 token = parseVariableInitializerOpt(token);
606 if (getOrSet !== null) {
607 listener.recoverableError("unexpected", token: getOrSet);
608 }
609 while (optional(',', token)) {
610 // TODO(ahe): Count these.
611 token = parseIdentifier(token.next);
612 token = parseVariableInitializerOpt(token);
613 ++fieldCount;
614 }
615 expectSemicolon(token);
616 listener.endFields(fieldCount, start, token);
617 } else {
618 token = parseQualifiedRestOpt(token);
619 token = parseFormalParameters(token);
620 token = parseInitializersOpt(token);
621 token = parseFunctionBody(token, false);
622 listener.endMethod(getOrSet, start, token);
623 }
624 return token.next;
625 }
626
627 Token parseFactoryMethod(Token token) {
628 assert(optional('factory', token));
629 Token factoryKeyword = token;
630 listener.beginFactoryMethod(factoryKeyword);
631 token = token.next; // Skip 'factory'.
632 token = parseIdentifier(token);
633 token = parseQualifiedRestOpt(token);
634 token = parseTypeVariablesOpt(token);
635 Token period = null;
636 if (optional('.', token)) {
637 period = token;
638 token = parseIdentifier(token.next);
639 }
640 token = parseFormalParameters(token);
641 token = parseFunctionBody(token, false);
642 listener.endFactoryMethod(factoryKeyword, period, token);
643 return token.next;
644 }
645
646 Token parseOperatorName(Token token) {
647 assert(optional('operator', token));
648 if (isUserDefinableOperator(token.next.stringValue)) {
649 Token operator = token;
650 token = token.next;
651 listener.handleOperatorName(operator, token);
652 return token.next;
653 } else {
654 return parseIdentifier(token);
655 }
656 }
657
658 Token parseFunction(Token token, Token getOrSet) {
659 listener.beginFunction(token);
660 token = parseModifiers(token);
661 if (getOrSet === token) token = token.next;
662 token = parseReturnTypeOpt(token);
663 if (getOrSet === token) token = token.next;
664 listener.beginFunctionName(token);
665 if (optional('operator', token)) {
666 token = parseOperatorName(token);
667 } else {
668 token = parseIdentifier(token);
669 }
670 token = parseQualifiedRestOpt(token);
671 listener.endFunctionName(token);
672 token = parseFormalParameters(token);
673 token = parseInitializersOpt(token);
674 token = parseFunctionBody(token, false);
675 listener.endFunction(getOrSet, token);
676 return token.next;
677 }
678
679 Token parseUnamedFunction(Token token) {
680 listener.beginUnamedFunction(token);
681 token = parseFormalParameters(token);
682 bool isBlock = optional('{', token);
683 token = parseFunctionBody(token, true);
684 listener.endUnamedFunction(token);
685 return isBlock ? token.next : token;
686 }
687
688 Token parseFunctionDeclaration(Token token) {
689 listener.beginFunctionDeclaration(token);
690 token = parseFunction(token, null);
691 listener.endFunctionDeclaration(token);
692 return token;
693 }
694
695 Token parseFunctionExpression(Token token) {
696 listener.beginFunction(token);
697 listener.handleModifiers(0);
698 token = parseReturnTypeOpt(token);
699 listener.beginFunctionName(token);
700 token = parseIdentifier(token);
701 listener.endFunctionName(token);
702 token = parseFormalParameters(token);
703 listener.handleNoInitializers();
704 bool isBlock = optional('{', token);
705 token = parseFunctionBody(token, true);
706 listener.endFunction(null, token);
707 return isBlock ? token.next : token;
708 }
709
710 Token parseFunctionBody(Token token, bool isExpression) {
711 if (optional(';', token)) {
712 listener.endFunctionBody(0, null, token);
713 return token;
714 } else if (optional('=>', token)) {
715 Token begin = token;
716 token = parseExpression(token.next);
717 if (!isExpression) {
718 expectSemicolon(token);
719 listener.endReturnStatement(true, begin, token);
720 } else {
721 listener.endReturnStatement(true, begin, null);
722 }
723 return token;
724 }
725 Token begin = token;
726 int statementCount = 0;
727 listener.beginFunctionBody(begin);
728 if (!optional('{', token)) {
729 return listener.expectedFunctionBody(token);
730 } else {
731 token = token.next;
732 }
733 while (notEofOrValue('}', token)) {
734 token = parseStatement(token);
735 ++statementCount;
736 }
737 listener.endFunctionBody(statementCount, begin, token);
738 expect('}', token);
739 return token;
740 }
741
742 Token parseStatement(Token token) {
743 final value = token.stringValue;
744 if (token.kind === IDENTIFIER_TOKEN) {
745 return parseExpressionStatementOrDeclaration(token);
746 } else if (value === '{') {
747 return parseBlock(token);
748 } else if (value === 'return') {
749 return parseReturnStatement(token);
750 } else if (value === 'var' || value === 'final') {
751 return parseVariablesDeclaration(token);
752 } else if (value === 'if') {
753 return parseIfStatement(token);
754 } else if (value === 'for') {
755 return parseForStatement(token);
756 } else if (value === 'throw') {
757 return parseThrowStatement(token);
758 } else if (value === 'void') {
759 return parseExpressionStatementOrDeclaration(token);
760 } else if (value === 'while') {
761 return parseWhileStatement(token);
762 } else if (value === 'do') {
763 return parseDoWhileStatement(token);
764 } else if (value === 'try') {
765 return parseTryStatement(token);
766 } else if (value === 'switch') {
767 return parseSwitchStatement(token);
768 } else if (value === 'break') {
769 return parseBreakStatement(token);
770 } else if (value === 'continue') {
771 return parseContinueStatement(token);
772 } else if (value === ';') {
773 return parseEmptyStatement(token);
774 } else {
775 return parseExpressionStatement(token);
776 }
777 }
778
779 Token parseReturnStatement(Token token) {
780 Token begin = token;
781 listener.beginReturnStatement(begin);
782 assert('return' === token.stringValue);
783 token = token.next;
784 if (optional(';', token)) {
785 listener.endReturnStatement(false, begin, token);
786 } else {
787 token = parseExpression(token);
788 listener.endReturnStatement(true, begin, token);
789 }
790 return expectSemicolon(token);
791 }
792
793 Token peekIdentifierAfterType(Token token) {
794 Token peek = peekAfterType(token);
795 if (peek !== null && isIdentifier(peek)) {
796 // We are looking at "type identifier".
797 return peek;
798 } else {
799 return null;
800 }
801 }
802
803 Token parseExpressionStatementOrDeclaration(Token token) {
804 assert(isIdentifier(token) || token.stringValue === 'void');
805 Token identifier = peekIdentifierAfterType(token);
806 if (identifier !== null) {
807 assert(isIdentifier(identifier));
808 Token afterId = identifier.next;
809 int afterIdKind = afterId.kind;
810 if (afterIdKind === EQ_TOKEN ||
811 afterIdKind === SEMICOLON_TOKEN ||
812 afterIdKind === COMMA_TOKEN) {
813 // We are looking at "type identifier" followed by '=', ';', ','.
814 return parseVariablesDeclaration(token);
815 } else if (afterIdKind === OPEN_PAREN_TOKEN) {
816 // We are looking at "type identifier '('".
817 BeginGroupToken beginParen = afterId;
818 Token endParen = beginParen.endGroup;
819 Token afterParens = endParen.next;
820 if (optional('{', afterParens) || optional('=>', afterParens)) {
821 // We are looking at "type identifier '(' ... ')'" followed
822 // by '=>' or '{'.
823 return parseFunctionDeclaration(token);
824 }
825 }
826 // Fall-through to expression statement.
827 } else {
828 if (optional(':', token.next)) {
829 return parseLabeledStatement(token);
830 } else if (optional('(', token.next)) {
831 BeginGroupToken begin = token.next;
832 String afterParens = begin.endGroup.next.stringValue;
833 if (afterParens === '{' || afterParens === '=>') {
834 return parseFunctionDeclaration(token);
835 }
836 }
837 }
838 return parseExpressionStatement(token);
839 }
840
841 Token parseLabeledStatement(Token token) {
842 listener.beginLabeledStatement(token);
843 token = parseIdentifier(token);
844 Token colon = token;
845 token = expect(':', token);
846 token = parseStatement(token);
847 listener.endLabeledStatement(colon);
848 return token;
849 }
850
851 Token parseExpressionStatement(Token token) {
852 listener.beginExpressionStatement(token);
853 token = parseExpression(token);
854 listener.endExpressionStatement(token);
855 return expectSemicolon(token);
856 }
857
858 Token parseExpression(Token token) {
859 return parsePrecedenceExpression(token, 2);
860 }
861
862 Token parseConditionalExpressionRest(Token token) {
863 assert(optional('?', token));
864 Token question = token;
865 token = parseExpression(token.next);
866 Token colon = token;
867 token = expect(':', token);
868 token = parseExpression(token);
869 listener.handleConditionalExpression(question, colon);
870 return token;
871 }
872
873 Token parsePrecedenceExpression(Token token, int precedence) {
874 assert(precedence >= 2);
875 assert(precedence <= POSTFIX_PRECEDENCE);
876 token = parseUnaryExpression(token);
877 PrecedenceInfo info = token.info;
878 int tokenLevel = info.precedence;
879 for (int level = tokenLevel; level >= precedence; --level) {
880 while (tokenLevel === level) {
881 Token operator = token;
882 if (tokenLevel === ASSIGNMENT_PRECEDENCE) {
883 // Right associative, so we recurse at the same precedence
884 // level.
885 token = parsePrecedenceExpression(token.next, level);
886 listener.handleAssignmentExpression(operator);
887 } else if (tokenLevel === POSTFIX_PRECEDENCE) {
888 if (info === PERIOD_INFO) {
889 // Left associative, so we recurse at the next higher
890 // precedence level. However, POSTFIX_PRECEDENCE is the
891 // highest level, so we just call parseUnaryExpression
892 // directly.
893 token = parseUnaryExpression(token.next);
894 listener.handleBinaryExpression(operator);
895 } else if ((info === OPEN_PAREN_INFO) ||
896 (info === OPEN_SQUARE_BRACKET_INFO)) {
897 token = parseArgumentOrIndexStar(token);
898 } else if ((info === PLUS_PLUS_INFO) ||
899 (info === MINUS_MINUS_INFO)) {
900 listener.handleUnaryPostfixAssignmentExpression(token);
901 token = token.next;
902 } else {
903 token = listener.unexpected(token);
904 }
905 } else if (info === IS_INFO) {
906 token = parseIsOperatorRest(token);
907 } else if (info === QUESTION_INFO) {
908 token = parseConditionalExpressionRest(token);
909 } else {
910 // Left associative, so we recurse at the next higher
911 // precedence level.
912 token = parsePrecedenceExpression(token.next, level + 1);
913 listener.handleBinaryExpression(operator);
914 }
915 info = token.info;
916 tokenLevel = info.precedence;
917 }
918 }
919 return token;
920 }
921
922 Token parseUnaryExpression(Token token) {
923 String value = token.stringValue;
924 // Prefix:
925 if (value === '+') {
926 // Dart only allows "prefix plus" as an initial part of a
927 // decimal literal. We scan it as a separate token and let
928 // the parser listener combine it with the digits.
929 Token next = token.next;
930 if (next.charOffset === token.charOffset + 1) {
931 if (next.kind === INT_TOKEN) {
932 listener.handleLiteralInt(token);
933 return next.next;
934 }
935 if (next.kind === DOUBLE_TOKEN) {
936 listener.handleLiteralDouble(token);
937 return next.next;
938 }
939 }
940 listener.recoverableError("Unexpected token '+'", token: token);
941 return parsePrecedenceExpression(next, POSTFIX_PRECEDENCE);
942 } else if ((value === '!') ||
943 (value === '-') ||
944 (value === '~')) {
945 Token operator = token;
946 // Right associative, so we recurse at the same precedence
947 // level.
948 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE);
949 listener.handleUnaryPrefixExpression(operator);
950 } else if ((value === '++') || value === '--') {
951 // TODO(ahe): Validate this is used correctly.
952 Token operator = token;
953 // Right associative, so we recurse at the same precedence
954 // level.
955 token = parsePrecedenceExpression(token.next, POSTFIX_PRECEDENCE);
956 listener.handleUnaryPrefixAssignmentExpression(operator);
957 } else {
958 token = parsePrimary(token);
959 }
960 return token;
961 }
962
963 Token parseArgumentOrIndexStar(Token token) {
964 while (true) {
965 if (optional('[', token)) {
966 Token openSquareBracket = token;
967 bool old = mayParseFunctionExpressions;
968 mayParseFunctionExpressions = true;
969 token = parseExpression(token.next);
970 mayParseFunctionExpressions = old;
971 listener.handleIndexedExpression(openSquareBracket, token);
972 token = expect(']', token);
973 } else if (optional('(', token)) {
974 token = parseArguments(token);
975 listener.endSend(token);
976 } else {
977 break;
978 }
979 }
980 return token;
981 }
982
983 Token parsePrimary(Token token) {
984 final kind = token.kind;
985 if (kind === IDENTIFIER_TOKEN) {
986 return parseSendOrFunctionLiteral(token);
987 } else if (kind === INT_TOKEN || kind === HEXADECIMAL_TOKEN) {
988 return parseLiteralInt(token);
989 } else if (kind === DOUBLE_TOKEN) {
990 return parseLiteralDouble(token);
991 } else if (kind === STRING_TOKEN) {
992 return parseLiteralString(token);
993 } else if (kind === KEYWORD_TOKEN) {
994 final value = token.stringValue;
995 if ((value === 'true') || (value === 'false')) {
996 return parseLiteralBool(token);
997 } else if (value === 'null') {
998 return parseLiteralNull(token);
999 } else if (value === 'this') {
1000 return parseThisExpression(token);
1001 } else if (value === 'super') {
1002 return parseSuperExpression(token);
1003 } else if (value === 'new') {
1004 return parseNewExpression(token);
1005 } else if (value === 'const') {
1006 return parseConstExpression(token);
1007 } else if (value === 'void') {
1008 return parseFunctionExpression(token);
1009 } else if (isIdentifier(token)) {
1010 return parseSendOrFunctionLiteral(token);
1011 } else {
1012 return listener.expectedExpression(token);
1013 }
1014 } else if (kind === OPEN_PAREN_TOKEN) {
1015 return parseParenthesizedExpressionOrFunctionLiteral(token);
1016 } else if ((kind === LT_TOKEN) ||
1017 (kind === OPEN_SQUARE_BRACKET_TOKEN) ||
1018 (kind === OPEN_CURLY_BRACKET_TOKEN) ||
1019 token.stringValue === '[]') {
1020 return parseLiteralListOrMap(token);
1021 } else {
1022 return listener.expectedExpression(token);
1023 }
1024 }
1025
1026 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
1027 BeginGroupToken beginGroup = token;
1028 int kind = beginGroup.endGroup.next.kind;
1029 if (mayParseFunctionExpressions &&
1030 (kind === FUNCTION_TOKEN || kind === OPEN_CURLY_BRACKET_TOKEN)) {
1031 return parseUnamedFunction(token);
1032 } else {
1033 bool old = mayParseFunctionExpressions;
1034 mayParseFunctionExpressions = true;
1035 token = parseParenthesizedExpression(token);
1036 mayParseFunctionExpressions = old;
1037 return token;
1038 }
1039 }
1040
1041 Token parseParenthesizedExpression(Token token) {
1042 BeginGroupToken begin = token;
1043 token = expect('(', token);
1044 token = parseExpression(token);
1045 if (begin.endGroup !== token) {
1046 listener.unexpected(token);
1047 token = begin.endGroup;
1048 }
1049 listener.handleParenthesizedExpression(begin);
1050 return expect(')', token);
1051 }
1052
1053 Token parseThisExpression(Token token) {
1054 listener.handleThisExpression(token);
1055 token = token.next;
1056 if (optional('(', token)) {
1057 // Constructor forwarding.
1058 token = parseArguments(token);
1059 listener.endSend(token);
1060 }
1061 return token;
1062 }
1063
1064 Token parseSuperExpression(Token token) {
1065 listener.handleSuperExpression(token);
1066 token = token.next;
1067 if (optional('(', token)) {
1068 // Super constructor.
1069 token = parseArguments(token);
1070 listener.endSend(token);
1071 }
1072 return token;
1073 }
1074
1075 Token parseLiteralListOrMap(Token token) {
1076 Token constKeyword = null;
1077 if (optional('const', token)) {
1078 constKeyword = token;
1079 token = token.next;
1080 }
1081 token = parseTypeArgumentsOpt(token);
1082 Token beginToken = token;
1083 int count = 0;
1084 if (optional('{', token)) {
1085 bool old = mayParseFunctionExpressions;
1086 mayParseFunctionExpressions = true;
1087 do {
1088 if (optional('}', token.next)) {
1089 token = token.next;
1090 break;
1091 }
1092 token = parseMapLiteralEntry(token.next);
1093 ++count;
1094 } while (optional(',', token));
1095 mayParseFunctionExpressions = old;
1096 listener.handleLiteralMap(count, beginToken, constKeyword, token);
1097 return expect('}', token);
1098 } else if (optional('[', token)) {
1099 bool old = mayParseFunctionExpressions;
1100 mayParseFunctionExpressions = true;
1101 do {
1102 if (optional(']', token.next)) {
1103 token = token.next;
1104 break;
1105 }
1106 token = parseExpression(token.next);
1107 ++count;
1108 } while (optional(',', token));
1109 mayParseFunctionExpressions = old;
1110 listener.handleLiteralList(count, beginToken, constKeyword, token);
1111 return expect(']', token);
1112 } else if (optional('[]', token)) {
1113 listener.handleLiteralList(0, token, constKeyword, token);
1114 return token.next;
1115 } else {
1116 listener.unexpected(token);
1117 }
1118 }
1119
1120 Token parseMapLiteralEntry(Token token) {
1121 listener.beginLiteralMapEntry(token);
1122 // Assume the listener rejects non-string keys.
1123 token = parseExpression(token);
1124 Token colon = token;
1125 token = expect(':', token);
1126 token = parseExpression(token);
1127 listener.endLiteralMapEntry(colon, token);
1128 return token;
1129 }
1130
1131 Token parseSendOrFunctionLiteral(Token token) {
1132 if (!mayParseFunctionExpressions) return parseSend(token);
1133 Token peek = peekAfterType(token);
1134 if (peek.kind === IDENTIFIER_TOKEN && isFunctionDeclaration(peek.next)) {
1135 return parseFunctionExpression(token);
1136 } else if (isFunctionDeclaration(token.next)) {
1137 return parseFunctionExpression(token);
1138 } else {
1139 return parseSend(token);
1140 }
1141 }
1142
1143 bool isFunctionDeclaration(Token token) {
1144 if (optional('(', token)) {
1145 BeginGroupToken begin = token;
1146 String afterParens = begin.endGroup.next.stringValue;
1147 if (afterParens === '{' || afterParens === '=>') {
1148 return true;
1149 }
1150 }
1151 return false;
1152 }
1153
1154 Token parseNewExpression(Token token) {
1155 Token newKeyword = token;
1156 token = expect('new', token);
1157 token = parseType(token);
1158 bool named = false;
1159 if (optional('.', token)) {
1160 named = true;
1161 token = parseIdentifier(token.next);
1162 }
1163 if (optional('(', token)) {
1164 token = parseArguments(token);
1165 } else {
1166 listener.handleNoArguments(token);
1167 token = listener.unexpected(token);
1168 }
1169 listener.handleNewExpression(newKeyword, named);
1170 return token;
1171 }
1172
1173 Token parseConstExpression(Token token) {
1174 Token constKeyword = token;
1175 token = expect('const', token);
1176 final String value = token.stringValue;
1177 if ((value === '<') ||
1178 (value === '[') ||
1179 (value === '[]') ||
1180 (value === '{')) {
1181 return parseLiteralListOrMap(constKeyword);
1182 }
1183 token = parseType(token);
1184 bool named = false;
1185 if (optional('.', token)) {
1186 named = true;
1187 token = parseIdentifier(token.next);
1188 }
1189 expect('(', token);
1190 token = parseArguments(token);
1191 listener.handleConstExpression(constKeyword, named);
1192 return token;
1193 }
1194
1195 Token parseLiteralInt(Token token) {
1196 listener.handleLiteralInt(token);
1197 return token.next;
1198 }
1199
1200 Token parseLiteralDouble(Token token) {
1201 listener.handleLiteralDouble(token);
1202 return token.next;
1203 }
1204
1205 Token parseLiteralString(Token token) {
1206 token = parseSingleLiteralString(token);
1207 int count = 1;
1208 while (token.kind === STRING_TOKEN) {
1209 token = parseSingleLiteralString(token);
1210 count++;
1211 }
1212 if (count > 1) {
1213 listener.handleStringJuxtaposition(count);
1214 }
1215 return token;
1216 }
1217
1218 Token parseSingleLiteralString(Token token) {
1219 listener.beginLiteralString(token);
1220 token = token.next;
1221 int interpolationCount = 0;
1222 while (optional('\${', token)) {
1223 token = token.next;
1224 token = parseExpression(token);
1225 token = expect('}', token);
1226 token = parseStringPart(token);
1227 ++interpolationCount;
1228 }
1229 listener.endLiteralString(interpolationCount);
1230 return token;
1231 }
1232
1233 Token parseLiteralBool(Token token) {
1234 listener.handleLiteralBool(token);
1235 return token.next;
1236 }
1237
1238 Token parseLiteralNull(Token token) {
1239 listener.handleLiteralNull(token);
1240 return token.next;
1241 }
1242
1243 Token parseSend(Token token) {
1244 listener.beginSend(token);
1245 token = parseIdentifier(token);
1246 token = parseArgumentsOpt(token);
1247 listener.endSend(token);
1248 return token;
1249 }
1250
1251 Token parseArgumentsOpt(Token token) {
1252 if (!optional('(', token)) {
1253 listener.handleNoArguments(token);
1254 return token;
1255 } else {
1256 return parseArguments(token);
1257 }
1258 }
1259
1260 Token parseArguments(Token token) {
1261 Token begin = token;
1262 listener.beginArguments(begin);
1263 assert('(' === token.stringValue);
1264 int argumentCount = 0;
1265 if (optional(')', token.next)) {
1266 listener.endArguments(argumentCount, begin, token.next);
1267 return token.next.next;
1268 }
1269 bool old = mayParseFunctionExpressions;
1270 mayParseFunctionExpressions = true;
1271 do {
1272 Token colon = null;
1273 if (optional(':', token.next.next)) {
1274 token = parseIdentifier(token.next);
1275 colon = token;
1276 }
1277 token = parseExpression(token.next);
1278 if (colon !== null) listener.handleNamedArgument(colon);
1279 ++argumentCount;
1280 } while (optional(',', token));
1281 mayParseFunctionExpressions = old;
1282 listener.endArguments(argumentCount, begin, token);
1283 return expect(')', token);
1284 }
1285
1286 Token parseIsOperatorRest(Token token) {
1287 assert(optional('is', token));
1288 Token operator = token;
1289 Token not = null;
1290 if (optional('!', token.next)) {
1291 token = token.next;
1292 not = token;
1293 }
1294 token = parseType(token.next);
1295 listener.handleIsOperator(operator, not, token);
1296 if (optional('is', token)) {
1297 // The is-operator cannot be chained, but it can take part of
1298 // expressions like: foo is Foo || foo is Bar.
1299 listener.unexpected(token);
1300 }
1301 return token;
1302 }
1303
1304 Token parseVariablesDeclaration(Token token) {
1305 token = parseVariablesDeclarationNoSemicolon(token);
1306 return expectSemicolon(token);
1307 }
1308
1309 Token parseVariablesDeclarationNoSemicolon(Token token) {
1310 int count = 1;
1311 listener.beginVariablesDeclaration(token);
1312 token = parseModifiers(token);
1313 token = parseTypeOpt(token);
1314 token = parseOptionallyInitializedIdentifier(token);
1315 while (optional(',', token)) {
1316 token = parseOptionallyInitializedIdentifier(token.next);
1317 ++count;
1318 }
1319 listener.endVariablesDeclaration(count, token);
1320 return token;
1321 }
1322
1323 Token parseOptionallyInitializedIdentifier(Token token) {
1324 listener.beginInitializedIdentifier(token);
1325 token = parseIdentifier(token);
1326 token = parseVariableInitializerOpt(token);
1327 listener.endInitializedIdentifier();
1328 return token;
1329 }
1330
1331 Token parseIfStatement(Token token) {
1332 Token ifToken = token;
1333 listener.beginIfStatement(ifToken);
1334 token = expect('if', token);
1335 token = parseParenthesizedExpression(token);
1336 token = parseStatement(token);
1337 Token elseToken = null;
1338 if (optional('else', token)) {
1339 elseToken = token;
1340 token = parseStatement(token.next);
1341 }
1342 listener.endIfStatement(ifToken, elseToken);
1343 return token;
1344 }
1345
1346 Token parseForStatement(Token token) {
1347 Token forToken = token;
1348 listener.beginForStatement(forToken);
1349 token = expect('for', token);
1350 token = expect('(', token);
1351 token = parseVariablesDeclarationOrExpressionOpt(token);
1352 if (optional('in', token)) {
1353 return parseForInRest(forToken, token);
1354 } else {
1355 return parseForRest(forToken, token);
1356 }
1357 }
1358
1359 Token parseVariablesDeclarationOrExpressionOpt(Token token) {
1360 final String value = token.stringValue;
1361 if (value === ';') {
1362 listener.handleNoExpression(token);
1363 return token;
1364 } else if ((value === 'var') || (value === 'final')) {
1365 return parseVariablesDeclarationNoSemicolon(token);
1366 }
1367 Token identifier = peekIdentifierAfterType(token);
1368 if (identifier !== null) {
1369 assert(isIdentifier(identifier));
1370 Token afterId = identifier.next;
1371 int afterIdKind = afterId.kind;
1372 if (afterIdKind === EQ_TOKEN || afterIdKind === SEMICOLON_TOKEN ||
1373 afterIdKind === COMMA_TOKEN || optional('in', afterId)) {
1374 return parseVariablesDeclarationNoSemicolon(token);
1375 }
1376 }
1377 return parseExpression(token);
1378 }
1379
1380 Token parseForRest(Token forToken, Token token) {
1381 token = expectSemicolon(token);
1382 if (optional(';', token)) {
1383 token = parseEmptyStatement(token);
1384 } else {
1385 token = parseExpressionStatement(token);
1386 }
1387 int expressionCount = 0;
1388 while (true) {
1389 if (optional(')', token)) break;
1390 token = parseExpression(token);
1391 ++expressionCount;
1392 if (optional(',', token)) {
1393 token = token.next;
1394 } else {
1395 break;
1396 }
1397 }
1398 token = expect(')', token);
1399 token = parseStatement(token);
1400 listener.endForStatement(expressionCount, forToken, token);
1401 return token;
1402 }
1403
1404 Token parseForInRest(Token forToken, Token token) {
1405 assert(optional('in', token));
1406 Token inKeyword = token;
1407 token = parseExpression(token.next);
1408 token = expect(')', token);
1409 token = parseStatement(token);
1410 listener.endForInStatement(forToken, inKeyword, token);
1411 return token;
1412 }
1413
1414 Token parseWhileStatement(Token token) {
1415 Token whileToken = token;
1416 listener.beginWhileStatement(whileToken);
1417 token = expect('while', token);
1418 token = parseParenthesizedExpression(token);
1419 token = parseStatement(token);
1420 listener.endWhileStatement(whileToken, token);
1421 return token;
1422 }
1423
1424 Token parseDoWhileStatement(Token token) {
1425 Token doToken = token;
1426 listener.beginDoWhileStatement(doToken);
1427 token = expect('do', token);
1428 token = parseStatement(token);
1429 Token whileToken = token;
1430 token = expect('while', token);
1431 token = parseParenthesizedExpression(token);
1432 listener.endDoWhileStatement(doToken, whileToken, token);
1433 return expectSemicolon(token);
1434 }
1435
1436 Token parseBlock(Token token) {
1437 Token begin = token;
1438 listener.beginBlock(begin);
1439 int statementCount = 0;
1440 token = expect('{', token);
1441 while (notEofOrValue('}', token)) {
1442 token = parseStatement(token);
1443 ++statementCount;
1444 }
1445 listener.endBlock(statementCount, begin, token);
1446 return expect('}', token);
1447 }
1448
1449 Token parseThrowStatement(Token token) {
1450 Token throwToken = token;
1451 listener.beginThrowStatement(throwToken);
1452 token = expect('throw', token);
1453 if (optional(';', token)) {
1454 listener.endRethrowStatement(throwToken, token);
1455 return token.next;
1456 } else {
1457 token = parseExpression(token);
1458 listener.endThrowStatement(throwToken, token);
1459 return expectSemicolon(token);
1460 }
1461 }
1462
1463 Token parseTryStatement(Token token) {
1464 assert(optional('try', token));
1465 Token tryKeyword = token;
1466 listener.beginTryStatement(tryKeyword);
1467 token = parseBlock(token.next);
1468 int catchCount = 0;
1469 while (optional('catch', token)) {
1470 Token catchKeyword = token;
1471 // TODO(ahe): Validate the "parameters".
1472 token = parseFormalParameters(token.next);
1473 token = parseBlock(token);
1474 ++catchCount;
1475 listener.handleCatchBlock(catchKeyword);
1476 }
1477 Token finallyKeyword = null;
1478 if (optional('finally', token)) {
1479 finallyKeyword = token;
1480 token = parseBlock(token.next);
1481 listener.handleFinallyBlock(finallyKeyword);
1482 }
1483 listener.endTryStatement(catchCount, tryKeyword, finallyKeyword);
1484 return token;
1485 }
1486
1487 Token parseSwitchStatement(Token token) {
1488 assert(optional('switch', token));
1489 Token switchKeyword = token;
1490 listener.beginSwitchStatement(switchKeyword);
1491 token = parseParenthesizedExpression(token.next);
1492 token = parseSwitchBlock(token);
1493 listener.endSwitchStatement(switchKeyword, token);
1494 return token.next;
1495 }
1496
1497 Token parseSwitchBlock(Token token) {
1498 Token begin = token;
1499 listener.beginSwitchBlock(begin);
1500 token = expect('{', token);
1501 int caseCount = 0;
1502 while (token.kind !== EOF_TOKEN) {
1503 if (optional('}', token)) {
1504 break;
1505 }
1506 token = parseSwitchCase(token);
1507 ++caseCount;
1508 }
1509 listener.endSwitchBlock(caseCount, begin, token);
1510 expect('}', token);
1511 return token;
1512 }
1513
1514 Token parseSwitchCase(Token token) {
1515 Token begin = token;
1516 Token defaultKeyword = null;
1517 Token label = null;
1518 // First an optional label.
1519 if (isIdentifier(token)) {
1520 label = token;
1521 token = parseIdentifier(token);
1522 token = expect(':', token);
1523 }
1524 // Then one or more case expressions, the last of which may be
1525 // 'default' instead.
1526 int expressionCount = 0;
1527 String value = token.stringValue;
1528 do {
1529 if (value === 'default') {
1530 defaultKeyword = token;
1531 token = expect(':', token.next);
1532 break;
1533 }
1534 token = expect('case', token);
1535 token = parseExpression(token);
1536 token = expect(':', token);
1537 expressionCount++;
1538 value = token.stringValue;
1539 } while (value === 'case' || value === 'default');
1540 // Finally zero or more statements.
1541 int statementCount = 0;
1542 while (token.kind !== EOF_TOKEN) {
1543 String value;
1544 if (isIdentifier(token) && optional(':', token.next)) {
1545 // Skip label.
1546 value = token.next.next.stringValue;
1547 } else {
1548 value = token.stringValue;
1549 }
1550 if (value === 'case' || value === 'default' || value === '}') {
1551 break;
1552 } else {
1553 token = parseStatement(token);
1554 ++statementCount;
1555 }
1556 }
1557 listener.handleSwitchCase(label, expressionCount, defaultKeyword,
1558 statementCount, begin, token);
1559 return token;
1560 }
1561
1562 Token parseBreakStatement(Token token) {
1563 assert(optional('break', token));
1564 Token breakKeyword = token;
1565 token = token.next;
1566 bool hasTarget = false;
1567 if (isIdentifier(token)) {
1568 token = parseIdentifier(token);
1569 hasTarget = true;
1570 }
1571 listener.handleBreakStatement(hasTarget, breakKeyword, token);
1572 return expectSemicolon(token);
1573 }
1574
1575 Token parseContinueStatement(Token token) {
1576 assert(optional('continue', token));
1577 Token continueKeyword = token;
1578 token = token.next;
1579 bool hasTarget = false;
1580 if (isIdentifier(token)) {
1581 token = parseIdentifier(token);
1582 hasTarget = true;
1583 }
1584 listener.handleContinueStatement(hasTarget, continueKeyword, token);
1585 return expectSemicolon(token);
1586 }
1587
1588 Token parseEmptyStatement(Token token) {
1589 listener.handleEmptyStatement(token);
1590 return expectSemicolon(token);
1591 }
1592 }
OLDNEW
« no previous file with comments | « frog/leg/scanner/node_scanner_bench.dart ('k') | frog/leg/scanner/parser_bench.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698