| 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 |