OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 #include "platform/assert.h" | 5 #include "platform/assert.h" |
6 #include "vm/os.h" | 6 #include "vm/os.h" |
7 #include "vm/scanner.h" | 7 #include "vm/scanner.h" |
8 #include "vm/token.h" | 8 #include "vm/token.h" |
9 #include "vm/unit_test.h" | 9 #include "vm/unit_test.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
| 13 |
| 14 typedef ZoneGrowableArray<Scanner::TokenDescriptor> GrowableTokenStream; |
| 15 |
| 16 |
13 static void LogTokenDesc(Scanner::TokenDescriptor token) { | 17 static void LogTokenDesc(Scanner::TokenDescriptor token) { |
14 OS::Print("pos %2d:%d-%d token %s ", | 18 OS::Print("pos %2d:%d-%d token %s ", |
15 token.position.line, token.position.column, | 19 token.position.line, token.position.column, |
16 token.position.column, | 20 token.position.column, |
17 Token::Name(token.kind)); | 21 Token::Name(token.kind)); |
18 if (token.literal != NULL) { | 22 if (token.literal != NULL) { |
19 OS::Print("%s", token.literal->ToCString()); | 23 OS::Print("%s", token.literal->ToCString()); |
20 } | 24 } |
21 OS::Print("\n"); | 25 OS::Print("\n"); |
22 } | 26 } |
23 | 27 |
24 | 28 |
25 static void LogTokenStream(const Scanner::GrowableTokenStream& token_stream) { | 29 static void LogTokenStream(const GrowableTokenStream& token_stream) { |
26 int token_index = 0; | 30 int token_index = 0; |
27 EXPECT_GT(token_stream.length(), 0); | 31 EXPECT_GT(token_stream.length(), 0); |
28 while (token_index < token_stream.length()) { | 32 while (token_index < token_stream.length()) { |
29 LogTokenDesc(token_stream[token_index]); | 33 LogTokenDesc(token_stream[token_index]); |
30 ASSERT(token_stream[token_index].kind != Token::kILLEGAL); | 34 ASSERT(token_stream[token_index].kind != Token::kILLEGAL); |
31 token_index++; | 35 token_index++; |
32 } | 36 } |
33 printf("%d tokens in stream.\n", token_index); | 37 printf("%d tokens in stream.\n", token_index); |
34 EXPECT_EQ(token_stream.Last().kind, Token::kEOS); | 38 EXPECT_EQ(token_stream.Last().kind, Token::kEOS); |
35 } | 39 } |
36 | 40 |
37 | 41 |
38 static void CheckKind(const Scanner::GrowableTokenStream &token_stream, | 42 static void CheckKind(const GrowableTokenStream &token_stream, |
39 int index, | 43 int index, |
40 Token::Kind kind) { | 44 Token::Kind kind) { |
41 if (token_stream[index].kind != kind) { | 45 if (token_stream[index].kind != kind) { |
42 OS::PrintErr("Token %d: expected kind %s but got %s\n", index, | 46 OS::PrintErr("Token %d: expected kind %s but got %s\n", index, |
43 Token::Name(kind), Token::Name(token_stream[index].kind)); | 47 Token::Name(kind), Token::Name(token_stream[index].kind)); |
44 } | 48 } |
45 EXPECT_EQ(kind, token_stream[index].kind); | 49 EXPECT_EQ(kind, token_stream[index].kind); |
46 } | 50 } |
47 | 51 |
48 | 52 |
49 static void CheckLiteral(const Scanner::GrowableTokenStream& token_stream, | 53 static void CheckLiteral(const GrowableTokenStream& token_stream, |
50 int index, | 54 int index, |
51 const char* literal) { | 55 const char* literal) { |
52 if (token_stream[index].literal == NULL) { | 56 if (token_stream[index].literal == NULL) { |
53 OS::PrintErr("Token %d: expected literal \"%s\" but got nothing\n", | 57 OS::PrintErr("Token %d: expected literal \"%s\" but got nothing\n", |
54 index, literal); | 58 index, literal); |
55 } else if (strcmp(literal, token_stream[index].literal->ToCString())) { | 59 } else if (strcmp(literal, token_stream[index].literal->ToCString())) { |
56 OS::PrintErr("Token %d: expected literal \"%s\" but got \"%s\"\n", | 60 OS::PrintErr("Token %d: expected literal \"%s\" but got \"%s\"\n", |
57 index, literal, token_stream[index].literal->ToCString()); | 61 index, literal, token_stream[index].literal->ToCString()); |
58 } | 62 } |
59 } | 63 } |
60 | 64 |
61 | 65 |
62 static void CheckIdent(const Scanner::GrowableTokenStream& token_stream, | 66 static void CheckIdent(const GrowableTokenStream& token_stream, |
63 int index, | 67 int index, |
64 const char* literal) { | 68 const char* literal) { |
65 CheckKind(token_stream, index, Token::kIDENT); | 69 CheckKind(token_stream, index, Token::kIDENT); |
66 CheckLiteral(token_stream, index, literal); | 70 CheckLiteral(token_stream, index, literal); |
67 } | 71 } |
68 | 72 |
69 | 73 |
70 static void CheckInteger(const Scanner::GrowableTokenStream& token_stream, | 74 static void CheckInteger(const GrowableTokenStream& token_stream, |
71 int index, | 75 int index, |
72 const char* literal) { | 76 const char* literal) { |
73 CheckKind(token_stream, index, Token::kINTEGER); | 77 CheckKind(token_stream, index, Token::kINTEGER); |
74 CheckLiteral(token_stream, index, literal); | 78 CheckLiteral(token_stream, index, literal); |
75 } | 79 } |
76 | 80 |
77 | 81 |
78 static void CheckLineNumber(const Scanner::GrowableTokenStream& token_stream, | 82 static void CheckLineNumber(const GrowableTokenStream& token_stream, |
79 int index, | 83 int index, |
80 int line_number) { | 84 int line_number) { |
81 if (token_stream[index].position.line != line_number) { | 85 if (token_stream[index].position.line != line_number) { |
82 OS::PrintErr("Token %d: expected line number %d but got %d\n", | 86 OS::PrintErr("Token %d: expected line number %d but got %d\n", |
83 index, line_number, token_stream[index].position.line); | 87 index, line_number, token_stream[index].position.line); |
84 } | 88 } |
85 } | 89 } |
86 | 90 |
87 | 91 |
88 static void CheckNumTokens(const Scanner::GrowableTokenStream& token_stream, | 92 static void CheckNumTokens(const GrowableTokenStream& token_stream, |
89 int index) { | 93 int index) { |
90 if (token_stream.length() != index) { | 94 if (token_stream.length() != index) { |
91 OS::PrintErr("Expected %d tokens but got only %" Pd ".\n", | 95 OS::PrintErr("Expected %d tokens but got only %" Pd ".\n", |
92 index, token_stream.length()); | 96 index, token_stream.length()); |
93 } | 97 } |
94 } | 98 } |
95 | 99 |
96 | 100 |
97 static const Scanner::GrowableTokenStream& Scan(const char* source) { | 101 class Collector : public Scanner::TokenCollector { |
| 102 public: |
| 103 explicit Collector(GrowableTokenStream* ts) : ts_(ts) { } |
| 104 virtual ~Collector() { } |
| 105 |
| 106 virtual void AddToken(const Scanner::TokenDescriptor& token) { |
| 107 ts_->Add(token); |
| 108 } |
| 109 private: |
| 110 GrowableTokenStream* ts_; |
| 111 }; |
| 112 |
| 113 |
| 114 static const GrowableTokenStream& Scan(const char* source) { |
| 115 OS::Print("\nScanning: <%s>\n", source); |
| 116 |
98 Scanner scanner(String::Handle(String::New(source)), | 117 Scanner scanner(String::Handle(String::New(source)), |
99 String::Handle(String::New(""))); | 118 String::Handle(String::New(""))); |
| 119 GrowableTokenStream* tokens = new GrowableTokenStream(128); |
| 120 Collector collector(tokens); |
100 | 121 |
101 OS::Print("\nScanning: <%s>\n", source); | 122 scanner.ScanAll(&collector); |
102 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); | 123 LogTokenStream(*tokens); |
103 LogTokenStream(tokens); | 124 return *tokens; |
104 return tokens; | |
105 } | 125 } |
106 | 126 |
107 | 127 |
108 static void BoringTest() { | 128 static void BoringTest() { |
109 const Scanner::GrowableTokenStream& tokens = Scan("x = iffy++;"); | 129 const GrowableTokenStream& tokens = Scan("x = iffy++;"); |
110 | 130 |
111 CheckNumTokens(tokens, 6); | 131 CheckNumTokens(tokens, 6); |
112 CheckIdent(tokens, 0, "x"); | 132 CheckIdent(tokens, 0, "x"); |
113 CheckKind(tokens, 1, Token::kASSIGN); | 133 CheckKind(tokens, 1, Token::kASSIGN); |
114 CheckIdent(tokens, 2, "iffy"); | 134 CheckIdent(tokens, 2, "iffy"); |
115 CheckKind(tokens, 3, Token::kINCR); | 135 CheckKind(tokens, 3, Token::kINCR); |
116 CheckKind(tokens, 4, Token::kSEMICOLON); | 136 CheckKind(tokens, 4, Token::kSEMICOLON); |
117 } | 137 } |
118 | 138 |
119 | 139 |
120 static void CommentTest() { | 140 static void CommentTest() { |
121 const Scanner::GrowableTokenStream& tokens = | 141 const GrowableTokenStream& tokens = |
122 Scan("Foo( /*block \n" | 142 Scan("Foo( /*block \n" |
123 "comment*/ 0xff) // line comment;"); | 143 "comment*/ 0xff) // line comment;"); |
124 | 144 |
125 CheckNumTokens(tokens, 6); | 145 CheckNumTokens(tokens, 6); |
126 CheckIdent(tokens, 0, "Foo"); | 146 CheckIdent(tokens, 0, "Foo"); |
127 CheckLineNumber(tokens, 0, 1); | 147 CheckLineNumber(tokens, 0, 1); |
128 CheckKind(tokens, 1, Token::kLPAREN); | 148 CheckKind(tokens, 1, Token::kLPAREN); |
129 CheckKind(tokens, 2, Token::kNEWLINE); | 149 CheckKind(tokens, 2, Token::kNEWLINE); |
130 CheckInteger(tokens, 3, "0xff"); | 150 CheckInteger(tokens, 3, "0xff"); |
131 CheckKind(tokens, 4, Token::kRPAREN); | 151 CheckKind(tokens, 4, Token::kRPAREN); |
132 CheckLineNumber(tokens, 4, 2); | 152 CheckLineNumber(tokens, 4, 2); |
133 } | 153 } |
134 | 154 |
135 | 155 |
136 static void GreedIsGood() { | 156 static void GreedIsGood() { |
137 // means i++ + j | 157 // means i++ + j |
138 const Scanner::GrowableTokenStream& tokens = Scan("x=i+++j"); | 158 const GrowableTokenStream& tokens = Scan("x=i+++j"); |
139 | 159 |
140 CheckNumTokens(tokens, 7); | 160 CheckNumTokens(tokens, 7); |
141 CheckIdent(tokens, 0, "x"); | 161 CheckIdent(tokens, 0, "x"); |
142 CheckKind(tokens, 1, Token::kASSIGN); | 162 CheckKind(tokens, 1, Token::kASSIGN); |
143 CheckIdent(tokens, 2, "i"); | 163 CheckIdent(tokens, 2, "i"); |
144 CheckKind(tokens, 3, Token::kINCR); | 164 CheckKind(tokens, 3, Token::kINCR); |
145 CheckKind(tokens, 4, Token::kADD); | 165 CheckKind(tokens, 4, Token::kADD); |
146 CheckIdent(tokens, 5, "j"); | 166 CheckIdent(tokens, 5, "j"); |
147 } | 167 } |
148 | 168 |
149 | 169 |
150 static void StringEscapes() { | 170 static void StringEscapes() { |
151 // sss = "\" \\ \n\r\t \'" | 171 // sss = "\" \\ \n\r\t \'" |
152 const Scanner::GrowableTokenStream& tokens = | 172 const GrowableTokenStream& tokens = |
153 Scan("sss = \"\\\" \\\\ \\n\\r\\t \\\'\""); | 173 Scan("sss = \"\\\" \\\\ \\n\\r\\t \\\'\""); |
154 | 174 |
155 EXPECT_EQ(4, tokens.length()); | 175 EXPECT_EQ(4, tokens.length()); |
156 CheckIdent(tokens, 0, "sss"); | 176 CheckIdent(tokens, 0, "sss"); |
157 CheckKind(tokens, 1, Token::kASSIGN); | 177 CheckKind(tokens, 1, Token::kASSIGN); |
158 CheckKind(tokens, 2, Token::kSTRING); | 178 CheckKind(tokens, 2, Token::kSTRING); |
159 CheckKind(tokens, 3, Token::kEOS); | 179 CheckKind(tokens, 3, Token::kEOS); |
160 CheckLineNumber(tokens, 2, 1); | 180 CheckLineNumber(tokens, 2, 1); |
161 const char* litchars = (tokens)[2].literal->ToCString(); | 181 const char* litchars = (tokens)[2].literal->ToCString(); |
162 EXPECT_EQ(9, (tokens)[2].literal->Length()); | 182 EXPECT_EQ(9, (tokens)[2].literal->Length()); |
163 | 183 |
164 EXPECT_EQ('"', litchars[0]); | 184 EXPECT_EQ('"', litchars[0]); |
165 EXPECT_EQ(' ', litchars[1]); | 185 EXPECT_EQ(' ', litchars[1]); |
166 EXPECT_EQ('\\', litchars[2]); | 186 EXPECT_EQ('\\', litchars[2]); |
167 EXPECT_EQ('\n', litchars[4]); | 187 EXPECT_EQ('\n', litchars[4]); |
168 EXPECT_EQ('\r', litchars[5]); | 188 EXPECT_EQ('\r', litchars[5]); |
169 EXPECT_EQ('\t', litchars[6]); | 189 EXPECT_EQ('\t', litchars[6]); |
170 EXPECT_EQ('\'', litchars[8]); | 190 EXPECT_EQ('\'', litchars[8]); |
171 } | 191 } |
172 | 192 |
173 | 193 |
174 static void InvalidStringEscapes() { | 194 static void InvalidStringEscapes() { |
175 const Scanner::GrowableTokenStream& high_start_4 = | 195 const GrowableTokenStream& high_start_4 = |
176 Scan("\"\\uD800\""); | 196 Scan("\"\\uD800\""); |
177 EXPECT_EQ(2, high_start_4.length()); | 197 EXPECT_EQ(2, high_start_4.length()); |
178 CheckKind(high_start_4, 0, Token::kERROR); | 198 CheckKind(high_start_4, 0, Token::kERROR); |
179 EXPECT(high_start_4[0].literal->Equals("invalid code point")); | 199 EXPECT(high_start_4[0].literal->Equals("invalid code point")); |
180 CheckKind(high_start_4, 1, Token::kEOS); | 200 CheckKind(high_start_4, 1, Token::kEOS); |
181 | 201 |
182 const Scanner::GrowableTokenStream& high_start_seq = | 202 const GrowableTokenStream& high_start_seq = |
183 Scan("\"\\u{D800}\""); | 203 Scan("\"\\u{D800}\""); |
184 EXPECT_EQ(2, high_start_seq.length()); | 204 EXPECT_EQ(2, high_start_seq.length()); |
185 CheckKind(high_start_seq, 0, Token::kERROR); | 205 CheckKind(high_start_seq, 0, Token::kERROR); |
186 EXPECT(high_start_seq[0].literal->Equals("invalid code point")); | 206 EXPECT(high_start_seq[0].literal->Equals("invalid code point")); |
187 CheckKind(high_start_seq, 1, Token::kEOS); | 207 CheckKind(high_start_seq, 1, Token::kEOS); |
188 | 208 |
189 const Scanner::GrowableTokenStream& high_end_4 = | 209 const GrowableTokenStream& high_end_4 = |
190 Scan("\"\\uDBFF\""); | 210 Scan("\"\\uDBFF\""); |
191 EXPECT_EQ(2, high_end_4.length()); | 211 EXPECT_EQ(2, high_end_4.length()); |
192 CheckKind(high_end_4, 0, Token::kERROR); | 212 CheckKind(high_end_4, 0, Token::kERROR); |
193 EXPECT(high_end_4[0].literal->Equals("invalid code point")); | 213 EXPECT(high_end_4[0].literal->Equals("invalid code point")); |
194 CheckKind(high_end_4, 1, Token::kEOS); | 214 CheckKind(high_end_4, 1, Token::kEOS); |
195 | 215 |
196 const Scanner::GrowableTokenStream& high_end_seq = | 216 const GrowableTokenStream& high_end_seq = |
197 Scan("\"\\u{DBFF}\""); | 217 Scan("\"\\u{DBFF}\""); |
198 EXPECT_EQ(2, high_end_seq.length()); | 218 EXPECT_EQ(2, high_end_seq.length()); |
199 CheckKind(high_end_seq, 0, Token::kERROR); | 219 CheckKind(high_end_seq, 0, Token::kERROR); |
200 EXPECT(high_end_seq[0].literal->Equals("invalid code point")); | 220 EXPECT(high_end_seq[0].literal->Equals("invalid code point")); |
201 CheckKind(high_end_seq, 1, Token::kEOS); | 221 CheckKind(high_end_seq, 1, Token::kEOS); |
202 | 222 |
203 const Scanner::GrowableTokenStream& low_start_4 = | 223 const GrowableTokenStream& low_start_4 = |
204 Scan("\"\\uDC00\""); | 224 Scan("\"\\uDC00\""); |
205 EXPECT_EQ(2, low_start_4.length()); | 225 EXPECT_EQ(2, low_start_4.length()); |
206 CheckKind(low_start_4, 0, Token::kERROR); | 226 CheckKind(low_start_4, 0, Token::kERROR); |
207 EXPECT(low_start_4[0].literal->Equals("invalid code point")); | 227 EXPECT(low_start_4[0].literal->Equals("invalid code point")); |
208 CheckKind(low_start_4, 1, Token::kEOS); | 228 CheckKind(low_start_4, 1, Token::kEOS); |
209 | 229 |
210 const Scanner::GrowableTokenStream& low_start_seq = | 230 const GrowableTokenStream& low_start_seq = |
211 Scan("\"\\u{DC00}\""); | 231 Scan("\"\\u{DC00}\""); |
212 EXPECT_EQ(2, low_start_seq.length()); | 232 EXPECT_EQ(2, low_start_seq.length()); |
213 CheckKind(low_start_seq, 0, Token::kERROR); | 233 CheckKind(low_start_seq, 0, Token::kERROR); |
214 EXPECT(low_start_seq[0].literal->Equals("invalid code point")); | 234 EXPECT(low_start_seq[0].literal->Equals("invalid code point")); |
215 CheckKind(low_start_seq, 1, Token::kEOS); | 235 CheckKind(low_start_seq, 1, Token::kEOS); |
216 | 236 |
217 const Scanner::GrowableTokenStream& low_end_4 = | 237 const GrowableTokenStream& low_end_4 = |
218 Scan("\"\\uDFFF\""); | 238 Scan("\"\\uDFFF\""); |
219 EXPECT_EQ(2, low_end_4.length()); | 239 EXPECT_EQ(2, low_end_4.length()); |
220 CheckKind(low_end_4, 0, Token::kERROR); | 240 CheckKind(low_end_4, 0, Token::kERROR); |
221 EXPECT(low_end_4[0].literal->Equals("invalid code point")); | 241 EXPECT(low_end_4[0].literal->Equals("invalid code point")); |
222 CheckKind(low_end_4, 1, Token::kEOS); | 242 CheckKind(low_end_4, 1, Token::kEOS); |
223 | 243 |
224 const Scanner::GrowableTokenStream& low_end_seq = | 244 const GrowableTokenStream& low_end_seq = |
225 Scan("\"\\u{DFFF}\""); | 245 Scan("\"\\u{DFFF}\""); |
226 EXPECT_EQ(2, low_end_seq.length()); | 246 EXPECT_EQ(2, low_end_seq.length()); |
227 CheckKind(low_end_seq, 0, Token::kERROR); | 247 CheckKind(low_end_seq, 0, Token::kERROR); |
228 EXPECT(low_end_seq[0].literal->Equals("invalid code point")); | 248 EXPECT(low_end_seq[0].literal->Equals("invalid code point")); |
229 CheckKind(low_end_seq, 1, Token::kEOS); | 249 CheckKind(low_end_seq, 1, Token::kEOS); |
230 | 250 |
231 const Scanner::GrowableTokenStream& out_of_range_low = | 251 const GrowableTokenStream& out_of_range_low = |
232 Scan("\"\\u{110000}\""); | 252 Scan("\"\\u{110000}\""); |
233 EXPECT_EQ(2, out_of_range_low.length()); | 253 EXPECT_EQ(2, out_of_range_low.length()); |
234 CheckKind(out_of_range_low, 0, Token::kERROR); | 254 CheckKind(out_of_range_low, 0, Token::kERROR); |
235 EXPECT(out_of_range_low[0].literal->Equals("invalid code point")); | 255 EXPECT(out_of_range_low[0].literal->Equals("invalid code point")); |
236 CheckKind(out_of_range_low, 1, Token::kEOS); | 256 CheckKind(out_of_range_low, 1, Token::kEOS); |
237 | 257 |
238 const Scanner::GrowableTokenStream& out_of_range_high = | 258 const GrowableTokenStream& out_of_range_high = |
239 Scan("\"\\u{FFFFFF}\""); | 259 Scan("\"\\u{FFFFFF}\""); |
240 EXPECT_EQ(2, out_of_range_high.length()); | 260 EXPECT_EQ(2, out_of_range_high.length()); |
241 CheckKind(out_of_range_high, 0, Token::kERROR); | 261 CheckKind(out_of_range_high, 0, Token::kERROR); |
242 EXPECT(out_of_range_high[0].literal->Equals("invalid code point")); | 262 EXPECT(out_of_range_high[0].literal->Equals("invalid code point")); |
243 CheckKind(out_of_range_high, 1, Token::kEOS); | 263 CheckKind(out_of_range_high, 1, Token::kEOS); |
244 } | 264 } |
245 | 265 |
246 | 266 |
247 static void RawString() { | 267 static void RawString() { |
248 // rs = @"\' \\" | 268 // rs = @"\' \\" |
249 const Scanner::GrowableTokenStream& tokens = Scan("rs = r\"\\\' \\\\\""); | 269 const GrowableTokenStream& tokens = Scan("rs = r\"\\\' \\\\\""); |
250 | 270 |
251 EXPECT_EQ(4, tokens.length()); | 271 EXPECT_EQ(4, tokens.length()); |
252 CheckIdent(tokens, 0, "rs"); | 272 CheckIdent(tokens, 0, "rs"); |
253 CheckKind(tokens, 1, Token::kASSIGN); | 273 CheckKind(tokens, 1, Token::kASSIGN); |
254 CheckKind(tokens, 2, Token::kSTRING); | 274 CheckKind(tokens, 2, Token::kSTRING); |
255 CheckKind(tokens, 3, Token::kEOS); | 275 CheckKind(tokens, 3, Token::kEOS); |
256 CheckLineNumber(tokens, 2, 1); | 276 CheckLineNumber(tokens, 2, 1); |
257 const char* litchars = (tokens)[2].literal->ToCString(); | 277 const char* litchars = (tokens)[2].literal->ToCString(); |
258 EXPECT_EQ(5, (tokens)[2].literal->Length()); | 278 EXPECT_EQ(5, (tokens)[2].literal->Length()); |
259 | 279 |
260 EXPECT_EQ('\\', litchars[0]); | 280 EXPECT_EQ('\\', litchars[0]); |
261 EXPECT_EQ('\'', litchars[1]); | 281 EXPECT_EQ('\'', litchars[1]); |
262 EXPECT_EQ(' ', litchars[2]); | 282 EXPECT_EQ(' ', litchars[2]); |
263 EXPECT_EQ('\\', litchars[3]); | 283 EXPECT_EQ('\\', litchars[3]); |
264 EXPECT_EQ('\\', litchars[4]); | 284 EXPECT_EQ('\\', litchars[4]); |
265 } | 285 } |
266 | 286 |
267 | 287 |
268 static void MultilineString() { | 288 static void MultilineString() { |
269 // |mls = ''' | 289 // |mls = ''' |
270 // |1' x | 290 // |1' x |
271 // |2'''; | 291 // |2'''; |
272 const Scanner::GrowableTokenStream& tokens = Scan("mls = '''\n1' x\n2''';"); | 292 const GrowableTokenStream& tokens = Scan("mls = '''\n1' x\n2''';"); |
273 | 293 |
274 EXPECT_EQ(7, tokens.length()); | 294 EXPECT_EQ(7, tokens.length()); |
275 CheckIdent(tokens, 0, "mls"); | 295 CheckIdent(tokens, 0, "mls"); |
276 CheckKind(tokens, 1, Token::kASSIGN); | 296 CheckKind(tokens, 1, Token::kASSIGN); |
277 CheckKind(tokens, 2, Token::kSTRING); | 297 CheckKind(tokens, 2, Token::kSTRING); |
278 CheckKind(tokens, 3, Token::kNEWLINE); | 298 CheckKind(tokens, 3, Token::kNEWLINE); |
279 CheckKind(tokens, 4, Token::kNEWLINE); | 299 CheckKind(tokens, 4, Token::kNEWLINE); |
280 CheckKind(tokens, 5, Token::kSEMICOLON); | 300 CheckKind(tokens, 5, Token::kSEMICOLON); |
281 CheckKind(tokens, 6, Token::kEOS); | 301 CheckKind(tokens, 6, Token::kEOS); |
282 CheckLineNumber(tokens, 0, 1); | 302 CheckLineNumber(tokens, 0, 1); |
283 CheckLineNumber(tokens, 5, 3); // Semicolon is on line 3. | 303 CheckLineNumber(tokens, 5, 3); // Semicolon is on line 3. |
284 const char* litchars = (tokens)[2].literal->ToCString(); | 304 const char* litchars = (tokens)[2].literal->ToCString(); |
285 EXPECT_EQ(6, (tokens)[2].literal->Length()); | 305 EXPECT_EQ(6, (tokens)[2].literal->Length()); |
286 | 306 |
287 EXPECT_EQ('1', litchars[0]); // First newline is dropped. | 307 EXPECT_EQ('1', litchars[0]); // First newline is dropped. |
288 EXPECT_EQ('\'', litchars[1]); | 308 EXPECT_EQ('\'', litchars[1]); |
289 EXPECT_EQ(' ', litchars[2]); | 309 EXPECT_EQ(' ', litchars[2]); |
290 EXPECT_EQ('x', litchars[3]); | 310 EXPECT_EQ('x', litchars[3]); |
291 EXPECT_EQ('\n', litchars[4]); | 311 EXPECT_EQ('\n', litchars[4]); |
292 EXPECT_EQ('2', litchars[5]); | 312 EXPECT_EQ('2', litchars[5]); |
293 } | 313 } |
294 | 314 |
295 | 315 |
296 static void EmptyString() { | 316 static void EmptyString() { |
297 // es = ""; | 317 // es = ""; |
298 const Scanner::GrowableTokenStream& tokens = Scan("es = \"\";"); | 318 const GrowableTokenStream& tokens = Scan("es = \"\";"); |
299 | 319 |
300 EXPECT_EQ(5, tokens.length()); | 320 EXPECT_EQ(5, tokens.length()); |
301 CheckIdent(tokens, 0, "es"); | 321 CheckIdent(tokens, 0, "es"); |
302 CheckKind(tokens, 1, Token::kASSIGN); | 322 CheckKind(tokens, 1, Token::kASSIGN); |
303 CheckKind(tokens, 2, Token::kSTRING); | 323 CheckKind(tokens, 2, Token::kSTRING); |
304 CheckKind(tokens, 3, Token::kSEMICOLON); | 324 CheckKind(tokens, 3, Token::kSEMICOLON); |
305 CheckKind(tokens, 4, Token::kEOS); | 325 CheckKind(tokens, 4, Token::kEOS); |
306 EXPECT_EQ(0, (tokens)[2].literal->Length()); | 326 EXPECT_EQ(0, (tokens)[2].literal->Length()); |
307 } | 327 } |
308 | 328 |
309 static void EmptyMultilineString() { | 329 static void EmptyMultilineString() { |
310 // es = """"""; | 330 // es = """"""; |
311 const Scanner::GrowableTokenStream& tokens = Scan("es = \"\"\"\"\"\";"); | 331 const GrowableTokenStream& tokens = Scan("es = \"\"\"\"\"\";"); |
312 | 332 |
313 EXPECT_EQ(5, tokens.length()); | 333 EXPECT_EQ(5, tokens.length()); |
314 CheckIdent(tokens, 0, "es"); | 334 CheckIdent(tokens, 0, "es"); |
315 CheckKind(tokens, 1, Token::kASSIGN); | 335 CheckKind(tokens, 1, Token::kASSIGN); |
316 CheckKind(tokens, 2, Token::kSTRING); | 336 CheckKind(tokens, 2, Token::kSTRING); |
317 CheckKind(tokens, 3, Token::kSEMICOLON); | 337 CheckKind(tokens, 3, Token::kSEMICOLON); |
318 CheckKind(tokens, 4, Token::kEOS); | 338 CheckKind(tokens, 4, Token::kEOS); |
319 EXPECT_EQ(0, (tokens)[2].literal->Length()); | 339 EXPECT_EQ(0, (tokens)[2].literal->Length()); |
320 } | 340 } |
321 | 341 |
322 | 342 |
323 static void NumberLiteral() { | 343 static void NumberLiteral() { |
324 const Scanner::GrowableTokenStream& tokens = | 344 const GrowableTokenStream& tokens = |
325 Scan("5 0x5d 0.3 0.33 1E+12 .42 +5"); | 345 Scan("5 0x5d 0.3 0.33 1E+12 .42 +5"); |
326 | 346 |
327 CheckKind(tokens, 0, Token::kINTEGER); | 347 CheckKind(tokens, 0, Token::kINTEGER); |
328 CheckKind(tokens, 1, Token::kINTEGER); | 348 CheckKind(tokens, 1, Token::kINTEGER); |
329 CheckKind(tokens, 2, Token::kDOUBLE); | 349 CheckKind(tokens, 2, Token::kDOUBLE); |
330 CheckKind(tokens, 3, Token::kDOUBLE); | 350 CheckKind(tokens, 3, Token::kDOUBLE); |
331 CheckKind(tokens, 4, Token::kDOUBLE); | 351 CheckKind(tokens, 4, Token::kDOUBLE); |
332 CheckKind(tokens, 5, Token::kDOUBLE); | 352 CheckKind(tokens, 5, Token::kDOUBLE); |
333 CheckKind(tokens, 6, Token::kADD); | 353 CheckKind(tokens, 6, Token::kADD); |
334 CheckKind(tokens, 7, Token::kINTEGER); | 354 CheckKind(tokens, 7, Token::kINTEGER); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 " }" | 414 " }" |
395 "}" | 415 "}" |
396 "" | 416 "" |
397 "" | 417 "" |
398 "j!==!iffy // means j !== !iffy"; | 418 "j!==!iffy // means j !== !iffy"; |
399 Scan(dart_source); | 419 Scan(dart_source); |
400 } | 420 } |
401 | 421 |
402 | 422 |
403 void InvalidText() { | 423 void InvalidText() { |
404 const Scanner::GrowableTokenStream& tokens = | 424 const GrowableTokenStream& tokens = |
405 Scan("\\"); | 425 Scan("\\"); |
406 | 426 |
407 EXPECT_EQ(2, tokens.length()); | 427 EXPECT_EQ(2, tokens.length()); |
408 CheckKind(tokens, 0, Token::kERROR); | 428 CheckKind(tokens, 0, Token::kERROR); |
409 CheckKind(tokens, 1, Token::kEOS); | 429 CheckKind(tokens, 1, Token::kEOS); |
410 } | 430 } |
411 | 431 |
412 | 432 |
413 void NewlinesTest() { | 433 void NewlinesTest() { |
414 const char* source = | 434 const char* source = |
415 "var es = /* a\n" | 435 "var es = /* a\n" |
416 " b\n" | 436 " b\n" |
417 " */ \"\"\"\n" | 437 " */ \"\"\"\n" |
418 "c\n" | 438 "c\n" |
419 "d\n" | 439 "d\n" |
420 "\"\"\";"; | 440 "\"\"\";"; |
421 | 441 |
422 const Scanner::GrowableTokenStream& tokens = Scan(source); | 442 const GrowableTokenStream& tokens = Scan(source); |
423 | 443 |
424 EXPECT_EQ(11, tokens.length()); | 444 EXPECT_EQ(11, tokens.length()); |
425 CheckKind(tokens, 0, Token::kVAR); | 445 CheckKind(tokens, 0, Token::kVAR); |
426 CheckIdent(tokens, 1, "es"); | 446 CheckIdent(tokens, 1, "es"); |
427 CheckKind(tokens, 2, Token::kASSIGN); | 447 CheckKind(tokens, 2, Token::kASSIGN); |
428 CheckKind(tokens, 3, Token::kNEWLINE); | 448 CheckKind(tokens, 3, Token::kNEWLINE); |
429 CheckKind(tokens, 4, Token::kNEWLINE); | 449 CheckKind(tokens, 4, Token::kNEWLINE); |
430 CheckKind(tokens, 5, Token::kSTRING); | 450 CheckKind(tokens, 5, Token::kSTRING); |
431 CheckKind(tokens, 6, Token::kNEWLINE); | 451 CheckKind(tokens, 6, Token::kNEWLINE); |
432 CheckKind(tokens, 7, Token::kNEWLINE); | 452 CheckKind(tokens, 7, Token::kNEWLINE); |
(...skipping 21 matching lines...) Expand all Loading... |
454 RawString(); | 474 RawString(); |
455 MultilineString(); | 475 MultilineString(); |
456 EmptyString(); | 476 EmptyString(); |
457 EmptyMultilineString(); | 477 EmptyMultilineString(); |
458 NumberLiteral(); | 478 NumberLiteral(); |
459 InvalidText(); | 479 InvalidText(); |
460 NewlinesTest(); | 480 NewlinesTest(); |
461 } | 481 } |
462 | 482 |
463 } // namespace dart | 483 } // namespace dart |
OLD | NEW |