Chromium Code Reviews| 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 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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) { | |
| 1567 Token pre = peek; | |
| 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; | |
| 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) { | |
| 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) { | |
|
ahe
2012/05/14 09:31:24
I dont' think the parser reports errors for this:
Lasse Reichstein Nielsen
2012/05/14 10:34:58
It generates an "unbalanced '{'" error.
| |
| 1619 String value = peek.stringValue; | |
| 1620 if (value === 'case' || value === 'default' || | |
|
ahe
2012/05/14 09:31:24
Please add parentheses around these expressions. I
Lasse Reichstein Nielsen
2012/05/14 10:34:58
Done.
Maybe putting them on separate lines is bett
ahe
2012/05/14 10:44:09
Seriously: I do not understand what it means. This
| |
| 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, | |
|
ahe
2012/05/14 09:31:24
Should labelCount and expressionCount be added tog
Lasse Reichstein Nielsen
2012/05/14 10:34:58
I prefer letting the listener decide that.
| |
| 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 Loading... | |
| 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 } |
| OLD | NEW |