Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017, 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 licenset hat can be found in the LICENSE file. | |
| 4 | |
| 5 library dart_scanner.error_token; | |
| 6 | |
| 7 // TODO(ahe): ErrorKind doesn't belong in dart_parser. Move to compiler_util or | |
| 8 // this package? | |
| 9 import 'package:dart_parser/src/error_kind.dart' show | |
| 10 ErrorKind; | |
| 11 | |
| 12 import '../dart_scanner.dart' show | |
| 13 BeginGroupToken, | |
| 14 Token, | |
| 15 unicodeReplacementCharacter; | |
| 16 | |
| 17 import 'precedence.dart' show | |
| 18 BAD_INPUT_INFO, | |
| 19 PrecedenceInfo; | |
| 20 | |
| 21 export 'package:dart_parser/src/error_kind.dart' show | |
| 22 ErrorKind; | |
| 23 | |
| 24 ErrorToken buildUnexpectedCharacterToken(int character, int charOffset) { | |
| 25 if (character < 0x1f) { | |
| 26 return new AsciiControlCharacterToken(character, charOffset); | |
| 27 } | |
| 28 switch (character) { | |
| 29 case unicodeReplacementCharacter: | |
| 30 return new EncodingErrorToken(charOffset); | |
| 31 | |
| 32 /// See [General Punctuation] | |
| 33 /// (http://www.unicode.org/charts/PDF/U2000.pdf). | |
| 34 case 0x00A0: // No-break space. | |
| 35 case 0x1680: // Ogham space mark. | |
| 36 case 0x180E: // Mongolian vowel separator. | |
| 37 case 0x2000: // En quad. | |
| 38 case 0x2001: // Em quad. | |
| 39 case 0x2002: // En space. | |
| 40 case 0x2003: // Em space. | |
| 41 case 0x2004: // Three-per-em space. | |
| 42 case 0x2005: // Four-per-em space. | |
| 43 case 0x2006: // Six-per-em space. | |
| 44 case 0x2007: // Figure space. | |
| 45 case 0x2008: // Punctuation space. | |
| 46 case 0x2009: // Thin space. | |
| 47 case 0x200A: // Hair space. | |
| 48 case 0x200B: // Zero width space. | |
| 49 case 0x2028: // Line separator. | |
| 50 case 0x2029: // Paragraph separator. | |
| 51 case 0x202F: // Narrow no-break space. | |
| 52 case 0x205F: // Medium mathematical space. | |
| 53 case 0x3000: // Ideographic space. | |
| 54 case 0xFEFF: // Zero width no-break space. | |
| 55 return new NonAsciiWhitespaceToken(character, charOffset); | |
| 56 | |
| 57 default: | |
| 58 return new NonAsciiIdentifierToken(character, charOffset); | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 /// Common superclass for all error tokens. | |
| 63 /// | |
| 64 /// It's considered an implementation error to access [value] of an | |
| 65 /// [ErrorToken]. | |
| 66 abstract class ErrorToken extends Token { | |
| 67 ErrorToken(int charOffset) : super(charOffset); | |
| 68 | |
| 69 PrecedenceInfo get info => BAD_INPUT_INFO; | |
| 70 | |
| 71 String get value => throw assertionMessage; | |
| 72 | |
| 73 String get stringValue => null; | |
| 74 | |
| 75 bool isIdentifier() => false; | |
| 76 | |
| 77 String get assertionMessage; | |
| 78 | |
| 79 ErrorKind get errorCode; | |
| 80 | |
| 81 int get character => null; | |
| 82 | |
| 83 String get start => null; | |
| 84 | |
| 85 int get endOffset => null; | |
| 86 | |
| 87 BeginGroupToken get begin => null; | |
| 88 } | |
| 89 | |
| 90 /// Represents an encoding error. | |
| 91 class EncodingErrorToken extends ErrorToken { | |
| 92 EncodingErrorToken(int charOffset) : super(charOffset); | |
| 93 | |
| 94 String toString() => "EncodingErrorToken()"; | |
| 95 | |
| 96 String get assertionMessage => "Unable to decode bytes as UTF-8."; | |
| 97 | |
| 98 ErrorKind get errorCode => ErrorKind.Encoding; | |
| 99 } | |
| 100 | |
| 101 /// Represents a non-ASCII character outside a string or comment. | |
| 102 class NonAsciiIdentifierToken extends ErrorToken { | |
| 103 final int character; | |
| 104 | |
| 105 NonAsciiIdentifierToken(this.character, int charOffset) : super(charOffset); | |
| 106 | |
| 107 String toString() => "NonAsciiIdentifierToken($character)"; | |
| 108 | |
| 109 String get assertionMessage { | |
| 110 String c = new String.fromCharCodes([character]); | |
| 111 String hex = character.toRadixString(16); | |
| 112 String padding = "0000".substring(hex.length); | |
| 113 hex = "$padding$hex"; | |
| 114 return | |
| 115 "The non-ASCII character '$c' (U+$hex) can't be used in identifiers," | |
| 116 " only in strings and comments.\n" | |
| 117 "Try using an US-ASCII letter, a digit, '_' (an underscore)," | |
| 118 " or '\$' (a dollar sign)."; | |
| 119 } | |
| 120 | |
| 121 ErrorKind get errorCode => ErrorKind.NonAsciiIdentifier; | |
| 122 } | |
| 123 | |
| 124 /// Represents a non-ASCII whitespace outside a string or comment. | |
| 125 class NonAsciiWhitespaceToken extends ErrorToken { | |
| 126 final int character; | |
| 127 | |
| 128 NonAsciiWhitespaceToken(this.character, int charOffset) : super(charOffset); | |
| 129 | |
| 130 String toString() => "NonAsciiWhitespaceToken($character)"; | |
| 131 | |
| 132 String get assertionMessage { | |
| 133 String hex = character.toRadixString(16); | |
| 134 return "The non-ASCII space character U+$hex can only be used in strings " | |
| 135 "and comments."; | |
| 136 } | |
| 137 | |
| 138 ErrorKind get errorCode => ErrorKind.NonAsciiWhitespace; | |
| 139 } | |
| 140 | |
| 141 /// Represents an ASCII control character outside a string or comment. | |
| 142 class AsciiControlCharacterToken extends ErrorToken { | |
| 143 final int character; | |
| 144 | |
| 145 AsciiControlCharacterToken(this.character, int charOffset) : super(charOffset) ; | |
|
Johnni Winther
2017/01/30 09:04:38
Long line.
ahe
2017/01/30 13:26:22
Done.
| |
| 146 | |
| 147 String toString() => "AsciiControlCharacterToken($character)"; | |
| 148 | |
| 149 String get assertionMessage { | |
| 150 String hex = character.toRadixString(16); | |
| 151 return "The control character U+$hex can only be used in strings and " | |
| 152 "comments."; | |
| 153 } | |
| 154 | |
| 155 ErrorKind get errorCode => ErrorKind.AsciiControlCharacter; | |
| 156 } | |
| 157 | |
| 158 /// Represents an unterminated string. | |
| 159 class UnterminatedToken extends ErrorToken { | |
| 160 final String start; | |
| 161 final int endOffset; | |
| 162 | |
| 163 UnterminatedToken(this.start, int charOffset, this.endOffset) | |
| 164 : super(charOffset); | |
| 165 | |
| 166 String toString() => "UnterminatedToken($start)"; | |
| 167 | |
| 168 String get assertionMessage => "'$start' isn't terminated."; | |
| 169 | |
| 170 int get charCount => endOffset - charOffset; | |
| 171 | |
| 172 ErrorKind get errorCode { | |
| 173 switch (start) { | |
| 174 case '1e': | |
| 175 return ErrorKind.MissingExponent; | |
| 176 | |
| 177 case '"': | |
| 178 case "'": | |
| 179 case '"""': | |
| 180 case "'''": | |
| 181 case 'r"': | |
| 182 case "r'": | |
| 183 case 'r"""': | |
| 184 case "r'''": | |
| 185 return ErrorKind.UnterminatedString; | |
| 186 | |
| 187 case '0x': | |
| 188 return ErrorKind.ExpectedHexDigit; | |
| 189 | |
| 190 case r'$': | |
| 191 return ErrorKind.UnexpectedDollarInString; | |
| 192 | |
| 193 case '/*': | |
| 194 return ErrorKind.UnterminatedComment; | |
| 195 | |
| 196 default: | |
| 197 return ErrorKind.UnterminatedToken; | |
| 198 } | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 /// Represents an open brace without a matching close brace. | |
| 203 /// | |
| 204 /// In this case, brace means any of `(`, `{`, `[`, and `<`, parenthesis, curly | |
| 205 /// brace, square brace, and angle brace, respectively. | |
| 206 class UnmatchedToken extends ErrorToken { | |
| 207 final BeginGroupToken begin; | |
| 208 | |
| 209 UnmatchedToken(BeginGroupToken begin) | |
| 210 : this.begin = begin, | |
| 211 super(begin.charOffset); | |
| 212 | |
| 213 String toString() => "UnmatchedToken(${begin.value})"; | |
| 214 | |
| 215 String get assertionMessage => "'$begin' isn't closed."; | |
| 216 | |
| 217 ErrorKind get errorCode => ErrorKind.UnmatchedToken; | |
| 218 } | |
| OLD | NEW |