Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 library fasta.scanner.array_based_scanner; | 5 library fasta.scanner.array_based_scanner; |
| 6 | 6 |
| 7 import 'error_token.dart' show ErrorToken; | 7 import 'error_token.dart' show ErrorToken; |
| 8 | 8 |
| 9 import 'keyword.dart' show Keyword; | 9 import 'keyword.dart' show Keyword; |
| 10 | 10 |
| 11 import 'precedence.dart' show COMMENT_INFO, EOF_INFO, PrecedenceInfo; | 11 import 'precedence.dart' show COMMENT_INFO, EOF_INFO, PrecedenceInfo; |
| 12 | 12 |
| 13 import 'token.dart' show BeginGroupToken, KeywordToken, SymbolToken, Token; | 13 import 'token.dart' |
| 14 show BeginGroupToken, KeywordToken, StringToken, SymbolToken, Token; | |
| 14 | 15 |
| 15 import 'token_constants.dart' | 16 import 'token_constants.dart' |
| 16 show LT_TOKEN, OPEN_CURLY_BRACKET_TOKEN, STRING_INTERPOLATION_TOKEN; | 17 show LT_TOKEN, OPEN_CURLY_BRACKET_TOKEN, STRING_INTERPOLATION_TOKEN; |
| 17 | 18 |
| 18 import 'characters.dart' show $LF, $STX; | 19 import 'characters.dart' show $LF, $STX; |
| 19 | 20 |
| 20 import 'abstract_scanner.dart' show AbstractScanner; | 21 import 'abstract_scanner.dart' show AbstractScanner; |
| 21 | 22 |
| 22 import '../util/link.dart' show Link; | 23 import '../util/link.dart' show Link; |
| 23 | 24 |
| 24 abstract class ArrayBasedScanner extends AbstractScanner { | 25 abstract class ArrayBasedScanner extends AbstractScanner { |
| 25 bool hasErrors = false; | 26 bool hasErrors = false; |
| 26 | 27 |
| 27 ArrayBasedScanner(bool includeComments, {int numberOfBytesHint}) | 28 ArrayBasedScanner(bool includeComments, {int numberOfBytesHint}) |
| 28 : super(includeComments, numberOfBytesHint: numberOfBytesHint); | 29 : super(includeComments, numberOfBytesHint: numberOfBytesHint); |
| 29 | 30 |
| 30 /** | 31 /** |
| 31 * The stack of open groups, e.g [: { ... ( .. :] | 32 * The stack of open groups, e.g [: { ... ( .. :] |
| 32 * Each BeginGroupToken has a pointer to the token where the group | 33 * Each BeginGroupToken has a pointer to the token where the group |
| 33 * ends. This field is set when scanning the end group token. | 34 * ends. This field is set when scanning the end group token. |
| 34 */ | 35 */ |
| 35 Link<BeginGroupToken> groupingStack = const Link<BeginGroupToken>(); | 36 Link<BeginGroupToken> groupingStack = const Link<BeginGroupToken>(); |
| 36 | 37 |
| 37 /** | 38 /** |
| 39 * Append the given token to the [tail] of the current stream of tokens. | |
| 40 */ | |
| 41 void appendToken(Token token) { | |
| 42 tail.next = token; | |
| 43 tail = tail.next; | |
| 44 if (comments != null) { | |
| 45 tail.precedingComments = comments; | |
| 46 comments = null; | |
| 47 commentsTail = null; | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 /** | |
| 38 * Appends a fixed token whose kind and content is determined by [info]. | 52 * Appends a fixed token whose kind and content is determined by [info]. |
| 39 * Appends an *operator* token from [info]. | 53 * Appends an *operator* token from [info]. |
| 40 * | 54 * |
| 41 * An operator token represent operators like ':', '.', ';', '&&', '==', '--', | 55 * An operator token represent operators like ':', '.', ';', '&&', '==', '--', |
| 42 * '=>', etc. | 56 * '=>', etc. |
| 43 */ | 57 */ |
| 44 void appendPrecedenceToken(PrecedenceInfo info) { | 58 void appendPrecedenceToken(PrecedenceInfo info) { |
| 45 tail.next = new SymbolToken(info, tokenStart); | 59 appendToken(new SymbolToken(info, tokenStart)); |
| 46 tail = tail.next; | |
| 47 } | 60 } |
| 48 | 61 |
| 49 /** | 62 /** |
| 50 * Appends a fixed token based on whether the current char is [choice] or not. | 63 * Appends a fixed token based on whether the current char is [choice] or not. |
| 51 * If the current char is [choice] a fixed token whose kind and content | 64 * If the current char is [choice] a fixed token whose kind and content |
| 52 * is determined by [yes] is appended, otherwise a fixed token whose kind | 65 * is determined by [yes] is appended, otherwise a fixed token whose kind |
| 53 * and content is determined by [no] is appended. | 66 * and content is determined by [no] is appended. |
| 54 */ | 67 */ |
| 55 int select(int choice, PrecedenceInfo yes, PrecedenceInfo no) { | 68 int select(int choice, PrecedenceInfo yes, PrecedenceInfo no) { |
| 56 int next = advance(); | 69 int next = advance(); |
| 57 if (identical(next, choice)) { | 70 if (identical(next, choice)) { |
| 58 appendPrecedenceToken(yes); | 71 appendPrecedenceToken(yes); |
| 59 return advance(); | 72 return advance(); |
| 60 } else { | 73 } else { |
| 61 appendPrecedenceToken(no); | 74 appendPrecedenceToken(no); |
| 62 return next; | 75 return next; |
| 63 } | 76 } |
| 64 } | 77 } |
| 65 | 78 |
| 66 /** | 79 /** |
| 67 * Appends a keyword token whose kind is determined by [keyword]. | 80 * Appends a keyword token whose kind is determined by [keyword]. |
| 68 */ | 81 */ |
| 69 void appendKeywordToken(Keyword keyword) { | 82 void appendKeywordToken(Keyword keyword) { |
| 70 String syntax = keyword.syntax; | 83 String syntax = keyword.syntax; |
| 71 // Type parameters and arguments cannot contain 'this'. | 84 // Type parameters and arguments cannot contain 'this'. |
| 72 if (identical(syntax, 'this')) { | 85 if (identical(syntax, 'this')) { |
| 73 discardOpenLt(); | 86 discardOpenLt(); |
| 74 } | 87 } |
| 75 tail.next = new KeywordToken(keyword, tokenStart); | 88 appendToken(new KeywordToken(keyword, tokenStart)); |
| 76 tail = tail.next; | |
| 77 } | 89 } |
| 78 | 90 |
| 79 void appendEofToken() { | 91 void appendEofToken() { |
| 80 beginToken(); | 92 beginToken(); |
| 81 discardOpenLt(); | 93 discardOpenLt(); |
| 82 while (!groupingStack.isEmpty) { | 94 while (!groupingStack.isEmpty) { |
| 83 unmatchedBeginGroup(groupingStack.head); | 95 unmatchedBeginGroup(groupingStack.head); |
| 84 groupingStack = groupingStack.tail; | 96 groupingStack = groupingStack.tail; |
| 85 } | 97 } |
| 86 tail.next = new SymbolToken(EOF_INFO, tokenStart); | 98 appendToken(new SymbolToken(EOF_INFO, tokenStart)); |
| 87 tail = tail.next; | |
| 88 // EOF points to itself so there's always infinite look-ahead. | 99 // EOF points to itself so there's always infinite look-ahead. |
| 89 tail.next = tail; | 100 tail.next = tail; |
| 90 } | 101 } |
| 91 | 102 |
| 92 /** | 103 /** |
| 93 * Notifies scanning a whitespace character. Note that [appendWhiteSpace] is | 104 * Notifies scanning a whitespace character. Note that [appendWhiteSpace] is |
| 94 * not always invoked for [$SPACE] characters. | 105 * not always invoked for [$SPACE] characters. |
| 95 * | 106 * |
| 96 * This method is used by the scanners to track line breaks and create the | 107 * This method is used by the scanners to track line breaks and create the |
| 97 * [lineStarts] map. | 108 * [lineStarts] map. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 111 void lineFeedInMultiline() { | 122 void lineFeedInMultiline() { |
| 112 lineStarts.add(stringOffset + 1); | 123 lineStarts.add(stringOffset + 1); |
| 113 } | 124 } |
| 114 | 125 |
| 115 /** | 126 /** |
| 116 * Appends a token that begins a new group, represented by [value]. | 127 * Appends a token that begins a new group, represented by [value]. |
| 117 * Group begin tokens are '{', '(', '[' and '${'. | 128 * Group begin tokens are '{', '(', '[' and '${'. |
| 118 */ | 129 */ |
| 119 void appendBeginGroup(PrecedenceInfo info) { | 130 void appendBeginGroup(PrecedenceInfo info) { |
| 120 Token token = new BeginGroupToken(info, tokenStart); | 131 Token token = new BeginGroupToken(info, tokenStart); |
| 121 tail.next = token; | 132 appendToken(token); |
| 122 tail = tail.next; | |
| 123 | 133 |
| 124 // { ( [ ${ cannot appear inside a type parameters / arguments. | 134 // { ( [ ${ cannot appear inside a type parameters / arguments. |
| 125 if (!identical(info.kind, LT_TOKEN)) discardOpenLt(); | 135 if (!identical(info.kind, LT_TOKEN)) discardOpenLt(); |
| 126 groupingStack = groupingStack.prepend(token); | 136 groupingStack = groupingStack.prepend(token); |
| 127 } | 137 } |
| 128 | 138 |
| 129 /** | 139 /** |
| 130 * Appends a token that begins an end group, represented by [value]. | 140 * Appends a token that begins an end group, represented by [value]. |
| 131 * It handles the group end tokens '}', ')' and ']'. The tokens '>' and | 141 * It handles the group end tokens '}', ')' and ']'. The tokens '>' and |
| 132 * '>>' are handled separately bo [appendGt] and [appendGtGt]. | 142 * '>>' are handled separately bo [appendGt] and [appendGtGt]. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 } | 212 } |
| 203 if (groupingStack.isEmpty) return; | 213 if (groupingStack.isEmpty) return; |
| 204 if (identical(groupingStack.head.kind, LT_TOKEN)) { | 214 if (identical(groupingStack.head.kind, LT_TOKEN)) { |
| 205 groupingStack.head.endGroup = tail; | 215 groupingStack.head.endGroup = tail; |
| 206 groupingStack = groupingStack.tail; | 216 groupingStack = groupingStack.tail; |
| 207 } | 217 } |
| 208 } | 218 } |
| 209 | 219 |
| 210 void appendComment(start, bool asciiOnly) { | 220 void appendComment(start, bool asciiOnly) { |
| 211 if (!includeComments) return; | 221 if (!includeComments) return; |
| 212 appendSubstringToken(COMMENT_INFO, start, asciiOnly); | 222 Token newComment = createSubstringToken(COMMENT_INFO, start, asciiOnly); |
| 223 if (comments == null) { | |
| 224 comments = newComment; | |
| 225 commentsTail = comments; | |
| 226 } else { | |
| 227 commentsTail.next = newComment; | |
| 228 commentsTail = commentsTail.next; | |
| 229 } | |
| 213 } | 230 } |
| 214 | 231 |
| 215 void appendErrorToken(ErrorToken token) { | 232 void appendErrorToken(ErrorToken token) { |
| 216 hasErrors = true; | 233 hasErrors = true; |
| 217 tail.next = token; | 234 appendToken(token); |
| 218 tail = token; | |
| 219 } | 235 } |
| 220 | 236 |
| 237 void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly, | |
| 238 [int extraOffset = 0]) { | |
| 239 appendToken(createSubstringToken(info, start, asciiOnly, extraOffset)); | |
| 240 } | |
| 241 | |
| 242 /** | |
| 243 * Returns a new substring from the scan offset [:start:] to the current | |
|
Paul Berry
2017/03/06 14:06:50
Nit: I've always seen this written as `[start]` ra
danrubel
2017/03/06 19:50:28
This is cribbed from appendSubstringToken. I think
| |
| 244 * [:scanOffset:] plus the [:extraOffset:]. For example, if the current | |
| 245 * scanOffset is 10, then [:appendSubstringToken(5, -1):] will append the | |
| 246 * substring string [5,9). | |
| 247 * | |
| 248 * Note that [extraOffset] can only be used if the covered character(s) are | |
| 249 * known to be ASCII. | |
| 250 */ | |
| 251 StringToken createSubstringToken( | |
| 252 PrecedenceInfo info, int start, bool asciiOnly, | |
| 253 [int extraOffset = 0]); | |
| 254 | |
| 221 /** | 255 /** |
| 222 * This method is called to discard '<' from the "grouping" stack. | 256 * This method is called to discard '<' from the "grouping" stack. |
| 223 * | 257 * |
| 224 * [PartialParser.skipExpression] relies on the fact that we do not | 258 * [PartialParser.skipExpression] relies on the fact that we do not |
| 225 * create groups for stuff like: | 259 * create groups for stuff like: |
| 226 * [:a = b < c, d = e > f:]. | 260 * [:a = b < c, d = e > f:]. |
| 227 * | 261 * |
| 228 * In other words, this method is called when the scanner recognizes | 262 * In other words, this method is called when the scanner recognizes |
| 229 * something which cannot possibly be part of a type parameter/argument | 263 * something which cannot possibly be part of a type parameter/argument |
| 230 * list, like the '=' in the above example. | 264 * list, like the '=' in the above example. |
| 231 */ | 265 */ |
| 232 void discardOpenLt() { | 266 void discardOpenLt() { |
| 233 while (!groupingStack.isEmpty && | 267 while (!groupingStack.isEmpty && |
| 234 identical(groupingStack.head.kind, LT_TOKEN)) { | 268 identical(groupingStack.head.kind, LT_TOKEN)) { |
| 235 groupingStack = groupingStack.tail; | 269 groupingStack = groupingStack.tail; |
| 236 } | 270 } |
| 237 } | 271 } |
| 238 } | 272 } |
| OLD | NEW |