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

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

Issue 9190038: Handle escapes in string literals. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rewrote to use iterators on SourceString. Created 8 years, 11 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/ssa/codegen.dart ('k') | frog/leg/ssa/ssa.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 interface HVisitor<R> { 5 interface HVisitor<R> {
6 R visitAdd(HAdd node); 6 R visitAdd(HAdd node);
7 R visitBailoutTarget(HBailoutTarget node); 7 R visitBailoutTarget(HBailoutTarget node);
8 R visitBitAnd(HBitAnd node); 8 R visitBitAnd(HBitAnd node);
9 R visitBitNot(HBitNot node); 9 R visitBitNot(HBitNot node);
10 R visitBitOr(HBitOr node); 10 R visitBitOr(HBitOr node);
(...skipping 1567 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 /** 1578 /**
1579 * Finds the quote type for a string given a part of it containing the 1579 * Finds the quote type for a string given a part of it containing the
1580 * starting quote. Returns flags, but doesn't include HAS_LEFT_QUOTE 1580 * starting quote. Returns flags, but doesn't include HAS_LEFT_QUOTE
1581 * or HAS_RIGHT_QUOTE. 1581 * or HAS_RIGHT_QUOTE.
1582 */ 1582 */
1583 static int flagsFromLeftQuote(SourceString sourceString) { 1583 static int flagsFromLeftQuote(SourceString sourceString) {
1584 Iterator<int> source = sourceString.iterator(); 1584 Iterator<int> source = sourceString.iterator();
1585 int flags = 0; 1585 int flags = 0;
1586 int start = 0; 1586 int start = 0;
1587 int quoteChar = source.next(); 1587 int quoteChar = source.next();
1588 if (quoteChar == '@'.charCodeAt(0)) { 1588 if (quoteChar == $AT) {
1589 flags |= RAW; 1589 flags |= RAW;
1590 start = 1; 1590 start = 1;
1591 quoteChar = source.next(); 1591 quoteChar = source.next();
1592 } 1592 }
1593 if (quoteChar == '\''.charCodeAt(0)) { 1593 if (quoteChar == $SQ) {
1594 flags |= SINGLE_QUOTED; 1594 flags |= SINGLE_QUOTED;
1595 } else { 1595 } else {
1596 assert(quoteChar == '"'.charCodeAt(0)); 1596 assert(quoteChar == $DQ);
1597 } 1597 }
1598 // String has one quote. Check it if has three. 1598 // String has one quote. Check it if has three.
1599 // If it only have two, the string must be an empty string literal, 1599 // If it only have two, the string must be an empty string literal,
1600 // and end after the second quote. 1600 // and end after the second quote.
1601 if (source.hasNext() && source.next() == quoteChar && source.hasNext()) { 1601 if (source.hasNext() && source.next() == quoteChar && source.hasNext()) {
1602 assert(source.next() == quoteChar); 1602 assert(source.next() == quoteChar);
1603 flags |= MULTI_LINE; 1603 flags |= MULTI_LINE;
1604 } 1604 }
1605 return flags; 1605 return flags;
1606 } 1606 }
(...skipping 20 matching lines...) Expand all
1627 if ((flags & HAS_BOTH_QUOTES) == 0) return wrappedString; 1627 if ((flags & HAS_BOTH_QUOTES) == 0) return wrappedString;
1628 return wrappedString.copyWithoutQuotes(leftQuoteLength, 1628 return wrappedString.copyWithoutQuotes(leftQuoteLength,
1629 rightQuoteLength); 1629 rightQuoteLength);
1630 } 1630 }
1631 1631
1632 bool get hasLeftQuote() => (flags & HAS_LEFT_QUOTE) != 0; 1632 bool get hasLeftQuote() => (flags & HAS_LEFT_QUOTE) != 0;
1633 bool get hasRightQuote() => (flags & HAS_RIGHT_QUOTE) != 0; 1633 bool get hasRightQuote() => (flags & HAS_RIGHT_QUOTE) != 0;
1634 bool get isMultiLine() => (flags & MULTI_LINE) != 0; 1634 bool get isMultiLine() => (flags & MULTI_LINE) != 0;
1635 bool get isRaw() => (flags & RAW) != 0; 1635 bool get isRaw() => (flags & RAW) != 0;
1636 String get quoteChar() => ((flags & SINGLE_QUOTED) != 0) ? "'" : '"'; 1636 String get quoteChar() => ((flags & SINGLE_QUOTED) != 0) ? "'" : '"';
1637 int get quoteCharCode() => ((flags & SINGLE_QUOTED) != 0) ? $SQ : $DQ;
1637 1638
1638 int get leftQuoteLength() => 1639 int get leftQuoteLength() =>
1639 hasLeftQuote ? (isRaw ? 1 : 0) + (isMultiLine ? 3 : 1) : 0; 1640 hasLeftQuote ? (isRaw ? 1 : 0) + (isMultiLine ? 3 : 1) : 0;
1640 int get rightQuoteLength() => 1641 int get rightQuoteLength() =>
1641 hasRightQuote ? (isMultiLine ? 3 : 1) : 0; 1642 hasRightQuote ? (isMultiLine ? 3 : 1) : 0;
1642 static int leftQuoteLengthFromFlags(int flags) { 1643 static int leftQuoteLengthFromFlags(int flags) {
1643 if ((flags & HAS_LEFT_QUOTE) == 0) return 0; 1644 if ((flags & HAS_LEFT_QUOTE) == 0) return 0;
1644 return (flags & (RAW | MULTI_LINE)) + 1; 1645 return (flags & (RAW | MULTI_LINE)) + 1;
1645 } 1646 }
1646 static int rightQuoteLengthFromFlags(int flags) { 1647 static int rightQuoteLengthFromFlags(int flags) {
1647 if ((flags & HAS_RIGHT_QUOTE) == 0) return 0; 1648 if ((flags & HAS_RIGHT_QUOTE) == 0) return 0;
1648 return (flags & MULTI_LINE) + 1; 1649 return (flags & MULTI_LINE) + 1;
1649 } 1650 }
1650 1651
1651 bool isEmpty() => unquotedSource().isEmpty(); 1652 bool isEmpty() => unquotedSource().isEmpty();
1652 1653
1654 static int hexValue(int hexDigit) {
1655 // hexDigit is one of '0'..'9', 'A'..'F' and 'a'..'f'.
1656 if (hexDigit <= $9) {
1657 return hexDigit - $0;
1658 }
1659 // Make letters lowercase.
1660 hexDigit |= $a - $A;
floitsch 2012/01/16 14:29:50 This "trick" depends on an ascii property where lo
Lasse Reichstein Nielsen 2012/01/17 08:50:51 I assume Unicode. There are no other encodings. FI
1661 hexDigit -= $a - 10;
1662 assert(10 <= hexDigit && hexDigit <= 15);
1663 return hexDigit;
1664 }
1665
1666
1667 static void writeUnicodeEscape(Iterator<int> iter, StringBuffer buffer) {
1668 buffer.add(@'\u');
1669 int code = iter.next();
1670 if (code == $OPEN_CURLY_BRACKET) {
1671 // In Dart, '\u{'x{0..7}'}' is a valid escape, but not in
1672 // JS. Convert to a \uxxxx escape.
1673 int value = 0;
1674 int hexDigit = iter.next();
1675 do {
1676 value = value * 16 + hexValue(hexDigit);
1677 hexDigit = iter.next();
1678 } while (hexDigit !== $CLOSE_CURLY_BRACKET); // until '}'.
floitsch 2012/01/16 14:29:50 remove comment.
Lasse Reichstein Nielsen 2012/01/17 08:50:51 Done.
1679 // JavaScript only supports characters in the BMP.
1680 // TODO(lrn): Handle characters outside the BMP, e.g.,
1681 // by having a slow-case string class.
1682 if (value > 0xffff) value = 0xfffd;
floitsch 2012/01/16 14:29:50 I would prefer bailing out (compiler.cancel).
Lasse Reichstein Nielsen 2012/01/17 08:50:51 Done.
1683
1684 for (int j = 12; j >= 0; j -= 4) {
1685 int digit = (value >> j) & 0xf;
1686 buffer.add("0123456789abcdef"[digit]);
1687 }
1688 return;
1689 }
1690 for (int i = 0; i < 4; i++) {
1691 if (i > 0) code = iter.next();
1692 buffer.add(new String.fromCharCodes([code]));
1693 }
1694 }
1695
1696 /**
1697 * Write the contents of the quoted string to a [StringBuffer] in
1698 * a form that is valid as JavaScript string literal content.
1699 * The string is assumed quoted by [quote] characters.
1700 * This method doesn't try to make the shortest string, but rather
1701 * to be as close to the original string as possible.
1702 */
1703 void writeEscaped(StringBuffer buffer, int quote) {
1704 bool raw = this.isRaw;
1705 Iterator<int> iter =
1706 wrappedString.copyWithoutQuotes(leftQuoteLength,
1707 rightQuoteLength).iterator();
1708 while (iter.hasNext()) {
1709 int code = iter.next();
1710 if (code == quote) {
1711 // We need to add a backslash before quotes, both in normal
1712 // and in raw strings.
1713 buffer.add(@'\');
1714 buffer.add(code == $SQ ? "'" : '"');
1715 } else if (code == $LF) {
1716 // Newlines in strings only occour in multiline strings.
1717 // They need to be written using escapes in JS..
1718 assert(isMultiLine);
1719 buffer.add(@'\n');
1720 } else if (code == $CR) {
1721 assert(isMultiLine);
1722 buffer.add(@'\r');
1723 } else if (code == $LS || code == $PS) {
1724 // These Unicode line terminators are invalid in JS strings.
1725 buffer.add(code == $LS ? @'\u2028' : @'\u2029');
1726 } else if (code != $BACKSLASH) {
1727 buffer.add(new String.fromCharCodes([code]));
1728 } else if (raw) {
1729 buffer.add(@'\\');
1730 } else {
1731 code = iter.next();
1732 switch (code) {
1733 case $u:
1734 writeUnicodeEscape(iter, buffer);
1735 break;
1736 case $x:
1737 buffer.add(@'\x');
1738 // Remaining character will be copied literally.
1739 break;
1740 // Character escapes that identical in meaning in JS.
1741 case $b: buffer.add(@'\b'); break;
1742 case $f: buffer.add(@'\f'); break;
1743 case $n: buffer.add(@'\n'); break;
1744 case $r: buffer.add(@'\r'); break;
1745 case $t: buffer.add(@'\t'); break;
1746 case $v: buffer.add(@'\v'); break;
1747 // Identity escapes that must be escaped in JS strings.
1748 case $BACKSLASH: buffer.add(@'\\'); break;
1749 case $LF: buffer.add(@'\n'); break;
1750 case $CR: buffer.add(@'\r'); break;
1751 case $LS: buffer.add(@'\u2028'); break;
1752 case $PS: buffer.add(@'\u2029'); break;
1753 // Quotes may or may not need the escape.
1754 case $SQ:
1755 case $DQ:
1756 // Only escape quotes if they match the generated string quotes.
1757 if (code == quote) buffer.add(@'\');
1758 buffer.add(code == $SQ ? "'" : '"');
1759 break;
1760 default:
1761 // All other escaped characters are identity escapes,
1762 // and don't need a backslash in JS.
1763 buffer.add(new String.fromCharCodes([code]));
1764 break;
1765 }
1766 }
1767 }
1768 }
1769
1653 /** 1770 /**
1654 * Does a conservative test for equality between two quoted strings. 1771 * Does a conservative test for equality between two quoted strings.
1655 * Returns true if the two definitly have the same string. 1772 * Returns true if the two definitly have the same string.
1656 * Returns false if the strings are different, or if it's not possible 1773 * Returns false if the strings are different, or if it's not possible
1657 * to (quickly) determine whether they are equal. 1774 * to (quickly) determine whether they are equal.
1658 */ 1775 */
1659 bool definitlyEquals(QuotedString other) { 1776 bool definitlyEquals(QuotedString other) {
1660 return flags == other.flags && wrappedString == other.wrappedString; 1777 return flags == other.flags && wrappedString == other.wrappedString;
1661 } 1778 }
1662 1779
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
2107 2224
2108 HInstruction get expression() => inputs[0]; 2225 HInstruction get expression() => inputs[0];
2109 2226
2110 HType computeType() => HType.BOOLEAN; 2227 HType computeType() => HType.BOOLEAN;
2111 bool hasExpectedType() => true; 2228 bool hasExpectedType() => true;
2112 2229
2113 accept(HVisitor visitor) => visitor.visitIs(this); 2230 accept(HVisitor visitor) => visitor.visitIs(this);
2114 2231
2115 toString() => "$expression is $typeExpression"; 2232 toString() => "$expression is $typeExpression";
2116 } 2233 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/codegen.dart ('k') | frog/leg/ssa/ssa.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698