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

Side by Side Diff: sky/framework/sky-element/third_party/esprima/esprima.sky

Issue 698653002: Add initial SkyElement & city-list example (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: moar cleanup Created 6 years, 1 month 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
OLDNEW
(Empty)
1 <script>
2
3 /*
4 Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
5 Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
6 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
7 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
8 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
9 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
10 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
11 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
12 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
13
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions are met:
16
17 * Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19 * Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 var Token,
36 TokenName,
37 Syntax,
38 Messages,
39 source,
40 index,
41 length,
42 delegate,
43 lookahead,
44 state;
45
46 Token = {
47 BooleanLiteral: 1,
48 EOF: 2,
49 Identifier: 3,
50 Keyword: 4,
51 NullLiteral: 5,
52 NumericLiteral: 6,
53 Punctuator: 7,
54 StringLiteral: 8
55 };
56
57 TokenName = {};
58 TokenName[Token.BooleanLiteral] = 'Boolean';
59 TokenName[Token.EOF] = '<end>';
60 TokenName[Token.Identifier] = 'Identifier';
61 TokenName[Token.Keyword] = 'Keyword';
62 TokenName[Token.NullLiteral] = 'Null';
63 TokenName[Token.NumericLiteral] = 'Numeric';
64 TokenName[Token.Punctuator] = 'Punctuator';
65 TokenName[Token.StringLiteral] = 'String';
66
67 Syntax = {
68 ArrayExpression: 'ArrayExpression',
69 BinaryExpression: 'BinaryExpression',
70 CallExpression: 'CallExpression',
71 ConditionalExpression: 'ConditionalExpression',
72 EmptyStatement: 'EmptyStatement',
73 ExpressionStatement: 'ExpressionStatement',
74 Identifier: 'Identifier',
75 Literal: 'Literal',
76 LabeledStatement: 'LabeledStatement',
77 LogicalExpression: 'LogicalExpression',
78 MemberExpression: 'MemberExpression',
79 ObjectExpression: 'ObjectExpression',
80 Program: 'Program',
81 Property: 'Property',
82 ThisExpression: 'ThisExpression',
83 UnaryExpression: 'UnaryExpression'
84 };
85
86 // Error messages should be identical to V8.
87 Messages = {
88 UnexpectedToken: 'Unexpected token %0',
89 UnknownLabel: 'Undefined label \'%0\'',
90 Redeclaration: '%0 \'%1\' has already been declared'
91 };
92
93 // Ensure the condition is true, otherwise throw an error.
94 // This is only to have a better contract semantic, i.e. another safety net
95 // to catch a logic error. The condition shall be fulfilled in normal case.
96 // Do NOT use this to enforce a certain condition on any user input.
97
98 function assert(condition, message) {
99 if (!condition) {
100 throw new Error('ASSERT: ' + message);
101 }
102 }
103
104 function isDecimalDigit(ch) {
105 return (ch >= 48 && ch <= 57); // 0..9
106 }
107
108
109 // 7.2 White Space
110
111 function isWhiteSpace(ch) {
112 return (ch === 32) || // space
113 (ch === 9) || // tab
114 (ch === 0xB) ||
115 (ch === 0xC) ||
116 (ch === 0xA0) ||
117 (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006 \u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch )) > 0);
118 }
119
120 // 7.3 Line Terminators
121
122 function isLineTerminator(ch) {
123 return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
124 }
125
126 // 7.6 Identifier Names and Identifiers
127
128 function isIdentifierStart(ch) {
129 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
130 (ch >= 65 && ch <= 90) || // A..Z
131 (ch >= 97 && ch <= 122); // a..z
132 }
133
134 function isIdentifierPart(ch) {
135 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
136 (ch >= 65 && ch <= 90) || // A..Z
137 (ch >= 97 && ch <= 122) || // a..z
138 (ch >= 48 && ch <= 57); // 0..9
139 }
140
141 // 7.6.1.1 Keywords
142
143 function isKeyword(id) {
144 return (id === 'this')
145 }
146
147 // 7.4 Comments
148
149 function skipWhitespace() {
150 while (index < length && isWhiteSpace(source.charCodeAt(index))) {
151 ++index;
152 }
153 }
154
155 function getIdentifier() {
156 var start, ch;
157
158 start = index++;
159 while (index < length) {
160 ch = source.charCodeAt(index);
161 if (isIdentifierPart(ch)) {
162 ++index;
163 } else {
164 break;
165 }
166 }
167
168 return source.slice(start, index);
169 }
170
171 function scanIdentifier() {
172 var start, id, type;
173
174 start = index;
175
176 id = getIdentifier();
177
178 // There is no keyword or literal with only one character.
179 // Thus, it must be an identifier.
180 if (id.length === 1) {
181 type = Token.Identifier;
182 } else if (isKeyword(id)) {
183 type = Token.Keyword;
184 } else if (id === 'null') {
185 type = Token.NullLiteral;
186 } else if (id === 'true' || id === 'false') {
187 type = Token.BooleanLiteral;
188 } else {
189 type = Token.Identifier;
190 }
191
192 return {
193 type: type,
194 value: id,
195 range: [start, index]
196 };
197 }
198
199
200 // 7.7 Punctuators
201
202 function scanPunctuator() {
203 var start = index,
204 code = source.charCodeAt(index),
205 code2,
206 ch1 = source[index],
207 ch2;
208
209 switch (code) {
210
211 // Check for most common single-character punctuators.
212 case 46: // . dot
213 case 40: // ( open bracket
214 case 41: // ) close bracket
215 case 59: // ; semicolon
216 case 44: // , comma
217 case 123: // { open curly brace
218 case 125: // } close curly brace
219 case 91: // [
220 case 93: // ]
221 case 58: // :
222 case 63: // ?
223 ++index;
224 return {
225 type: Token.Punctuator,
226 value: String.fromCharCode(code),
227 range: [start, index]
228 };
229
230 default:
231 code2 = source.charCodeAt(index + 1);
232
233 // '=' (char #61) marks an assignment or comparison operator.
234 if (code2 === 61) {
235 switch (code) {
236 case 37: // %
237 case 38: // &
238 case 42: // *:
239 case 43: // +
240 case 45: // -
241 case 47: // /
242 case 60: // <
243 case 62: // >
244 case 124: // |
245 index += 2;
246 return {
247 type: Token.Punctuator,
248 value: String.fromCharCode(code) + String.fromCharCode(code2 ),
249 range: [start, index]
250 };
251
252 case 33: // !
253 case 61: // =
254 index += 2;
255
256 // !== and ===
257 if (source.charCodeAt(index) === 61) {
258 ++index;
259 }
260 return {
261 type: Token.Punctuator,
262 value: source.slice(start, index),
263 range: [start, index]
264 };
265 default:
266 break;
267 }
268 }
269 break;
270 }
271
272 // Peek more characters.
273
274 ch2 = source[index + 1];
275
276 // Other 2-character punctuators: && ||
277
278 if (ch1 === ch2 && ('&|'.indexOf(ch1) >= 0)) {
279 index += 2;
280 return {
281 type: Token.Punctuator,
282 value: ch1 + ch2,
283 range: [start, index]
284 };
285 }
286
287 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
288 ++index;
289 return {
290 type: Token.Punctuator,
291 value: ch1,
292 range: [start, index]
293 };
294 }
295
296 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
297 }
298
299 // 7.8.3 Numeric Literals
300 function scanNumericLiteral() {
301 var number, start, ch;
302
303 ch = source[index];
304 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
305 'Numeric literal must start with a decimal digit or a decimal point');
306
307 start = index;
308 number = '';
309 if (ch !== '.') {
310 number = source[index++];
311 ch = source[index];
312
313 // Hex number starts with '0x'.
314 // Octal number starts with '0'.
315 if (number === '0') {
316 // decimal number starts with '0' such as '09' is illegal.
317 if (ch && isDecimalDigit(ch.charCodeAt(0))) {
318 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
319 }
320 }
321
322 while (isDecimalDigit(source.charCodeAt(index))) {
323 number += source[index++];
324 }
325 ch = source[index];
326 }
327
328 if (ch === '.') {
329 number += source[index++];
330 while (isDecimalDigit(source.charCodeAt(index))) {
331 number += source[index++];
332 }
333 ch = source[index];
334 }
335
336 if (ch === 'e' || ch === 'E') {
337 number += source[index++];
338
339 ch = source[index];
340 if (ch === '+' || ch === '-') {
341 number += source[index++];
342 }
343 if (isDecimalDigit(source.charCodeAt(index))) {
344 while (isDecimalDigit(source.charCodeAt(index))) {
345 number += source[index++];
346 }
347 } else {
348 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
349 }
350 }
351
352 if (isIdentifierStart(source.charCodeAt(index))) {
353 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
354 }
355
356 return {
357 type: Token.NumericLiteral,
358 value: parseFloat(number),
359 range: [start, index]
360 };
361 }
362
363 // 7.8.4 String Literals
364
365 function scanStringLiteral() {
366 var str = '', quote, start, ch, octal = false;
367
368 quote = source[index];
369 assert((quote === '\'' || quote === '"'),
370 'String literal must starts with a quote');
371
372 start = index;
373 ++index;
374
375 while (index < length) {
376 ch = source[index++];
377
378 if (ch === quote) {
379 quote = '';
380 break;
381 } else if (ch === '\\') {
382 ch = source[index++];
383 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
384 switch (ch) {
385 case 'n':
386 str += '\n';
387 break;
388 case 'r':
389 str += '\r';
390 break;
391 case 't':
392 str += '\t';
393 break;
394 case 'b':
395 str += '\b';
396 break;
397 case 'f':
398 str += '\f';
399 break;
400 case 'v':
401 str += '\x0B';
402 break;
403
404 default:
405 str += ch;
406 break;
407 }
408 } else {
409 if (ch === '\r' && source[index] === '\n') {
410 ++index;
411 }
412 }
413 } else if (isLineTerminator(ch.charCodeAt(0))) {
414 break;
415 } else {
416 str += ch;
417 }
418 }
419
420 if (quote !== '') {
421 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
422 }
423
424 return {
425 type: Token.StringLiteral,
426 value: str,
427 octal: octal,
428 range: [start, index]
429 };
430 }
431
432 function isIdentifierName(token) {
433 return token.type === Token.Identifier ||
434 token.type === Token.Keyword ||
435 token.type === Token.BooleanLiteral ||
436 token.type === Token.NullLiteral;
437 }
438
439 function advance() {
440 var ch;
441
442 skipWhitespace();
443
444 if (index >= length) {
445 return {
446 type: Token.EOF,
447 range: [index, index]
448 };
449 }
450
451 ch = source.charCodeAt(index);
452
453 // Very common: ( and ) and ;
454 if (ch === 40 || ch === 41 || ch === 58) {
455 return scanPunctuator();
456 }
457
458 // String literal starts with single quote (#39) or double quote (#34).
459 if (ch === 39 || ch === 34) {
460 return scanStringLiteral();
461 }
462
463 if (isIdentifierStart(ch)) {
464 return scanIdentifier();
465 }
466
467 // Dot (.) char #46 can also start a floating-point number, hence the need
468 // to check the next character.
469 if (ch === 46) {
470 if (isDecimalDigit(source.charCodeAt(index + 1))) {
471 return scanNumericLiteral();
472 }
473 return scanPunctuator();
474 }
475
476 if (isDecimalDigit(ch)) {
477 return scanNumericLiteral();
478 }
479
480 return scanPunctuator();
481 }
482
483 function lex() {
484 var token;
485
486 token = lookahead;
487 index = token.range[1];
488
489 lookahead = advance();
490
491 index = token.range[1];
492
493 return token;
494 }
495
496 function peek() {
497 var pos;
498
499 pos = index;
500 lookahead = advance();
501 index = pos;
502 }
503
504 // Throw an exception
505
506 function throwError(token, messageFormat) {
507 var error,
508 args = Array.prototype.slice.call(arguments, 2),
509 msg = messageFormat.replace(
510 /%(\d)/g,
511 function (whole, index) {
512 assert(index < args.length, 'Message reference must be in range' );
513 return args[index];
514 }
515 );
516
517 error = new Error(msg);
518 error.index = index;
519 error.description = msg;
520 throw error;
521 }
522
523 // Throw an exception because of the token.
524
525 function throwUnexpected(token) {
526 throwError(token, Messages.UnexpectedToken, token.value);
527 }
528
529 // Expect the next token to match the specified punctuator.
530 // If not, an exception will be thrown.
531
532 function expect(value) {
533 var token = lex();
534 if (token.type !== Token.Punctuator || token.value !== value) {
535 throwUnexpected(token);
536 }
537 }
538
539 // Return true if the next token matches the specified punctuator.
540
541 function match(value) {
542 return lookahead.type === Token.Punctuator && lookahead.value === value;
543 }
544
545 // Return true if the next token matches the specified keyword
546
547 function matchKeyword(keyword) {
548 return lookahead.type === Token.Keyword && lookahead.value === keyword;
549 }
550
551 function consumeSemicolon() {
552 // Catch the very common case first: immediately a semicolon (char #59).
553 if (source.charCodeAt(index) === 59) {
554 lex();
555 return;
556 }
557
558 skipWhitespace();
559
560 if (match(';')) {
561 lex();
562 return;
563 }
564
565 if (lookahead.type !== Token.EOF && !match('}')) {
566 throwUnexpected(lookahead);
567 }
568 }
569
570 // 11.1.4 Array Initialiser
571
572 function parseArrayInitialiser() {
573 var elements = [];
574
575 expect('[');
576
577 while (!match(']')) {
578 if (match(',')) {
579 lex();
580 elements.push(null);
581 } else {
582 elements.push(parseExpression());
583
584 if (!match(']')) {
585 expect(',');
586 }
587 }
588 }
589
590 expect(']');
591
592 return delegate.createArrayExpression(elements);
593 }
594
595 // 11.1.5 Object Initialiser
596
597 function parseObjectPropertyKey() {
598 var token;
599
600 skipWhitespace();
601 token = lex();
602
603 // Note: This function is called only from parseObjectProperty(), where
604 // EOF and Punctuator tokens are already filtered out.
605 if (token.type === Token.StringLiteral || token.type === Token.NumericLitera l) {
606 return delegate.createLiteral(token);
607 }
608
609 return delegate.createIdentifier(token.value);
610 }
611
612 function parseObjectProperty() {
613 var token, key;
614
615 token = lookahead;
616 skipWhitespace();
617
618 if (token.type === Token.EOF || token.type === Token.Punctuator) {
619 throwUnexpected(token);
620 }
621
622 key = parseObjectPropertyKey();
623 expect(':');
624 return delegate.createProperty('init', key, parseExpression());
625 }
626
627 function parseObjectInitialiser() {
628 var properties = [];
629
630 expect('{');
631
632 while (!match('}')) {
633 properties.push(parseObjectProperty());
634
635 if (!match('}')) {
636 expect(',');
637 }
638 }
639
640 expect('}');
641
642 return delegate.createObjectExpression(properties);
643 }
644
645 // 11.1.6 The Grouping Operator
646
647 function parseGroupExpression() {
648 var expr;
649
650 expect('(');
651
652 expr = parseExpression();
653
654 expect(')');
655
656 return expr;
657 }
658
659
660 // 11.1 Primary Expressions
661
662 function parsePrimaryExpression() {
663 var type, token, expr;
664
665 if (match('(')) {
666 return parseGroupExpression();
667 }
668
669 type = lookahead.type;
670
671 if (type === Token.Identifier) {
672 expr = delegate.createIdentifier(lex().value);
673 } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
674 expr = delegate.createLiteral(lex());
675 } else if (type === Token.Keyword) {
676 if (matchKeyword('this')) {
677 lex();
678 expr = delegate.createThisExpression();
679 }
680 } else if (type === Token.BooleanLiteral) {
681 token = lex();
682 token.value = (token.value === 'true');
683 expr = delegate.createLiteral(token);
684 } else if (type === Token.NullLiteral) {
685 token = lex();
686 token.value = null;
687 expr = delegate.createLiteral(token);
688 } else if (match('[')) {
689 expr = parseArrayInitialiser();
690 } else if (match('{')) {
691 expr = parseObjectInitialiser();
692 }
693
694 if (expr) {
695 return expr;
696 }
697
698 throwUnexpected(lex());
699 }
700
701 // 11.2 Left-Hand-Side Expressions
702
703 function parseArguments() {
704 var args = [];
705
706 expect('(');
707
708 if (!match(')')) {
709 while (index < length) {
710 args.push(parseExpression());
711 if (match(')')) {
712 break;
713 }
714 expect(',');
715 }
716 }
717
718 expect(')');
719
720 return args;
721 }
722
723 function parseNonComputedProperty() {
724 var token;
725
726 token = lex();
727
728 if (!isIdentifierName(token)) {
729 throwUnexpected(token);
730 }
731
732 return delegate.createIdentifier(token.value);
733 }
734
735 function parseNonComputedMember() {
736 expect('.');
737
738 return parseNonComputedProperty();
739 }
740
741 function parseComputedMember() {
742 var expr;
743
744 expect('[');
745
746 expr = parseExpression();
747
748 expect(']');
749
750 return expr;
751 }
752
753 function parseLeftHandSideExpression() {
754 var expr, args, property;
755
756 expr = parsePrimaryExpression();
757
758 while (true) {
759 if (match('[')) {
760 property = parseComputedMember();
761 expr = delegate.createMemberExpression('[', expr, property);
762 } else if (match('.')) {
763 property = parseNonComputedMember();
764 expr = delegate.createMemberExpression('.', expr, property);
765 } else if (match('(')) {
766 args = parseArguments();
767 expr = delegate.createCallExpression(expr, args);
768 } else {
769 break;
770 }
771 }
772
773 return expr;
774 }
775
776 // 11.3 Postfix Expressions
777
778 var parsePostfixExpression = parseLeftHandSideExpression;
779
780 // 11.4 Unary Operators
781
782 function parseUnaryExpression() {
783 var token, expr;
784
785 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
786 expr = parsePostfixExpression();
787 } else if (match('+') || match('-') || match('!')) {
788 token = lex();
789 expr = parseUnaryExpression();
790 expr = delegate.createUnaryExpression(token.value, expr);
791 } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('t ypeof')) {
792 throwError({}, Messages.UnexpectedToken);
793 } else {
794 expr = parsePostfixExpression();
795 }
796
797 return expr;
798 }
799
800 function binaryPrecedence(token) {
801 var prec = 0;
802
803 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
804 return 0;
805 }
806
807 switch (token.value) {
808 case '||':
809 prec = 1;
810 break;
811
812 case '&&':
813 prec = 2;
814 break;
815
816 case '==':
817 case '!=':
818 case '===':
819 case '!==':
820 prec = 6;
821 break;
822
823 case '<':
824 case '>':
825 case '<=':
826 case '>=':
827 case 'instanceof':
828 prec = 7;
829 break;
830
831 case 'in':
832 prec = 7;
833 break;
834
835 case '+':
836 case '-':
837 prec = 9;
838 break;
839
840 case '*':
841 case '/':
842 case '%':
843 prec = 11;
844 break;
845
846 default:
847 break;
848 }
849
850 return prec;
851 }
852
853 // 11.5 Multiplicative Operators
854 // 11.6 Additive Operators
855 // 11.7 Bitwise Shift Operators
856 // 11.8 Relational Operators
857 // 11.9 Equality Operators
858 // 11.10 Binary Bitwise Operators
859 // 11.11 Binary Logical Operators
860
861 function parseBinaryExpression() {
862 var expr, token, prec, stack, right, operator, left, i;
863
864 left = parseUnaryExpression();
865
866 token = lookahead;
867 prec = binaryPrecedence(token);
868 if (prec === 0) {
869 return left;
870 }
871 token.prec = prec;
872 lex();
873
874 right = parseUnaryExpression();
875
876 stack = [left, token, right];
877
878 while ((prec = binaryPrecedence(lookahead)) > 0) {
879
880 // Reduce: make a binary expression from the three topmost entries.
881 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
882 right = stack.pop();
883 operator = stack.pop().value;
884 left = stack.pop();
885 expr = delegate.createBinaryExpression(operator, left, right);
886 stack.push(expr);
887 }
888
889 // Shift.
890 token = lex();
891 token.prec = prec;
892 stack.push(token);
893 expr = parseUnaryExpression();
894 stack.push(expr);
895 }
896
897 // Final reduce to clean-up the stack.
898 i = stack.length - 1;
899 expr = stack[i];
900 while (i > 1) {
901 expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
902 i -= 2;
903 }
904
905 return expr;
906 }
907
908
909 // 11.12 Conditional Operator
910
911 function parseConditionalExpression() {
912 var expr, consequent, alternate;
913
914 expr = parseBinaryExpression();
915
916 if (match('?')) {
917 lex();
918 consequent = parseConditionalExpression();
919 expect(':');
920 alternate = parseConditionalExpression();
921
922 expr = delegate.createConditionalExpression(expr, consequent, alternate) ;
923 }
924
925 return expr;
926 }
927
928 // Simplification since we do not support AssignmentExpression.
929 var parseExpression = parseConditionalExpression;
930
931 // Polymer Syntax extensions
932
933 // Filter ::
934 // Identifier
935 // Identifier "(" ")"
936 // Identifier "(" FilterArguments ")"
937
938 function parseFilter() {
939 var identifier, args;
940
941 identifier = lex();
942
943 if (identifier.type !== Token.Identifier) {
944 throwUnexpected(identifier);
945 }
946
947 args = match('(') ? parseArguments() : [];
948
949 return delegate.createFilter(identifier.value, args);
950 }
951
952 // Filters ::
953 // "|" Filter
954 // Filters "|" Filter
955
956 function parseFilters() {
957 while (match('|')) {
958 lex();
959 parseFilter();
960 }
961 }
962
963 // TopLevel ::
964 // LabelledExpressions
965 // AsExpression
966 // InExpression
967 // FilterExpression
968
969 // AsExpression ::
970 // FilterExpression as Identifier
971
972 // InExpression ::
973 // Identifier, Identifier in FilterExpression
974 // Identifier in FilterExpression
975
976 // FilterExpression ::
977 // Expression
978 // Expression Filters
979
980 function parseTopLevel() {
981 skipWhitespace();
982 peek();
983
984 var expr = parseExpression();
985 if (expr) {
986 if (lookahead.value === ',' || lookahead.value == 'in' &&
987 expr.type === Syntax.Identifier) {
988 parseInExpression(expr);
989 } else {
990 parseFilters();
991 if (lookahead.value === 'as') {
992 parseAsExpression(expr);
993 } else {
994 delegate.createTopLevel(expr);
995 }
996 }
997 }
998
999 if (lookahead.type !== Token.EOF) {
1000 throwUnexpected(lookahead);
1001 }
1002 }
1003
1004 function parseAsExpression(expr) {
1005 lex(); // as
1006 var identifier = lex().value;
1007 delegate.createAsExpression(expr, identifier);
1008 }
1009
1010 function parseInExpression(identifier) {
1011 var indexName;
1012 if (lookahead.value === ',') {
1013 lex();
1014 if (lookahead.type !== Token.Identifier)
1015 throwUnexpected(lookahead);
1016 indexName = lex().value;
1017 }
1018
1019 lex(); // in
1020 var expr = parseExpression();
1021 parseFilters();
1022 delegate.createInExpression(identifier.name, indexName, expr);
1023 }
1024
1025 function parse(code, inDelegate) {
1026 delegate = inDelegate;
1027 source = code;
1028 index = 0;
1029 length = source.length;
1030 lookahead = null;
1031 state = {
1032 labelSet: {}
1033 };
1034
1035 return parseTopLevel();
1036 }
1037
1038 module.exports = {
1039 parse: parse
1040 };
1041
1042 </script>
OLDNEW
« sky/examples/city-list/city-list.sky ('K') | « sky/framework/sky-element/sky-element.sky ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698