| OLD | NEW |
| 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 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 ++caseCount; | 1566 ++caseCount; |
| 1567 } | 1567 } |
| 1568 listener.endSwitchBlock(caseCount, begin, token); | 1568 listener.endSwitchBlock(caseCount, begin, token); |
| 1569 expect('}', token); | 1569 expect('}', token); |
| 1570 return token; | 1570 return token; |
| 1571 } | 1571 } |
| 1572 | 1572 |
| 1573 Token parseSwitchCase(Token token) { | 1573 Token parseSwitchCase(Token token) { |
| 1574 Token begin = token; | 1574 Token begin = token; |
| 1575 Token defaultKeyword = null; | 1575 Token defaultKeyword = null; |
| 1576 Token label = null; | 1576 |
| 1577 // First an optional label. | 1577 /** |
| 1578 if (isIdentifier(token)) { | 1578 * Peek ahead in the token stream to see what's after a sequence |
| 1579 label = token; | 1579 * of labels. We don't parse the labels before we know whether we |
| 1580 token = parseLabel(token); | 1580 * need to call [listener.beginLabeledStatement]. |
| 1581 */ |
| 1582 Token peekAfterLabels(Token token) { |
| 1583 while (isIdentifier(token) && optional(':', token.next)) { |
| 1584 token = token.next.next; |
| 1585 } |
| 1586 return token; |
| 1581 } | 1587 } |
| 1582 // Then one or more case expressions, the last of which may be | 1588 |
| 1583 // 'default' instead. | |
| 1584 int expressionCount = 0; | 1589 int expressionCount = 0; |
| 1585 { | 1590 int labelCount = 0; |
| 1586 String value = token.stringValue; | 1591 |
| 1587 do { | 1592 Token parseLabelsUntil(Token token, Token limit) { |
| 1588 if (value === 'default') { | 1593 while (token !== limit) { |
| 1589 defaultKeyword = token; | 1594 token = parseLabel(token); |
| 1590 token = expect(':', token.next); | 1595 labelCount++; |
| 1591 break; | 1596 } |
| 1592 } | 1597 return token; |
| 1593 token = expect('case', token); | 1598 } |
| 1594 token = parseExpression(token); | 1599 |
| 1600 while (true) { |
| 1601 // Look-ahead to after a sequence of labels. The labels can belong to |
| 1602 // either a case or a following statement. |
| 1603 Token peek = peekAfterLabels(token); |
| 1604 // Loop until we find something that can't be part of a switch case. |
| 1605 String value = peek.stringValue; |
| 1606 if (value === 'default') { |
| 1607 token = parseLabelsUntil(token, peek); |
| 1608 defaultKeyword = token; |
| 1609 token = expect(':', token.next); |
| 1610 break; |
| 1611 } else if (value === 'case') { |
| 1612 token = parseLabelsUntil(token, peek); |
| 1613 Token caseKeyword = token; |
| 1614 token = parseExpression(token.next); |
| 1615 Token colon = token; |
| 1595 token = expect(':', token); | 1616 token = expect(':', token); |
| 1617 listener.handleCaseMatch(caseKeyword, colon); |
| 1596 expressionCount++; | 1618 expressionCount++; |
| 1597 value = token.stringValue; | 1619 } else { |
| 1598 } while (value === 'case' || value === 'default'); | 1620 break; |
| 1621 } |
| 1599 } | 1622 } |
| 1600 // Finally zero or more statements. | 1623 // Finally zero or more statements. |
| 1601 int statementCount = 0; | 1624 int statementCount = 0; |
| 1602 while (token.kind !== EOF_TOKEN) { | 1625 while (token.kind !== EOF_TOKEN) { |
| 1603 String value; | 1626 Token peek = peekAfterLabels(token); |
| 1604 if (isIdentifier(token) && optional(':', token.next)) { | 1627 String value = peek.stringValue; |
| 1605 // Skip label. | 1628 if (value === 'case' || value === 'default' || |
| 1606 value = token.next.next.stringValue; | 1629 (value === '}' && peek === token)) { |
| 1607 } else { | 1630 // A label just before "}" will be handled as a statement error. |
| 1608 value = token.stringValue; | |
| 1609 } | |
| 1610 if (value === 'case' || value === 'default' || value === '}') { | |
| 1611 break; | 1631 break; |
| 1612 } else { | 1632 } else { |
| 1613 token = parseStatement(token); | 1633 token = parseStatement(token); |
| 1614 ++statementCount; | 1634 ++statementCount; |
| 1615 } | 1635 } |
| 1616 } | 1636 } |
| 1617 listener.handleSwitchCase(label, expressionCount, defaultKeyword, | 1637 listener.handleSwitchCase(labelCount, expressionCount, defaultKeyword, |
| 1618 statementCount, begin, token); | 1638 statementCount, begin, token); |
| 1619 return token; | 1639 return token; |
| 1620 } | 1640 } |
| 1621 | 1641 |
| 1622 Token parseBreakStatement(Token token) { | 1642 Token parseBreakStatement(Token token) { |
| 1623 assert(optional('break', token)); | 1643 assert(optional('break', token)); |
| 1624 Token breakKeyword = token; | 1644 Token breakKeyword = token; |
| 1625 token = token.next; | 1645 token = token.next; |
| 1626 bool hasTarget = false; | 1646 bool hasTarget = false; |
| 1627 if (isIdentifier(token)) { | 1647 if (isIdentifier(token)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1643 } | 1663 } |
| 1644 listener.handleContinueStatement(hasTarget, continueKeyword, token); | 1664 listener.handleContinueStatement(hasTarget, continueKeyword, token); |
| 1645 return expectSemicolon(token); | 1665 return expectSemicolon(token); |
| 1646 } | 1666 } |
| 1647 | 1667 |
| 1648 Token parseEmptyStatement(Token token) { | 1668 Token parseEmptyStatement(Token token) { |
| 1649 listener.handleEmptyStatement(token); | 1669 listener.handleEmptyStatement(token); |
| 1650 return expectSemicolon(token); | 1670 return expectSemicolon(token); |
| 1651 } | 1671 } |
| 1652 } | 1672 } |
| OLD | NEW |