| 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 class ArrayBasedScanner<S> extends AbstractScanner<S> { | 5 class ArrayBasedScanner<S> extends AbstractScanner<S> { |
| 6 int get charOffset() => byteOffset + extraCharOffset; | 6 int get charOffset() => byteOffset + extraCharOffset; |
| 7 final Token tokens; | 7 final Token tokens; |
| 8 Token tail; | 8 Token tail; |
| 9 int tokenStart; | 9 int tokenStart; |
| 10 int byteOffset; | 10 int byteOffset; |
| 11 | 11 |
| 12 /** Since the input is UTF8, some characters are represented by more | 12 /** Since the input is UTF8, some characters are represented by more |
| 13 * than one byte. [extraCharOffset] tracks the difference. */ | 13 * than one byte. [extraCharOffset] tracks the difference. */ |
| 14 int extraCharOffset; | 14 int extraCharOffset; |
| 15 Link<Token> groupingStack = const EmptyLink<Token>(); | 15 Link<BeginGroupToken> groupingStack = const EmptyLink<BeginGroupToken>(); |
| 16 | 16 |
| 17 ArrayBasedScanner() | 17 ArrayBasedScanner() |
| 18 : this.extraCharOffset = 0, | 18 : this.extraCharOffset = 0, |
| 19 this.tokenStart = -1, | 19 this.tokenStart = -1, |
| 20 this.byteOffset = -1, | 20 this.byteOffset = -1, |
| 21 this.tokens = new Token(EOF_INFO, -1) { | 21 this.tokens = new Token(EOF_INFO, -1) { |
| 22 this.tail = this.tokens; | 22 this.tail = this.tokens; |
| 23 } | 23 } |
| 24 | 24 |
| 25 int advance() { | 25 int advance() { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 51 void appendKeywordToken(Keyword keyword) { | 51 void appendKeywordToken(Keyword keyword) { |
| 52 tail.next = new KeywordToken(keyword, tokenStart); | 52 tail.next = new KeywordToken(keyword, tokenStart); |
| 53 tail = tail.next; | 53 tail = tail.next; |
| 54 } | 54 } |
| 55 | 55 |
| 56 void appendEofToken() { | 56 void appendEofToken() { |
| 57 tail.next = new Token(EOF_INFO, charOffset); | 57 tail.next = new Token(EOF_INFO, charOffset); |
| 58 tail = tail.next; | 58 tail = tail.next; |
| 59 // EOF points to itself so there's always infinite look-ahead. | 59 // EOF points to itself so there's always infinite look-ahead. |
| 60 tail.next = tail; | 60 tail.next = tail; |
| 61 if (!groupingStack.isEmpty()) { |
| 62 BeginGroupToken begin = groupingStack.head; |
| 63 throw new MalformedInputException('Unbalanced ${begin.stringValue}', |
| 64 begin); |
| 65 } |
| 61 } | 66 } |
| 62 | 67 |
| 63 void beginToken() { | 68 void beginToken() { |
| 64 tokenStart = charOffset; | 69 tokenStart = charOffset; |
| 65 } | 70 } |
| 66 | 71 |
| 67 Token firstToken() { | 72 Token firstToken() { |
| 68 return tokens.next; | 73 return tokens.next; |
| 69 } | 74 } |
| 70 | 75 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 93 appendStringToken(info, value); | 98 appendStringToken(info, value); |
| 94 if (groupingStack.isEmpty()) { | 99 if (groupingStack.isEmpty()) { |
| 95 return advance(); | 100 return advance(); |
| 96 } | 101 } |
| 97 discardOpenLt(); | 102 discardOpenLt(); |
| 98 BeginGroupToken begin = groupingStack.head; | 103 BeginGroupToken begin = groupingStack.head; |
| 99 if (begin.kind !== openKind) { | 104 if (begin.kind !== openKind) { |
| 100 if (openKind !== OPEN_CURLY_BRACKET_TOKEN || | 105 if (openKind !== OPEN_CURLY_BRACKET_TOKEN || |
| 101 begin.kind !== STRING_INTERPOLATION_TOKEN) { | 106 begin.kind !== STRING_INTERPOLATION_TOKEN) { |
| 102 // Not ending string interpolation. | 107 // Not ending string interpolation. |
| 103 throw new MalformedInputException('Unmatched ${begin.stringValue}'); | 108 throw new MalformedInputException('Unmatched ${begin.stringValue}', |
| 109 begin); |
| 104 } | 110 } |
| 105 // We're ending an interpolated expression. | 111 // We're ending an interpolated expression. |
| 106 begin.endGroup = tail; | 112 begin.endGroup = tail; |
| 107 groupingStack = groupingStack.tail; | 113 groupingStack = groupingStack.tail; |
| 108 // Using "start-of-text" to signal that we're back in string | 114 // Using "start-of-text" to signal that we're back in string |
| 109 // scanning mode. | 115 // scanning mode. |
| 110 return $STX; | 116 return $STX; |
| 111 } | 117 } |
| 112 begin.endGroup = tail; | 118 begin.endGroup = tail; |
| 113 groupingStack = groupingStack.tail; | 119 groupingStack = groupingStack.tail; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 | 161 |
| 156 void discardOpenLt() { | 162 void discardOpenLt() { |
| 157 while (!groupingStack.isEmpty() && groupingStack.head.kind === LT_TOKEN) { | 163 while (!groupingStack.isEmpty() && groupingStack.head.kind === LT_TOKEN) { |
| 158 groupingStack = groupingStack.tail; | 164 groupingStack = groupingStack.tail; |
| 159 } | 165 } |
| 160 } | 166 } |
| 161 | 167 |
| 162 // TODO(ahe): make class abstract instead of adding an abstract method. | 168 // TODO(ahe): make class abstract instead of adding an abstract method. |
| 163 abstract peek(); | 169 abstract peek(); |
| 164 } | 170 } |
| OLD | NEW |