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 part of scanner; | 5 part of scanner; |
6 | 6 |
7 /** | 7 /** |
8 * Scanner that reads from a String and creates tokens that points to | 8 * Scanner that reads from a String and creates tokens that points to |
9 * substrings. | 9 * substrings. |
10 */ | 10 */ |
11 class StringScanner extends ArrayBasedScanner<SourceString> { | 11 class StringScanner extends ArrayBasedScanner { |
12 final String string; | 12 /** The file content. */ |
| 13 String string; |
13 | 14 |
14 StringScanner(String this.string, {bool includeComments: false}) | 15 /** The current offset in [string]. */ |
15 : super(includeComments); | 16 int scanOffset = -1; |
16 | 17 |
17 int nextByte() => charAt(++byteOffset); | 18 StringScanner(SourceFile file, {bool includeComments: false}) |
18 | 19 : string = file.slowText(), |
19 int peek() => charAt(byteOffset + 1); | 20 super(file, includeComments) { |
20 | 21 ensureZeroTermination(); |
21 int charAt(index) | |
22 => (string.length > index) ? string.codeUnitAt(index) : $EOF; | |
23 | |
24 SourceString asciiString(int start, int offset) { | |
25 return new SourceString.fromSubstring(string, start, byteOffset + offset); | |
26 } | 22 } |
27 | 23 |
28 SourceString utf8String(int start, int offset) { | 24 StringScanner.fromString(this.string, {bool includeComments: false}) |
29 return new SourceString.fromSubstring( | 25 : super(null, includeComments) { |
30 string, start, byteOffset + offset + 1); | 26 ensureZeroTermination(); |
31 } | 27 } |
32 | 28 |
33 void appendByteStringToken(PrecedenceInfo info, SourceString value) { | 29 void ensureZeroTermination() { |
34 // assert(kind != $a || keywords.get(value) == null); | 30 if (string.isEmpty || string.codeUnitAt(string.length - 1) != 0) { |
35 tail.next = new StringToken.fromSource(info, value, tokenStart); | 31 // TODO(lry), abort instead of copying the array, or warn? |
| 32 string = string + '\x00'; |
| 33 } |
| 34 } |
| 35 |
| 36 int advance() => string.codeUnitAt(++scanOffset); |
| 37 int peek() => string.codeUnitAt(scanOffset + 1); |
| 38 |
| 39 int get stringOffset => scanOffset; |
| 40 |
| 41 int currentAsUnicode(int next) => next; |
| 42 |
| 43 void handleUnicode(int startScanOffset) { } |
| 44 |
| 45 |
| 46 Token firstToken() => tokens.next; |
| 47 Token previousToken() => tail; |
| 48 |
| 49 void appendSubstringToken(PrecedenceInfo info, int start, |
| 50 bool asciiOnly, [int extraOffset = 0]) { |
| 51 tail.next = new StringToken.fromSubstring(info, string, start, |
| 52 scanOffset + extraOffset, tokenStart, true); |
36 tail = tail.next; | 53 tail = tail.next; |
37 } | 54 } |
38 | |
39 void unmatchedBeginGroup(BeginGroupToken begin) { | |
40 SourceString error = new SourceString('unmatched "${begin.stringValue}"'); | |
41 Token close = | |
42 new StringToken.fromSource(BAD_INPUT_INFO, error, begin.charOffset); | |
43 // We want to ensure that unmatched BeginGroupTokens are reported | |
44 // as errors. However, the rest of the parser assume the groups | |
45 // are well-balanced and will never look at the endGroup | |
46 // token. This is a nice property that allows us to skip quickly | |
47 // over correct code. By inserting an additional error token in | |
48 // the stream, we can keep ignoring endGroup tokens. | |
49 Token next = | |
50 new StringToken.fromSource(BAD_INPUT_INFO, error, begin.charOffset); | |
51 begin.endGroup = close; | |
52 close.next = next; | |
53 next.next = begin.next; | |
54 } | |
55 } | 55 } |
OLD | NEW |