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

Side by Side Diff: lib/compiler/implementation/scanner/parser.dart

Issue 10387080: Accept more labels per switch case. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove debug-print. Created 8 years, 7 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * An event generating parser of Dart programs. This parser expects 6 * An event generating parser of Dart programs. This parser expects
7 * all tokens in a linked list (aka a token stream). 7 * all tokens in a linked list (aka a token stream).
8 * 8 *
9 * The class [Scanner] is used to generate a token stream. See the 9 * The class [Scanner] is used to generate a token stream. See the
10 * file scanner.dart. 10 * file scanner.dart.
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 844
845 Token parseLabel(Token token) { 845 Token parseLabel(Token token) {
846 token = parseIdentifier(token); 846 token = parseIdentifier(token);
847 Token colon = token; 847 Token colon = token;
848 token = expect(':', token); 848 token = expect(':', token);
849 listener.handleLabel(colon); 849 listener.handleLabel(colon);
850 return token; 850 return token;
851 } 851 }
852 852
853 Token parseLabeledStatement(Token token) { 853 Token parseLabeledStatement(Token token) {
854 listener.beginLabeledStatement(token); 854 int labelCount = 0;
855 token = parseLabel(token); 855 do {
856 token = parseLabel(token);
857 labelCount++;
858 } while (isIdentifier(token) && optional(':', token.next));
859 listener.beginLabeledStatement(token, labelCount);
856 token = parseStatement(token); 860 token = parseStatement(token);
857 listener.endLabeledStatement(); 861 listener.endLabeledStatement(labelCount);
858 return token; 862 return token;
859 } 863 }
860 864
861 Token parseExpressionStatement(Token token) { 865 Token parseExpressionStatement(Token token) {
862 listener.beginExpressionStatement(token); 866 listener.beginExpressionStatement(token);
863 token = parseExpression(token); 867 token = parseExpression(token);
864 listener.endExpressionStatement(token); 868 listener.endExpressionStatement(token);
865 return expectSemicolon(token); 869 return expectSemicolon(token);
866 } 870 }
867 871
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 assert(optional('switch', token)); 1551 assert(optional('switch', token));
1548 Token switchKeyword = token; 1552 Token switchKeyword = token;
1549 listener.beginSwitchStatement(switchKeyword); 1553 listener.beginSwitchStatement(switchKeyword);
1550 token = parseParenthesizedExpression(token.next); 1554 token = parseParenthesizedExpression(token.next);
1551 token = parseSwitchBlock(token); 1555 token = parseSwitchBlock(token);
1552 listener.endSwitchStatement(switchKeyword, token); 1556 listener.endSwitchStatement(switchKeyword, token);
1553 return token.next; 1557 return token.next;
1554 } 1558 }
1555 1559
1556 Token parseSwitchBlock(Token token) { 1560 Token parseSwitchBlock(Token token) {
1561 /**
1562 * Peek after the following labels (if any). The following token
1563 * is used to determine if the labels belong to a statement or a
1564 * switch case.
1565 */
1566 Token peekPastLabels(Token peek) {
ahe 2012/05/14 09:24:25 I would prefer if this function's argument was nam
Lasse Reichstein Nielsen 2012/05/14 10:34:58 It's now a top-level function. I'll rename "peek"
1567 Token pre = peek;
ahe 2012/05/14 09:24:25 Unused variable?
Lasse Reichstein Nielsen 2012/05/14 10:34:58 Done.
1568 while (isIdentifier(peek) && optional(':', peek.next)) {
1569 peek = peek.next.next;
1570 }
1571 return peek;
1572 }
1573
1574 // When entering or leaving [parseSwitchCase], peek points to the first
1575 // token that isn't a label.
1576 Token peek;
ahe 2012/05/14 09:24:25 It is confusing that peekPastLabels has "peek" par
Lasse Reichstein Nielsen 2012/05/14 10:34:58 It was actually deliberate. Alas, parameter is now
1577
1578 /**
1579 * Parse a group of labels, cases and possibly a default keyword and
1580 * the statements that they select.
1581 */
1582 Token parseSwitchCase(Token token) {
ahe 2012/05/14 09:24:25 This method is definitely something that I think a
Lasse Reichstein Nielsen 2012/05/14 10:34:58 It's avoided, but at the cost of potentially peeki
1583 Token begin = token;
1584 Token defaultKeyword = null;
1585 int expressionCount = 0;
1586 int labelCount = 0;
1587
1588 while (true) {
1589 // Loop until we find something that can't be part of a switch case.
1590 String value = peek.stringValue;
1591 if (value === 'default') {
1592 while (token !== peek) {
1593 token = parseLabel(token);
1594 labelCount++;
1595 }
1596 defaultKeyword = token;
1597 token = expect(':', token.next);
1598 peek = token;
1599 break;
1600 } else if (value === 'case') {
1601 while (token !== peek) {
1602 token = parseLabel(token);
1603 labelCount++;
1604 }
1605 Token caseKeyword = token;
1606 token = parseExpression(token.next);
1607 Token colonToken = token;
1608 token = expect(':', token);
1609 listener.handleCaseMatch(caseKeyword, colonToken);
1610 expressionCount++;
1611 peek = peekPastLabels(token);
1612 } else {
1613 break;
1614 }
1615 }
1616 // Finally zero or more statements.
1617 int statementCount = 0;
1618 while (token.kind !== EOF_TOKEN) {
1619 String value = peek.stringValue;
1620 if (value === 'case' || value === 'default' ||
1621 (value === '}' && token === peek)) {
1622 // A label just before "}" will be handled as a statement error.
1623 break;
1624 } else {
1625 token = parseStatement(token);
1626 }
1627 statementCount++;
1628 peek = peekPastLabels(token);
1629 }
1630 listener.handleSwitchCase(labelCount, expressionCount, defaultKeyword,
1631 statementCount, begin, token);
1632 return token;
1633 }
1634
1557 Token begin = token; 1635 Token begin = token;
1558 listener.beginSwitchBlock(begin); 1636 listener.beginSwitchBlock(begin);
1559 token = expect('{', token); 1637 token = expect('{', token);
1560 int caseCount = 0; 1638 int caseCount = 0;
1639 peek = peekPastLabels(token);
1561 while (token.kind !== EOF_TOKEN) { 1640 while (token.kind !== EOF_TOKEN) {
1562 if (optional('}', token)) { 1641 if (optional('}', token)) {
1563 break; 1642 break;
1564 } 1643 }
1565 token = parseSwitchCase(token); 1644 token = parseSwitchCase(token);
1566 ++caseCount; 1645 ++caseCount;
1567 } 1646 }
1568 listener.endSwitchBlock(caseCount, begin, token); 1647 listener.endSwitchBlock(caseCount, begin, token);
1569 expect('}', token); 1648 expect('}', token);
1570 return token; 1649 return token;
1571 } 1650 }
1572 1651
1573 Token parseSwitchCase(Token token) {
1574 Token begin = token;
1575 Token defaultKeyword = null;
1576 Token label = null;
1577 // First an optional label.
1578 if (isIdentifier(token)) {
1579 label = token;
1580 token = parseLabel(token);
1581 }
1582 // Then one or more case expressions, the last of which may be
1583 // 'default' instead.
1584 int expressionCount = 0;
1585 {
1586 String value = token.stringValue;
1587 do {
1588 if (value === 'default') {
1589 defaultKeyword = token;
1590 token = expect(':', token.next);
1591 break;
1592 }
1593 token = expect('case', token);
1594 token = parseExpression(token);
1595 token = expect(':', token);
1596 expressionCount++;
1597 value = token.stringValue;
1598 } while (value === 'case' || value === 'default');
1599 }
1600 // Finally zero or more statements.
1601 int statementCount = 0;
1602 while (token.kind !== EOF_TOKEN) {
1603 String value;
1604 if (isIdentifier(token) && optional(':', token.next)) {
1605 // Skip label.
1606 value = token.next.next.stringValue;
1607 } else {
1608 value = token.stringValue;
1609 }
1610 if (value === 'case' || value === 'default' || value === '}') {
1611 break;
1612 } else {
1613 token = parseStatement(token);
1614 ++statementCount;
1615 }
1616 }
1617 listener.handleSwitchCase(label, expressionCount, defaultKeyword,
1618 statementCount, begin, token);
1619 return token;
1620 }
1621 1652
1622 Token parseBreakStatement(Token token) { 1653 Token parseBreakStatement(Token token) {
1623 assert(optional('break', token)); 1654 assert(optional('break', token));
1624 Token breakKeyword = token; 1655 Token breakKeyword = token;
1625 token = token.next; 1656 token = token.next;
1626 bool hasTarget = false; 1657 bool hasTarget = false;
1627 if (isIdentifier(token)) { 1658 if (isIdentifier(token)) {
1628 token = parseIdentifier(token); 1659 token = parseIdentifier(token);
1629 hasTarget = true; 1660 hasTarget = true;
1630 } 1661 }
(...skipping 12 matching lines...) Expand all
1643 } 1674 }
1644 listener.handleContinueStatement(hasTarget, continueKeyword, token); 1675 listener.handleContinueStatement(hasTarget, continueKeyword, token);
1645 return expectSemicolon(token); 1676 return expectSemicolon(token);
1646 } 1677 }
1647 1678
1648 Token parseEmptyStatement(Token token) { 1679 Token parseEmptyStatement(Token token) {
1649 listener.handleEmptyStatement(token); 1680 listener.handleEmptyStatement(token);
1650 return expectSemicolon(token); 1681 return expectSemicolon(token);
1651 } 1682 }
1652 } 1683 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698