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) { | |
siva
2016/05/11 20:21:27
{ }
| |
104 } | |
105 virtual ~Collector() { } | |
106 | |
107 virtual void AddToken(const Scanner::TokenDescriptor& token) { | |
108 ts_->Add(token); | |
109 } | |
110 private: | |
111 GrowableTokenStream* ts_; | |
112 }; | |
113 | |
114 | |
115 static const GrowableTokenStream& Scan(const char* source) { | |
116 OS::Print("\nScanning: <%s>\n", source); | |
117 | |
98 Scanner scanner(String::Handle(String::New(source)), | 118 Scanner scanner(String::Handle(String::New(source)), |
99 String::Handle(String::New(""))); | 119 String::Handle(String::New(""))); |
120 GrowableTokenStream* tokens = new GrowableTokenStream(128); | |
121 Collector collector(tokens); | |
100 | 122 |
101 OS::Print("\nScanning: <%s>\n", source); | 123 scanner.ScanAll(&collector); |
102 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); | 124 LogTokenStream(*tokens); |
103 LogTokenStream(tokens); | 125 return *tokens; |
104 return tokens; | |
105 } | 126 } |
106 | 127 |
107 | 128 |
108 static void BoringTest() { | 129 static void BoringTest() { |
109 const Scanner::GrowableTokenStream& tokens = Scan("x = iffy++;"); | 130 const GrowableTokenStream& tokens = Scan("x = iffy++;"); |
110 | 131 |
111 CheckNumTokens(tokens, 6); | 132 CheckNumTokens(tokens, 6); |
112 CheckIdent(tokens, 0, "x"); | 133 CheckIdent(tokens, 0, "x"); |
113 CheckKind(tokens, 1, Token::kASSIGN); | 134 CheckKind(tokens, 1, Token::kASSIGN); |
114 CheckIdent(tokens, 2, "iffy"); | 135 CheckIdent(tokens, 2, "iffy"); |
115 CheckKind(tokens, 3, Token::kINCR); | 136 CheckKind(tokens, 3, Token::kINCR); |
116 CheckKind(tokens, 4, Token::kSEMICOLON); | 137 CheckKind(tokens, 4, Token::kSEMICOLON); |
117 } | 138 } |
118 | 139 |
119 | 140 |
120 static void CommentTest() { | 141 static void CommentTest() { |
121 const Scanner::GrowableTokenStream& tokens = | 142 const GrowableTokenStream& tokens = |
122 Scan("Foo( /*block \n" | 143 Scan("Foo( /*block \n" |
123 "comment*/ 0xff) // line comment;"); | 144 "comment*/ 0xff) // line comment;"); |
124 | 145 |
125 CheckNumTokens(tokens, 6); | 146 CheckNumTokens(tokens, 6); |
126 CheckIdent(tokens, 0, "Foo"); | 147 CheckIdent(tokens, 0, "Foo"); |
127 CheckLineNumber(tokens, 0, 1); | 148 CheckLineNumber(tokens, 0, 1); |
128 CheckKind(tokens, 1, Token::kLPAREN); | 149 CheckKind(tokens, 1, Token::kLPAREN); |
129 CheckKind(tokens, 2, Token::kNEWLINE); | 150 CheckKind(tokens, 2, Token::kNEWLINE); |
130 CheckInteger(tokens, 3, "0xff"); | 151 CheckInteger(tokens, 3, "0xff"); |
131 CheckKind(tokens, 4, Token::kRPAREN); | 152 CheckKind(tokens, 4, Token::kRPAREN); |
132 CheckLineNumber(tokens, 4, 2); | 153 CheckLineNumber(tokens, 4, 2); |
133 } | 154 } |
134 | 155 |
135 | 156 |
136 static void GreedIsGood() { | 157 static void GreedIsGood() { |
137 // means i++ + j | 158 // means i++ + j |
138 const Scanner::GrowableTokenStream& tokens = Scan("x=i+++j"); | 159 const GrowableTokenStream& tokens = Scan("x=i+++j"); |
139 | 160 |
140 CheckNumTokens(tokens, 7); | 161 CheckNumTokens(tokens, 7); |
141 CheckIdent(tokens, 0, "x"); | 162 CheckIdent(tokens, 0, "x"); |
142 CheckKind(tokens, 1, Token::kASSIGN); | 163 CheckKind(tokens, 1, Token::kASSIGN); |
143 CheckIdent(tokens, 2, "i"); | 164 CheckIdent(tokens, 2, "i"); |
144 CheckKind(tokens, 3, Token::kINCR); | 165 CheckKind(tokens, 3, Token::kINCR); |
145 CheckKind(tokens, 4, Token::kADD); | 166 CheckKind(tokens, 4, Token::kADD); |
146 CheckIdent(tokens, 5, "j"); | 167 CheckIdent(tokens, 5, "j"); |
147 } | 168 } |
148 | 169 |
149 | 170 |
150 static void StringEscapes() { | 171 static void StringEscapes() { |
151 // sss = "\" \\ \n\r\t \'" | 172 // sss = "\" \\ \n\r\t \'" |
152 const Scanner::GrowableTokenStream& tokens = | 173 const GrowableTokenStream& tokens = |
153 Scan("sss = \"\\\" \\\\ \\n\\r\\t \\\'\""); | 174 Scan("sss = \"\\\" \\\\ \\n\\r\\t \\\'\""); |
154 | 175 |
155 EXPECT_EQ(4, tokens.length()); | 176 EXPECT_EQ(4, tokens.length()); |
156 CheckIdent(tokens, 0, "sss"); | 177 CheckIdent(tokens, 0, "sss"); |
157 CheckKind(tokens, 1, Token::kASSIGN); | 178 CheckKind(tokens, 1, Token::kASSIGN); |
158 CheckKind(tokens, 2, Token::kSTRING); | 179 CheckKind(tokens, 2, Token::kSTRING); |
159 CheckKind(tokens, 3, Token::kEOS); | 180 CheckKind(tokens, 3, Token::kEOS); |
160 CheckLineNumber(tokens, 2, 1); | 181 CheckLineNumber(tokens, 2, 1); |
161 const char* litchars = (tokens)[2].literal->ToCString(); | 182 const char* litchars = (tokens)[2].literal->ToCString(); |
162 EXPECT_EQ(9, (tokens)[2].literal->Length()); | 183 EXPECT_EQ(9, (tokens)[2].literal->Length()); |
163 | 184 |
164 EXPECT_EQ('"', litchars[0]); | 185 EXPECT_EQ('"', litchars[0]); |
165 EXPECT_EQ(' ', litchars[1]); | 186 EXPECT_EQ(' ', litchars[1]); |
166 EXPECT_EQ('\\', litchars[2]); | 187 EXPECT_EQ('\\', litchars[2]); |
167 EXPECT_EQ('\n', litchars[4]); | 188 EXPECT_EQ('\n', litchars[4]); |
168 EXPECT_EQ('\r', litchars[5]); | 189 EXPECT_EQ('\r', litchars[5]); |
169 EXPECT_EQ('\t', litchars[6]); | 190 EXPECT_EQ('\t', litchars[6]); |
170 EXPECT_EQ('\'', litchars[8]); | 191 EXPECT_EQ('\'', litchars[8]); |
171 } | 192 } |
172 | 193 |
173 | 194 |
174 static void InvalidStringEscapes() { | 195 static void InvalidStringEscapes() { |
175 const Scanner::GrowableTokenStream& high_start_4 = | 196 const GrowableTokenStream& high_start_4 = |
176 Scan("\"\\uD800\""); | 197 Scan("\"\\uD800\""); |
177 EXPECT_EQ(2, high_start_4.length()); | 198 EXPECT_EQ(2, high_start_4.length()); |
178 CheckKind(high_start_4, 0, Token::kERROR); | 199 CheckKind(high_start_4, 0, Token::kERROR); |
179 EXPECT(high_start_4[0].literal->Equals("invalid code point")); | 200 EXPECT(high_start_4[0].literal->Equals("invalid code point")); |
180 CheckKind(high_start_4, 1, Token::kEOS); | 201 CheckKind(high_start_4, 1, Token::kEOS); |
181 | 202 |
182 const Scanner::GrowableTokenStream& high_start_seq = | 203 const GrowableTokenStream& high_start_seq = |
183 Scan("\"\\u{D800}\""); | 204 Scan("\"\\u{D800}\""); |
184 EXPECT_EQ(2, high_start_seq.length()); | 205 EXPECT_EQ(2, high_start_seq.length()); |
185 CheckKind(high_start_seq, 0, Token::kERROR); | 206 CheckKind(high_start_seq, 0, Token::kERROR); |
186 EXPECT(high_start_seq[0].literal->Equals("invalid code point")); | 207 EXPECT(high_start_seq[0].literal->Equals("invalid code point")); |
187 CheckKind(high_start_seq, 1, Token::kEOS); | 208 CheckKind(high_start_seq, 1, Token::kEOS); |
188 | 209 |
189 const Scanner::GrowableTokenStream& high_end_4 = | 210 const GrowableTokenStream& high_end_4 = |
190 Scan("\"\\uDBFF\""); | 211 Scan("\"\\uDBFF\""); |
191 EXPECT_EQ(2, high_end_4.length()); | 212 EXPECT_EQ(2, high_end_4.length()); |
192 CheckKind(high_end_4, 0, Token::kERROR); | 213 CheckKind(high_end_4, 0, Token::kERROR); |
193 EXPECT(high_end_4[0].literal->Equals("invalid code point")); | 214 EXPECT(high_end_4[0].literal->Equals("invalid code point")); |
194 CheckKind(high_end_4, 1, Token::kEOS); | 215 CheckKind(high_end_4, 1, Token::kEOS); |
195 | 216 |
196 const Scanner::GrowableTokenStream& high_end_seq = | 217 const GrowableTokenStream& high_end_seq = |
197 Scan("\"\\u{DBFF}\""); | 218 Scan("\"\\u{DBFF}\""); |
198 EXPECT_EQ(2, high_end_seq.length()); | 219 EXPECT_EQ(2, high_end_seq.length()); |
199 CheckKind(high_end_seq, 0, Token::kERROR); | 220 CheckKind(high_end_seq, 0, Token::kERROR); |
200 EXPECT(high_end_seq[0].literal->Equals("invalid code point")); | 221 EXPECT(high_end_seq[0].literal->Equals("invalid code point")); |
201 CheckKind(high_end_seq, 1, Token::kEOS); | 222 CheckKind(high_end_seq, 1, Token::kEOS); |
202 | 223 |
203 const Scanner::GrowableTokenStream& low_start_4 = | 224 const GrowableTokenStream& low_start_4 = |
204 Scan("\"\\uDC00\""); | 225 Scan("\"\\uDC00\""); |
205 EXPECT_EQ(2, low_start_4.length()); | 226 EXPECT_EQ(2, low_start_4.length()); |
206 CheckKind(low_start_4, 0, Token::kERROR); | 227 CheckKind(low_start_4, 0, Token::kERROR); |
207 EXPECT(low_start_4[0].literal->Equals("invalid code point")); | 228 EXPECT(low_start_4[0].literal->Equals("invalid code point")); |
208 CheckKind(low_start_4, 1, Token::kEOS); | 229 CheckKind(low_start_4, 1, Token::kEOS); |
209 | 230 |
210 const Scanner::GrowableTokenStream& low_start_seq = | 231 const GrowableTokenStream& low_start_seq = |
211 Scan("\"\\u{DC00}\""); | 232 Scan("\"\\u{DC00}\""); |
212 EXPECT_EQ(2, low_start_seq.length()); | 233 EXPECT_EQ(2, low_start_seq.length()); |
213 CheckKind(low_start_seq, 0, Token::kERROR); | 234 CheckKind(low_start_seq, 0, Token::kERROR); |
214 EXPECT(low_start_seq[0].literal->Equals("invalid code point")); | 235 EXPECT(low_start_seq[0].literal->Equals("invalid code point")); |
215 CheckKind(low_start_seq, 1, Token::kEOS); | 236 CheckKind(low_start_seq, 1, Token::kEOS); |
216 | 237 |
217 const Scanner::GrowableTokenStream& low_end_4 = | 238 const GrowableTokenStream& low_end_4 = |
218 Scan("\"\\uDFFF\""); | 239 Scan("\"\\uDFFF\""); |
219 EXPECT_EQ(2, low_end_4.length()); | 240 EXPECT_EQ(2, low_end_4.length()); |
220 CheckKind(low_end_4, 0, Token::kERROR); | 241 CheckKind(low_end_4, 0, Token::kERROR); |
221 EXPECT(low_end_4[0].literal->Equals("invalid code point")); | 242 EXPECT(low_end_4[0].literal->Equals("invalid code point")); |
222 CheckKind(low_end_4, 1, Token::kEOS); | 243 CheckKind(low_end_4, 1, Token::kEOS); |
223 | 244 |
224 const Scanner::GrowableTokenStream& low_end_seq = | 245 const GrowableTokenStream& low_end_seq = |
225 Scan("\"\\u{DFFF}\""); | 246 Scan("\"\\u{DFFF}\""); |
226 EXPECT_EQ(2, low_end_seq.length()); | 247 EXPECT_EQ(2, low_end_seq.length()); |
227 CheckKind(low_end_seq, 0, Token::kERROR); | 248 CheckKind(low_end_seq, 0, Token::kERROR); |
228 EXPECT(low_end_seq[0].literal->Equals("invalid code point")); | 249 EXPECT(low_end_seq[0].literal->Equals("invalid code point")); |
229 CheckKind(low_end_seq, 1, Token::kEOS); | 250 CheckKind(low_end_seq, 1, Token::kEOS); |
230 | 251 |
231 const Scanner::GrowableTokenStream& out_of_range_low = | 252 const GrowableTokenStream& out_of_range_low = |
232 Scan("\"\\u{110000}\""); | 253 Scan("\"\\u{110000}\""); |
233 EXPECT_EQ(2, out_of_range_low.length()); | 254 EXPECT_EQ(2, out_of_range_low.length()); |
234 CheckKind(out_of_range_low, 0, Token::kERROR); | 255 CheckKind(out_of_range_low, 0, Token::kERROR); |
235 EXPECT(out_of_range_low[0].literal->Equals("invalid code point")); | 256 EXPECT(out_of_range_low[0].literal->Equals("invalid code point")); |
236 CheckKind(out_of_range_low, 1, Token::kEOS); | 257 CheckKind(out_of_range_low, 1, Token::kEOS); |
237 | 258 |
238 const Scanner::GrowableTokenStream& out_of_range_high = | 259 const GrowableTokenStream& out_of_range_high = |
239 Scan("\"\\u{FFFFFF}\""); | 260 Scan("\"\\u{FFFFFF}\""); |
240 EXPECT_EQ(2, out_of_range_high.length()); | 261 EXPECT_EQ(2, out_of_range_high.length()); |
241 CheckKind(out_of_range_high, 0, Token::kERROR); | 262 CheckKind(out_of_range_high, 0, Token::kERROR); |
242 EXPECT(out_of_range_high[0].literal->Equals("invalid code point")); | 263 EXPECT(out_of_range_high[0].literal->Equals("invalid code point")); |
243 CheckKind(out_of_range_high, 1, Token::kEOS); | 264 CheckKind(out_of_range_high, 1, Token::kEOS); |
244 } | 265 } |
245 | 266 |
246 | 267 |
247 static void RawString() { | 268 static void RawString() { |
248 // rs = @"\' \\" | 269 // rs = @"\' \\" |
249 const Scanner::GrowableTokenStream& tokens = Scan("rs = r\"\\\' \\\\\""); | 270 const GrowableTokenStream& tokens = Scan("rs = r\"\\\' \\\\\""); |
250 | 271 |
251 EXPECT_EQ(4, tokens.length()); | 272 EXPECT_EQ(4, tokens.length()); |
252 CheckIdent(tokens, 0, "rs"); | 273 CheckIdent(tokens, 0, "rs"); |
253 CheckKind(tokens, 1, Token::kASSIGN); | 274 CheckKind(tokens, 1, Token::kASSIGN); |
254 CheckKind(tokens, 2, Token::kSTRING); | 275 CheckKind(tokens, 2, Token::kSTRING); |
255 CheckKind(tokens, 3, Token::kEOS); | 276 CheckKind(tokens, 3, Token::kEOS); |
256 CheckLineNumber(tokens, 2, 1); | 277 CheckLineNumber(tokens, 2, 1); |
257 const char* litchars = (tokens)[2].literal->ToCString(); | 278 const char* litchars = (tokens)[2].literal->ToCString(); |
258 EXPECT_EQ(5, (tokens)[2].literal->Length()); | 279 EXPECT_EQ(5, (tokens)[2].literal->Length()); |
259 | 280 |
260 EXPECT_EQ('\\', litchars[0]); | 281 EXPECT_EQ('\\', litchars[0]); |
261 EXPECT_EQ('\'', litchars[1]); | 282 EXPECT_EQ('\'', litchars[1]); |
262 EXPECT_EQ(' ', litchars[2]); | 283 EXPECT_EQ(' ', litchars[2]); |
263 EXPECT_EQ('\\', litchars[3]); | 284 EXPECT_EQ('\\', litchars[3]); |
264 EXPECT_EQ('\\', litchars[4]); | 285 EXPECT_EQ('\\', litchars[4]); |
265 } | 286 } |
266 | 287 |
267 | 288 |
268 static void MultilineString() { | 289 static void MultilineString() { |
269 // |mls = ''' | 290 // |mls = ''' |
270 // |1' x | 291 // |1' x |
271 // |2'''; | 292 // |2'''; |
272 const Scanner::GrowableTokenStream& tokens = Scan("mls = '''\n1' x\n2''';"); | 293 const GrowableTokenStream& tokens = Scan("mls = '''\n1' x\n2''';"); |
273 | 294 |
274 EXPECT_EQ(7, tokens.length()); | 295 EXPECT_EQ(7, tokens.length()); |
275 CheckIdent(tokens, 0, "mls"); | 296 CheckIdent(tokens, 0, "mls"); |
276 CheckKind(tokens, 1, Token::kASSIGN); | 297 CheckKind(tokens, 1, Token::kASSIGN); |
277 CheckKind(tokens, 2, Token::kSTRING); | 298 CheckKind(tokens, 2, Token::kSTRING); |
278 CheckKind(tokens, 3, Token::kNEWLINE); | 299 CheckKind(tokens, 3, Token::kNEWLINE); |
279 CheckKind(tokens, 4, Token::kNEWLINE); | 300 CheckKind(tokens, 4, Token::kNEWLINE); |
280 CheckKind(tokens, 5, Token::kSEMICOLON); | 301 CheckKind(tokens, 5, Token::kSEMICOLON); |
281 CheckKind(tokens, 6, Token::kEOS); | 302 CheckKind(tokens, 6, Token::kEOS); |
282 CheckLineNumber(tokens, 0, 1); | 303 CheckLineNumber(tokens, 0, 1); |
283 CheckLineNumber(tokens, 5, 3); // Semicolon is on line 3. | 304 CheckLineNumber(tokens, 5, 3); // Semicolon is on line 3. |
284 const char* litchars = (tokens)[2].literal->ToCString(); | 305 const char* litchars = (tokens)[2].literal->ToCString(); |
285 EXPECT_EQ(6, (tokens)[2].literal->Length()); | 306 EXPECT_EQ(6, (tokens)[2].literal->Length()); |
286 | 307 |
287 EXPECT_EQ('1', litchars[0]); // First newline is dropped. | 308 EXPECT_EQ('1', litchars[0]); // First newline is dropped. |
288 EXPECT_EQ('\'', litchars[1]); | 309 EXPECT_EQ('\'', litchars[1]); |
289 EXPECT_EQ(' ', litchars[2]); | 310 EXPECT_EQ(' ', litchars[2]); |
290 EXPECT_EQ('x', litchars[3]); | 311 EXPECT_EQ('x', litchars[3]); |
291 EXPECT_EQ('\n', litchars[4]); | 312 EXPECT_EQ('\n', litchars[4]); |
292 EXPECT_EQ('2', litchars[5]); | 313 EXPECT_EQ('2', litchars[5]); |
293 } | 314 } |
294 | 315 |
295 | 316 |
296 static void EmptyString() { | 317 static void EmptyString() { |
297 // es = ""; | 318 // es = ""; |
298 const Scanner::GrowableTokenStream& tokens = Scan("es = \"\";"); | 319 const GrowableTokenStream& tokens = Scan("es = \"\";"); |
299 | 320 |
300 EXPECT_EQ(5, tokens.length()); | 321 EXPECT_EQ(5, tokens.length()); |
301 CheckIdent(tokens, 0, "es"); | 322 CheckIdent(tokens, 0, "es"); |
302 CheckKind(tokens, 1, Token::kASSIGN); | 323 CheckKind(tokens, 1, Token::kASSIGN); |
303 CheckKind(tokens, 2, Token::kSTRING); | 324 CheckKind(tokens, 2, Token::kSTRING); |
304 CheckKind(tokens, 3, Token::kSEMICOLON); | 325 CheckKind(tokens, 3, Token::kSEMICOLON); |
305 CheckKind(tokens, 4, Token::kEOS); | 326 CheckKind(tokens, 4, Token::kEOS); |
306 EXPECT_EQ(0, (tokens)[2].literal->Length()); | 327 EXPECT_EQ(0, (tokens)[2].literal->Length()); |
307 } | 328 } |
308 | 329 |
309 static void EmptyMultilineString() { | 330 static void EmptyMultilineString() { |
310 // es = """"""; | 331 // es = """"""; |
311 const Scanner::GrowableTokenStream& tokens = Scan("es = \"\"\"\"\"\";"); | 332 const GrowableTokenStream& tokens = Scan("es = \"\"\"\"\"\";"); |
312 | 333 |
313 EXPECT_EQ(5, tokens.length()); | 334 EXPECT_EQ(5, tokens.length()); |
314 CheckIdent(tokens, 0, "es"); | 335 CheckIdent(tokens, 0, "es"); |
315 CheckKind(tokens, 1, Token::kASSIGN); | 336 CheckKind(tokens, 1, Token::kASSIGN); |
316 CheckKind(tokens, 2, Token::kSTRING); | 337 CheckKind(tokens, 2, Token::kSTRING); |
317 CheckKind(tokens, 3, Token::kSEMICOLON); | 338 CheckKind(tokens, 3, Token::kSEMICOLON); |
318 CheckKind(tokens, 4, Token::kEOS); | 339 CheckKind(tokens, 4, Token::kEOS); |
319 EXPECT_EQ(0, (tokens)[2].literal->Length()); | 340 EXPECT_EQ(0, (tokens)[2].literal->Length()); |
320 } | 341 } |
321 | 342 |
322 | 343 |
323 static void NumberLiteral() { | 344 static void NumberLiteral() { |
324 const Scanner::GrowableTokenStream& tokens = | 345 const GrowableTokenStream& tokens = |
325 Scan("5 0x5d 0.3 0.33 1E+12 .42 +5"); | 346 Scan("5 0x5d 0.3 0.33 1E+12 .42 +5"); |
326 | 347 |
327 CheckKind(tokens, 0, Token::kINTEGER); | 348 CheckKind(tokens, 0, Token::kINTEGER); |
328 CheckKind(tokens, 1, Token::kINTEGER); | 349 CheckKind(tokens, 1, Token::kINTEGER); |
329 CheckKind(tokens, 2, Token::kDOUBLE); | 350 CheckKind(tokens, 2, Token::kDOUBLE); |
330 CheckKind(tokens, 3, Token::kDOUBLE); | 351 CheckKind(tokens, 3, Token::kDOUBLE); |
331 CheckKind(tokens, 4, Token::kDOUBLE); | 352 CheckKind(tokens, 4, Token::kDOUBLE); |
332 CheckKind(tokens, 5, Token::kDOUBLE); | 353 CheckKind(tokens, 5, Token::kDOUBLE); |
333 CheckKind(tokens, 6, Token::kADD); | 354 CheckKind(tokens, 6, Token::kADD); |
334 CheckKind(tokens, 7, Token::kINTEGER); | 355 CheckKind(tokens, 7, Token::kINTEGER); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 " }" | 415 " }" |
395 "}" | 416 "}" |
396 "" | 417 "" |
397 "" | 418 "" |
398 "j!==!iffy // means j !== !iffy"; | 419 "j!==!iffy // means j !== !iffy"; |
399 Scan(dart_source); | 420 Scan(dart_source); |
400 } | 421 } |
401 | 422 |
402 | 423 |
403 void InvalidText() { | 424 void InvalidText() { |
404 const Scanner::GrowableTokenStream& tokens = | 425 const GrowableTokenStream& tokens = |
405 Scan("\\"); | 426 Scan("\\"); |
406 | 427 |
407 EXPECT_EQ(2, tokens.length()); | 428 EXPECT_EQ(2, tokens.length()); |
408 CheckKind(tokens, 0, Token::kERROR); | 429 CheckKind(tokens, 0, Token::kERROR); |
409 CheckKind(tokens, 1, Token::kEOS); | 430 CheckKind(tokens, 1, Token::kEOS); |
410 } | 431 } |
411 | 432 |
412 | 433 |
413 void NewlinesTest() { | 434 void NewlinesTest() { |
414 const char* source = | 435 const char* source = |
415 "var es = /* a\n" | 436 "var es = /* a\n" |
416 " b\n" | 437 " b\n" |
417 " */ \"\"\"\n" | 438 " */ \"\"\"\n" |
418 "c\n" | 439 "c\n" |
419 "d\n" | 440 "d\n" |
420 "\"\"\";"; | 441 "\"\"\";"; |
421 | 442 |
422 const Scanner::GrowableTokenStream& tokens = Scan(source); | 443 const GrowableTokenStream& tokens = Scan(source); |
423 | 444 |
424 EXPECT_EQ(11, tokens.length()); | 445 EXPECT_EQ(11, tokens.length()); |
425 CheckKind(tokens, 0, Token::kVAR); | 446 CheckKind(tokens, 0, Token::kVAR); |
426 CheckIdent(tokens, 1, "es"); | 447 CheckIdent(tokens, 1, "es"); |
427 CheckKind(tokens, 2, Token::kASSIGN); | 448 CheckKind(tokens, 2, Token::kASSIGN); |
428 CheckKind(tokens, 3, Token::kNEWLINE); | 449 CheckKind(tokens, 3, Token::kNEWLINE); |
429 CheckKind(tokens, 4, Token::kNEWLINE); | 450 CheckKind(tokens, 4, Token::kNEWLINE); |
430 CheckKind(tokens, 5, Token::kSTRING); | 451 CheckKind(tokens, 5, Token::kSTRING); |
431 CheckKind(tokens, 6, Token::kNEWLINE); | 452 CheckKind(tokens, 6, Token::kNEWLINE); |
432 CheckKind(tokens, 7, Token::kNEWLINE); | 453 CheckKind(tokens, 7, Token::kNEWLINE); |
(...skipping 21 matching lines...) Expand all Loading... | |
454 RawString(); | 475 RawString(); |
455 MultilineString(); | 476 MultilineString(); |
456 EmptyString(); | 477 EmptyString(); |
457 EmptyMultilineString(); | 478 EmptyMultilineString(); |
458 NumberLiteral(); | 479 NumberLiteral(); |
459 InvalidText(); | 480 InvalidText(); |
460 NewlinesTest(); | 481 NewlinesTest(); |
461 } | 482 } |
462 | 483 |
463 } // namespace dart | 484 } // namespace dart |
OLD | NEW |