Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(615)

Side by Side Diff: lib/compiler/implementation/scanner/scanner.dart

Issue 9958009: Implement cascaded calls. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 interface Scanner { 5 interface Scanner {
6 Token tokenize(); 6 Token tokenize();
7 } 7 }
8 8
9 /** 9 /**
10 * Common base class for a Dart scanner. 10 * Common base class for a Dart scanner.
11 */ 11 */
12 class AbstractScanner<T> implements Scanner { 12 class AbstractScanner<T> implements Scanner {
13 abstract int advance(); 13 abstract int advance();
14 abstract int nextByte(); 14 abstract int nextByte();
15 abstract int peek(); 15 abstract int peek();
16 abstract int select(int choice, PrecedenceInfo yes, PrecedenceInfo no); 16 abstract int select(int choice, PrecedenceInfo yes, PrecedenceInfo no);
17 abstract void appendPrecenceToken(PrecedenceInfo info); 17 abstract void appendPrecedenceToken(PrecedenceInfo info);
18 abstract void appendStringToken(PrecedenceInfo info, String value); 18 abstract void appendStringToken(PrecedenceInfo info, String value);
19 abstract void appendByteStringToken(PrecedenceInfo info, T value); 19 abstract void appendByteStringToken(PrecedenceInfo info, T value);
20 abstract void appendKeywordToken(Keyword keyword); 20 abstract void appendKeywordToken(Keyword keyword);
21 abstract void appendWhiteSpace(int next); 21 abstract void appendWhiteSpace(int next);
22 abstract void appendEofToken(); 22 abstract void appendEofToken();
23 abstract T asciiString(int start, int offset); 23 abstract T asciiString(int start, int offset);
24 abstract T utf8String(int start, int offset); 24 abstract T utf8String(int start, int offset);
25 abstract Token firstToken(); 25 abstract Token firstToken();
26 abstract void beginToken(); 26 abstract void beginToken();
27 abstract void addToCharOffset(int offset); 27 abstract void addToCharOffset(int offset);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 106
107 if (next === $OPEN_SQUARE_BRACKET) { 107 if (next === $OPEN_SQUARE_BRACKET) {
108 return tokenizeOpenSquareBracket(next); 108 return tokenizeOpenSquareBracket(next);
109 } 109 }
110 110
111 if (next === $TILDE) { 111 if (next === $TILDE) {
112 return tokenizeTilde(next); 112 return tokenizeTilde(next);
113 } 113 }
114 114
115 if (next === $BACKSLASH) { 115 if (next === $BACKSLASH) {
116 appendPrecenceToken(BACKSLASH_INFO); 116 appendPrecedenceToken(BACKSLASH_INFO);
117 return advance(); 117 return advance();
118 } 118 }
119 119
120 if (next === $HASH) { 120 if (next === $HASH) {
121 return tokenizeTag(next); 121 return tokenizeTag(next);
122 } 122 }
123 123
124 if (next === $OPEN_PAREN) { 124 if (next === $OPEN_PAREN) {
125 appendBeginGroup(OPEN_PAREN_INFO, "("); 125 appendBeginGroup(OPEN_PAREN_INFO, "(");
126 return advance(); 126 return advance();
127 } 127 }
128 128
129 if (next === $CLOSE_PAREN) { 129 if (next === $CLOSE_PAREN) {
130 return appendEndGroup(CLOSE_PAREN_INFO, ")", OPEN_PAREN_TOKEN); 130 return appendEndGroup(CLOSE_PAREN_INFO, ")", OPEN_PAREN_TOKEN);
131 } 131 }
132 132
133 if (next === $COMMA) { 133 if (next === $COMMA) {
134 appendPrecenceToken(COMMA_INFO); 134 appendPrecedenceToken(COMMA_INFO);
135 return advance(); 135 return advance();
136 } 136 }
137 137
138 if (next === $COLON) { 138 if (next === $COLON) {
139 appendPrecenceToken(COLON_INFO); 139 appendPrecedenceToken(COLON_INFO);
140 return advance(); 140 return advance();
141 } 141 }
142 142
143 if (next === $SEMICOLON) { 143 if (next === $SEMICOLON) {
144 appendPrecenceToken(SEMICOLON_INFO); 144 appendPrecedenceToken(SEMICOLON_INFO);
145 discardOpenLt(); 145 discardOpenLt();
146 return advance(); 146 return advance();
147 } 147 }
148 148
149 if (next === $QUESTION) { 149 if (next === $QUESTION) {
150 appendPrecenceToken(QUESTION_INFO); 150 appendPrecedenceToken(QUESTION_INFO);
151 return advance(); 151 return advance();
152 } 152 }
153 153
154 if (next === $CLOSE_SQUARE_BRACKET) { 154 if (next === $CLOSE_SQUARE_BRACKET) {
155 return appendEndGroup(CLOSE_SQUARE_BRACKET_INFO, "]", 155 return appendEndGroup(CLOSE_SQUARE_BRACKET_INFO, "]",
156 OPEN_SQUARE_BRACKET_TOKEN); 156 OPEN_SQUARE_BRACKET_TOKEN);
157 } 157 }
158 158
159 if (next === $BACKPING) { 159 if (next === $BACKPING) {
160 appendPrecenceToken(BACKPING_INFO); 160 appendPrecedenceToken(BACKPING_INFO);
161 return advance(); 161 return advance();
162 } 162 }
163 163
164 if (next === $OPEN_CURLY_BRACKET) { 164 if (next === $OPEN_CURLY_BRACKET) {
165 appendBeginGroup(OPEN_CURLY_BRACKET_INFO, "{"); 165 appendBeginGroup(OPEN_CURLY_BRACKET_INFO, "{");
166 return advance(); 166 return advance();
167 } 167 }
168 168
169 if (next === $CLOSE_CURLY_BRACKET) { 169 if (next === $CLOSE_CURLY_BRACKET) {
170 return appendEndGroup(CLOSE_CURLY_BRACKET_INFO, "}", 170 return appendEndGroup(CLOSE_CURLY_BRACKET_INFO, "}",
171 OPEN_CURLY_BRACKET_TOKEN); 171 OPEN_CURLY_BRACKET_TOKEN);
172 } 172 }
173 173
174 if (next === $SLASH) { 174 if (next === $SLASH) {
175 return tokenizeSlashOrComment(next); 175 return tokenizeSlashOrComment(next);
176 } 176 }
177 177
178 if (next === $AT) { 178 if (next === $AT) {
179 return tokenizeRawString(next); 179 return tokenizeRawString(next);
180 } 180 }
181 181
182 if (next === $DQ || next === $SQ) { 182 if (next === $DQ || next === $SQ) {
183 return tokenizeString(next, byteOffset, false); 183 return tokenizeString(next, byteOffset, false);
184 } 184 }
185 185
186 if (next === $PERIOD) { 186 if (next === $PERIOD) {
187 return tokenizeDotOrNumber(next); 187 return tokenizeDotsOrNumber(next);
188 } 188 }
189 189
190 if (next === $0) { 190 if (next === $0) {
191 return tokenizeHexOrNumber(next); 191 return tokenizeHexOrNumber(next);
192 } 192 }
193 193
194 // TODO(ahe): Would a range check be faster? 194 // TODO(ahe): Would a range check be faster?
195 if (next === $1 || next === $2 || next === $3 || next === $4 || next === $5 195 if (next === $1 || next === $2 || next === $3 || next === $4 || next === $5
196 || next === $6 || next === $7 || next === $8 || next === $9) { 196 || next === $6 || next === $7 || next === $8 || next === $9) {
197 return tokenizeNumber(next); 197 return tokenizeNumber(next);
(...skipping 19 matching lines...) Expand all
217 int tokenizeTag(int next) { 217 int tokenizeTag(int next) {
218 // # or #!.*[\n\r] 218 // # or #!.*[\n\r]
219 if (byteOffset === 0) { 219 if (byteOffset === 0) {
220 if (peek() === $BANG) { 220 if (peek() === $BANG) {
221 do { 221 do {
222 next = advance(); 222 next = advance();
223 } while (next !== $LF && next !== $CR && next !== $EOF); 223 } while (next !== $LF && next !== $CR && next !== $EOF);
224 return next; 224 return next;
225 } 225 }
226 } 226 }
227 appendPrecenceToken(HASH_INFO); 227 appendPrecedenceToken(HASH_INFO);
228 return advance(); 228 return advance();
229 } 229 }
230 230
231 int tokenizeTilde(int next) { 231 int tokenizeTilde(int next) {
232 // ~ ~/ ~/= 232 // ~ ~/ ~/=
233 next = advance(); 233 next = advance();
234 if (next === $SLASH) { 234 if (next === $SLASH) {
235 return select($EQ, TILDE_SLASH_EQ_INFO, TILDE_SLASH_INFO); 235 return select($EQ, TILDE_SLASH_EQ_INFO, TILDE_SLASH_INFO);
236 } else { 236 } else {
237 appendPrecenceToken(TILDE_INFO); 237 appendPrecedenceToken(TILDE_INFO);
238 return next; 238 return next;
239 } 239 }
240 } 240 }
241 241
242 int tokenizeOpenSquareBracket(int next) { 242 int tokenizeOpenSquareBracket(int next) {
243 // [ [] []= 243 // [ [] []=
244 next = advance(); 244 next = advance();
245 if (next === $CLOSE_SQUARE_BRACKET) { 245 if (next === $CLOSE_SQUARE_BRACKET) {
246 return select($EQ, INDEX_EQ_INFO, INDEX_INFO); 246 return select($EQ, INDEX_EQ_INFO, INDEX_INFO);
247 } else { 247 } else {
248 appendBeginGroup(OPEN_SQUARE_BRACKET_INFO, "["); 248 appendBeginGroup(OPEN_SQUARE_BRACKET_INFO, "[");
249 return next; 249 return next;
250 } 250 }
251 } 251 }
252 252
253 int tokenizeCaret(int next) { 253 int tokenizeCaret(int next) {
254 // ^ ^= 254 // ^ ^=
255 return select($EQ, CARET_EQ_INFO, CARET_INFO); 255 return select($EQ, CARET_EQ_INFO, CARET_INFO);
256 } 256 }
257 257
258 int tokenizeBar(int next) { 258 int tokenizeBar(int next) {
259 // | || |= 259 // | || |=
260 next = advance(); 260 next = advance();
261 if (next === $BAR) { 261 if (next === $BAR) {
262 appendPrecenceToken(BAR_BAR_INFO); 262 appendPrecedenceToken(BAR_BAR_INFO);
263 return advance(); 263 return advance();
264 } else if (next === $EQ) { 264 } else if (next === $EQ) {
265 appendPrecenceToken(BAR_EQ_INFO); 265 appendPrecedenceToken(BAR_EQ_INFO);
266 return advance(); 266 return advance();
267 } else { 267 } else {
268 appendPrecenceToken(BAR_INFO); 268 appendPrecedenceToken(BAR_INFO);
269 return next; 269 return next;
270 } 270 }
271 } 271 }
272 272
273 int tokenizeAmpersand(int next) { 273 int tokenizeAmpersand(int next) {
274 // && &= & 274 // && &= &
275 next = advance(); 275 next = advance();
276 if (next === $AMPERSAND) { 276 if (next === $AMPERSAND) {
277 appendPrecenceToken(AMPERSAND_AMPERSAND_INFO); 277 appendPrecedenceToken(AMPERSAND_AMPERSAND_INFO);
278 return advance(); 278 return advance();
279 } else if (next === $EQ) { 279 } else if (next === $EQ) {
280 appendPrecenceToken(AMPERSAND_EQ_INFO); 280 appendPrecedenceToken(AMPERSAND_EQ_INFO);
281 return advance(); 281 return advance();
282 } else { 282 } else {
283 appendPrecenceToken(AMPERSAND_INFO); 283 appendPrecedenceToken(AMPERSAND_INFO);
284 return next; 284 return next;
285 } 285 }
286 } 286 }
287 287
288 int tokenizePercent(int next) { 288 int tokenizePercent(int next) {
289 // % %= 289 // % %=
290 return select($EQ, PERCENT_EQ_INFO, PERCENT_INFO); 290 return select($EQ, PERCENT_EQ_INFO, PERCENT_INFO);
291 } 291 }
292 292
293 int tokenizeMultiply(int next) { 293 int tokenizeMultiply(int next) {
294 // * *= 294 // * *=
295 return select($EQ, STAR_EQ_INFO, STAR_INFO); 295 return select($EQ, STAR_EQ_INFO, STAR_INFO);
296 } 296 }
297 297
298 int tokenizeMinus(int next) { 298 int tokenizeMinus(int next) {
299 // - -- -= 299 // - -- -=
300 next = advance(); 300 next = advance();
301 if (next === $MINUS) { 301 if (next === $MINUS) {
302 appendPrecenceToken(MINUS_MINUS_INFO); 302 appendPrecedenceToken(MINUS_MINUS_INFO);
303 return advance(); 303 return advance();
304 } else if (next === $EQ) { 304 } else if (next === $EQ) {
305 appendPrecenceToken(MINUS_EQ_INFO); 305 appendPrecedenceToken(MINUS_EQ_INFO);
306 return advance(); 306 return advance();
307 } else { 307 } else {
308 appendPrecenceToken(MINUS_INFO); 308 appendPrecedenceToken(MINUS_INFO);
309 return next; 309 return next;
310 } 310 }
311 } 311 }
312 312
313 313
314 int tokenizePlus(int next) { 314 int tokenizePlus(int next) {
315 // + ++ += 315 // + ++ +=
316 next = advance(); 316 next = advance();
317 if ($PLUS === next) { 317 if ($PLUS === next) {
318 appendPrecenceToken(PLUS_PLUS_INFO); 318 appendPrecedenceToken(PLUS_PLUS_INFO);
319 return advance(); 319 return advance();
320 } else if ($EQ === next) { 320 } else if ($EQ === next) {
321 appendPrecenceToken(PLUS_EQ_INFO); 321 appendPrecedenceToken(PLUS_EQ_INFO);
322 return advance(); 322 return advance();
323 } else { 323 } else {
324 appendPrecenceToken(PLUS_INFO); 324 appendPrecedenceToken(PLUS_INFO);
325 return next; 325 return next;
326 } 326 }
327 } 327 }
328 328
329 int tokenizeExclamation(int next) { 329 int tokenizeExclamation(int next) {
330 // ! != !== 330 // ! != !==
331 next = advance(); 331 next = advance();
332 if (next === $EQ) { 332 if (next === $EQ) {
333 return select($EQ, BANG_EQ_EQ_INFO, BANG_EQ_INFO); 333 return select($EQ, BANG_EQ_EQ_INFO, BANG_EQ_INFO);
334 } 334 }
335 appendPrecenceToken(BANG_INFO); 335 appendPrecedenceToken(BANG_INFO);
336 return next; 336 return next;
337 } 337 }
338 338
339 int tokenizeEquals(int next) { 339 int tokenizeEquals(int next) {
340 // = == === 340 // = == ===
341 next = advance(); 341 next = advance();
342 if (next === $EQ) { 342 if (next === $EQ) {
343 return select($EQ, EQ_EQ_EQ_INFO, EQ_EQ_INFO); 343 return select($EQ, EQ_EQ_EQ_INFO, EQ_EQ_INFO);
344 } else if (next === $GT) { 344 } else if (next === $GT) {
345 appendPrecenceToken(FUNCTION_INFO); 345 appendPrecedenceToken(FUNCTION_INFO);
346 return advance(); 346 return advance();
347 } 347 }
348 appendPrecenceToken(EQ_INFO); 348 appendPrecedenceToken(EQ_INFO);
349 return next; 349 return next;
350 } 350 }
351 351
352 int tokenizeGreaterThan(int next) { 352 int tokenizeGreaterThan(int next) {
353 // > >= >> >>= >>> >>>= 353 // > >= >> >>= >>> >>>=
354 next = advance(); 354 next = advance();
355 if ($EQ === next) { 355 if ($EQ === next) {
356 appendPrecenceToken(GT_EQ_INFO); 356 appendPrecedenceToken(GT_EQ_INFO);
357 return advance(); 357 return advance();
358 } else if ($GT === next) { 358 } else if ($GT === next) {
359 next = advance(); 359 next = advance();
360 if ($EQ === next) { 360 if ($EQ === next) {
361 appendPrecenceToken(GT_GT_EQ_INFO); 361 appendPrecedenceToken(GT_GT_EQ_INFO);
362 return advance(); 362 return advance();
363 } else if ($GT === next) { 363 } else if ($GT === next) {
364 next = advance(); 364 next = advance();
365 if (next === $EQ) { 365 if (next === $EQ) {
366 appendPrecenceToken(GT_GT_GT_EQ_INFO); 366 appendPrecedenceToken(GT_GT_GT_EQ_INFO);
367 return advance(); 367 return advance();
368 } else { 368 } else {
369 appendGtGtGt(GT_GT_GT_INFO, ">>>"); 369 appendGtGtGt(GT_GT_GT_INFO, ">>>");
370 return next; 370 return next;
371 } 371 }
372 } else { 372 } else {
373 appendGtGt(GT_GT_INFO, ">>"); 373 appendGtGt(GT_GT_INFO, ">>");
374 return next; 374 return next;
375 } 375 }
376 } else { 376 } else {
377 appendGt(GT_INFO, ">"); 377 appendGt(GT_INFO, ">");
378 return next; 378 return next;
379 } 379 }
380 } 380 }
381 381
382 int tokenizeLessThan(int next) { 382 int tokenizeLessThan(int next) {
383 // < <= << <<= 383 // < <= << <<=
384 next = advance(); 384 next = advance();
385 if ($EQ === next) { 385 if ($EQ === next) {
386 appendPrecenceToken(LT_EQ_INFO); 386 appendPrecedenceToken(LT_EQ_INFO);
387 return advance(); 387 return advance();
388 } else if ($LT === next) { 388 } else if ($LT === next) {
389 return select($EQ, LT_LT_EQ_INFO, LT_LT_INFO); 389 return select($EQ, LT_LT_EQ_INFO, LT_LT_INFO);
390 } else { 390 } else {
391 appendBeginGroup(LT_INFO, "<"); 391 appendBeginGroup(LT_INFO, "<");
392 return next; 392 return next;
393 } 393 }
394 } 394 }
395 395
396 int tokenizeNumber(int next) { 396 int tokenizeNumber(int next) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 } else { 431 } else {
432 if (!hasDigits) { 432 if (!hasDigits) {
433 throw new MalformedInputException("hex digit expected", charOffset); 433 throw new MalformedInputException("hex digit expected", charOffset);
434 } 434 }
435 appendByteStringToken(HEXADECIMAL_INFO, asciiString(start, 0)); 435 appendByteStringToken(HEXADECIMAL_INFO, asciiString(start, 0));
436 return next; 436 return next;
437 } 437 }
438 } 438 }
439 } 439 }
440 440
441 int tokenizeDotOrNumber(int next) { 441 int tokenizeDotsOrNumber(int next) {
442 int start = byteOffset; 442 int start = byteOffset;
443 next = advance(); 443 next = advance();
444 if (($0 <= next && next <= $9)) { 444 if (($0 <= next && next <= $9)) {
445 return tokenizeFractionPart(next, start); 445 return tokenizeFractionPart(next, start);
446 } else if ($PERIOD === next) { 446 } else if ($PERIOD === next) {
447 return select($PERIOD, PERIOD_PERIOD_PERIOD_INFO, PERIOD_PERIOD_INFO); 447 return select($PERIOD, PERIOD_PERIOD_PERIOD_INFO, PERIOD_PERIOD_INFO);
448 } else { 448 } else {
449 appendPrecenceToken(PERIOD_INFO); 449 appendPrecedenceToken(PERIOD_INFO);
450 return next; 450 return next;
451 } 451 }
452 } 452 }
453 453
454 int tokenizeFractionPart(int next, int start) { 454 int tokenizeFractionPart(int next, int start) {
455 bool done = false; 455 bool done = false;
456 bool hasDigit = false; 456 bool hasDigit = false;
457 LOOP: while (!done) { 457 LOOP: while (!done) {
458 if ($0 <= next && next <= $9) { 458 if ($0 <= next && next <= $9) {
459 hasDigit = true; 459 hasDigit = true;
460 } else if ($e === next || $E === next) { 460 } else if ($e === next || $E === next) {
461 hasDigit = true; 461 hasDigit = true;
462 next = tokenizeExponent(advance()); 462 next = tokenizeExponent(advance());
463 done = true; 463 done = true;
464 continue LOOP; 464 continue LOOP;
465 } else { 465 } else {
466 done = true; 466 done = true;
467 continue LOOP; 467 continue LOOP;
468 } 468 }
469 next = advance(); 469 next = advance();
470 } 470 }
471 if (!hasDigit) { 471 if (!hasDigit) {
472 appendByteStringToken(INT_INFO, asciiString(start, -1)); 472 appendByteStringToken(INT_INFO, asciiString(start, -1));
473 if ($PERIOD === next) {
474 return select($PERIOD, PERIOD_PERIOD_PERIOD_INFO, PERIOD_PERIOD_INFO);
475 }
473 // TODO(ahe): Wrong offset for the period. 476 // TODO(ahe): Wrong offset for the period.
474 appendPrecenceToken(PERIOD_INFO); 477 appendPrecedenceToken(PERIOD_INFO);
475 return bigSwitch(next); 478 return bigSwitch(next);
476 } 479 }
477 if (next === $d || next === $D) { 480 if (next === $d || next === $D) {
478 next = advance(); 481 next = advance();
479 } 482 }
480 appendByteStringToken(DOUBLE_INFO, asciiString(start, 0)); 483 appendByteStringToken(DOUBLE_INFO, asciiString(start, 0));
481 return next; 484 return next;
482 } 485 }
483 486
484 int tokenizeExponent(int next) { 487 int tokenizeExponent(int next) {
(...skipping 14 matching lines...) Expand all
499 } 502 }
500 } 503 }
501 504
502 int tokenizeSlashOrComment(int next) { 505 int tokenizeSlashOrComment(int next) {
503 next = advance(); 506 next = advance();
504 if ($STAR === next) { 507 if ($STAR === next) {
505 return tokenizeMultiLineComment(next); 508 return tokenizeMultiLineComment(next);
506 } else if ($SLASH === next) { 509 } else if ($SLASH === next) {
507 return tokenizeSingleLineComment(next); 510 return tokenizeSingleLineComment(next);
508 } else if ($EQ === next) { 511 } else if ($EQ === next) {
509 appendPrecenceToken(SLASH_EQ_INFO); 512 appendPrecedenceToken(SLASH_EQ_INFO);
510 return advance(); 513 return advance();
511 } else { 514 } else {
512 appendPrecenceToken(SLASH_INFO); 515 appendPrecedenceToken(SLASH_INFO);
513 return next; 516 return next;
514 } 517 }
515 } 518 }
516 519
517 int tokenizeSingleLineComment(int next) { 520 int tokenizeSingleLineComment(int next) {
518 while (true) { 521 while (true) {
519 next = advance(); 522 next = advance();
520 if ($LF === next || $CR === next || $EOF === next) { 523 if ($LF === next || $CR === next || $EOF === next) {
521 return next; 524 return next;
522 } 525 }
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 charOffset); 758 charOffset);
756 } 759 }
757 } 760 }
758 761
759 class MalformedInputException { 762 class MalformedInputException {
760 final String message; 763 final String message;
761 final position; 764 final position;
762 MalformedInputException(this.message, this.position); 765 MalformedInputException(this.message, this.position);
763 toString() => message; 766 toString() => message;
764 } 767 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/scanner/parser.dart ('k') | lib/compiler/implementation/scanner/token.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698