3 # Copyright 2014, 2015 Piotr Dabkowski
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the 'Software'),
7 # to deal in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 # the Software, and to permit persons to whom the Software is furnished to do so, subject
10 # to the following conditions:
12 # The above copyright notice and this permission notice shall be included in all copies or
13 # substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
19 # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
20 from __future__ import unicode_literals
21 from .pyjsparserdata import *
22 from .std_nodes import *
23 from pprint import pprint
26 __all__ = ['PyJsParser', 'parse', 'ENABLE_JS2PY_ERRORS', 'ENABLE_PYIMPORT', 'JsSyntaxError']
27 REGEXP_SPECIAL_SINGLE = ('\\', '^', '$', '*', '+', '?', '.', '[', ']', '(', ')', '{', '{', '|', '-')
28 ENABLE_PYIMPORT = False
29 ENABLE_JS2PY_ERRORS = False
31 PY3 = sys.version_info >= (3,0)
39 ESPRIMA_VERSION = '2.2.0'
41 # Small naming convention changes
54 parser.parse('var JavaScriptCode = 5.1')
61 pprint(self.parse(code))
65 self.sourceType = None
69 self.hasLineTerminator = None
71 self.lastLineNumber = None
72 self.lastLineStart = None
73 self.startIndex = None
74 self.startLineNumber = None
75 self.startLineStart = None
80 self.isBindingElement = None
81 self.isAssignmentTarget = None
82 self.firstCoverInitializedNameError = None
86 def skipSingleLineComment(self, offset):
87 start = self.index - offset;
88 while self.index < self.length:
89 ch = self.source[self.index];
91 if isLineTerminator(ch):
92 if (ord(ch) == 13 and ord(self.source[self.index]) == 10):
95 self.hasLineTerminator = True
96 self.lineStart = self.index
99 def skipMultiLineComment(self):
100 while self.index < self.length:
101 ch = ord(self.source[self.index])
102 if isLineTerminator(ch):
103 if (ch == 0x0D and ord(self.source[self.index + 1]) == 0x0A):
107 self.hasLineTerminator = True
108 self.lineStart = self.index
110 # Block comment ends with '*/'.
111 if ord(self.source[self.index + 1]) == 0x2F:
117 self.tolerateUnexpectedToken()
119 def skipComment(self):
120 self.hasLineTerminator = False
121 start = (self.index == 0)
122 while self.index < self.length:
123 ch = ord(self.source[self.index])
126 elif isLineTerminator(ch):
127 self.hasLineTerminator = True
129 if (ch == 0x0D and ord(self.source[self.index]) == 0x0A):
132 self.lineStart = self.index
134 elif (ch == 0x2F): # U+002F is '/'
135 ch = ord(self.source[self.index + 1])
138 self.skipSingleLineComment(2)
140 elif (ch == 0x2A): # U+002A is '*'
142 self.skipMultiLineComment()
145 elif (start and ch == 0x2D): # U+002D is '-'
147 if (ord(self.source[self.index + 1]) == 0x2D) and (ord(self.source[self.index + 2]) == 0x3E):
148 # '-->' is a single-line comment
150 self.skipSingleLineComment(3)
153 elif (ch == 0x3C): # U+003C is '<'
154 if self.source[self.index + 1: self.index + 4] == '!--':
157 self.skipSingleLineComment(4)
163 def scanHexEscape(self, prefix):
165 leng = 4 if (prefix == 'u') else 2
166 for i in xrange(leng):
167 if self.index < self.length and isHexDigit(self.source[self.index]):
168 ch = self.source[self.index]
170 code = code * 16 + HEX_CONV[ch]
175 def scanUnicodeCodePointEscape(self):
176 ch = self.source[self.index]
178 # At least, one hex digit is required.
180 self.throwUnexpectedToken()
181 while (self.index < self.length):
182 ch = self.source[self.index]
184 if not isHexDigit(ch):
186 code = code * 16 + HEX_CONV[ch]
187 if code > 0x10FFFF or ch != '}':
188 self.throwUnexpectedToken()
192 cu1 = ((code - 0x10000) >> 10) + 0xD800;
193 cu2 = ((code - 0x10000) & 1023) + 0xDC00;
194 return unichr(cu1) + unichr(cu2)
196 def ccode(self, offset=0):
197 return ord(self.source[self.index + offset])
199 def log_err_case(self):
202 print('INDEX', self.index)
203 print(self.source[self.index - 10:self.index + 10])
207 return None if loc >= self.length else self.source[loc]
209 def substr(self, le, offset=0):
210 return self.source[self.index + offset:self.index + offset + le]
212 def getEscapedIdentifier(self):
213 d = self.source[self.index]
216 # '\u' (U+005C, U+0075) denotes an escaped character.
218 if (ord(self.source[self.index]) != 0x75):
219 self.throwUnexpectedToken()
221 ch = self.scanHexEscape('u')
222 if not ch or ch == '\\' or not isIdentifierStart(ch[0]):
223 self.throwUnexpectedToken()
225 while (self.index < self.length):
227 if not isIdentifierPart(ch):
232 # '\u' (U+005C, U+0075) denotes an escaped character.
235 if (self.ccode() != 0x75):
236 self.throwUnexpectedToken()
238 ch = self.scanHexEscape('u');
239 if (not ch or ch == '\\' or not isIdentifierPart(ch[0])):
240 self.throwUnexpectedToken()
244 def getIdentifier(self):
247 while (self.index < self.length):
250 # Blackslash (U+005C) marks Unicode escape sequence.
252 return self.getEscapedIdentifier()
253 if (isIdentifierPart(ch)):
257 return self.source[start: self.index]
259 def scanIdentifier(self):
262 # Backslash (U+005C) starts an escaped character.
263 d = self.getEscapedIdentifier() if (self.ccode() == 0x5C) else self.getIdentifier()
265 # There is no keyword or literal with only one character.
266 # Thus, it must be an identifier.
268 type = Token.Identifier
272 type = Token.NullLiteral
273 elif (i == 'true' or d == 'false'):
274 type = Token.BooleanLiteral
276 type = Token.Identifier;
280 'lineNumber': self.lineNumber,
281 'lineStart': self.lineStart,
288 def scanPunctuator(self):
290 'type': Token.Punctuator,
292 'lineNumber': self.lineNumber,
293 'lineStart': self.lineStart,
297 # Check for most common single-character punctuators.
298 st = self.source[self.index]
300 self.state['curlyStack'].append('{')
304 self.state['curlyStack'].pop()
305 elif st in ('.', '(', ')', ';', ',', '[', ']', ':', '?', '~'):
308 # 4-character punctuator.
313 # 3-character punctuators.
315 if st in ('===', '!==', '>>>', '<<=', '>>='):
318 # 2-character punctuators.
320 if st in ('&&', '||', '==', '!=', '+=', '-=', '*=', '/=', '++', '--', '<<', '>>', '&=', '|=', '^=',
321 '%=', '<=', '>=', '=>'):
324 # 1-character punctuators.
325 st = self.source[self.index]
326 if st in ('<', '>', '=', '!', '+', '-', '*', '%', '&', '|', '^', '/'):
328 if self.index == token['start']:
329 self.throwUnexpectedToken()
330 token['end'] = self.index;
334 # 7.8.3 Numeric Literals
336 def scanHexLiteral(self, start):
338 while (self.index < self.length):
339 if (not isHexDigit(self.source[self.index])):
341 number += self.source[self.index]
344 self.throwUnexpectedToken()
345 if isIdentifierStart(self.ccode()):
346 self.throwUnexpectedToken()
348 'type': Token.NumericLiteral,
349 'value': int(number, 16),
350 'lineNumber': self.lineNumber,
351 'lineStart': self.lineStart,
355 def scanBinaryLiteral(self, start):
357 while (self.index < self.length):
358 ch = self.source[self.index]
359 if (ch != '0' and ch != '1'):
361 number += self.source[self.index]
366 self.throwUnexpectedToken()
367 if (self.index < self.length):
368 ch = self.source[self.index]
369 # istanbul ignore else
370 if (isIdentifierStart(ch) or isDecimalDigit(ch)):
371 self.throwUnexpectedToken();
373 'type': Token.NumericLiteral,
374 'value': int(number, 2),
375 'lineNumber': self.lineNumber,
376 'lineStart': self.lineStart,
380 def scanOctalLiteral(self, prefix, start):
381 if isOctalDigit(prefix):
383 number = '0' + self.source[self.index]
389 while (self.index < self.length):
390 if (not isOctalDigit(self.source[self.index])):
392 number += self.source[self.index]
394 if (not octal and not number):
396 self.throwUnexpectedToken()
397 if (isIdentifierStart(self.ccode()) or isDecimalDigit(self.ccode())):
398 self.throwUnexpectedToken()
400 'type': Token.NumericLiteral,
401 'value': int(number, 8),
402 'lineNumber': self.lineNumber,
403 'lineStart': self.lineStart,
407 def octalToDecimal(self, ch):
408 # \0 is not octal escape sequence
412 if (self.index < self.length and isOctalDigit(self.source[self.index])):
414 code = code * 8 + int(self.source[self.index], 8)
417 # 3 digits are only allowed when string starts
419 if (ch in '0123' and self.index < self.length and isOctalDigit(self.source[self.index])):
420 code = code * 8 + int((self.source[self.index]), 8)
426 def isImplicitOctalLiteral(self):
427 # Implicit octal, unless there is a non-octal digit.
428 # (Annex B.1.1 on Numeric Literals)
429 for i in xrange(self.index + 1, self.length):
431 if (ch == '8' or ch == '9'):
433 if (not isOctalDigit(ch)):
437 def scanNumericLiteral(self):
438 ch = self.source[self.index]
439 assert isDecimalDigit(ch) or (ch == '.'), 'Numeric literal must start with a decimal digit or a decimal point'
443 number = self.source[self.index]
445 ch = self.source[self.index]
446 # Hex number starts with '0x'.
447 # Octal number starts with '0'.
448 # Octal number in ES6 starts with '0o'.
449 # Binary number in ES6 starts with '0b'.
451 if (ch == 'x' or ch == 'X'):
453 return self.scanHexLiteral(start);
454 if (ch == 'b' or ch == 'B'):
456 return self.scanBinaryLiteral(start)
457 if (ch == 'o' or ch == 'O'):
458 return self.scanOctalLiteral(ch, start)
459 if (isOctalDigit(ch)):
460 if (self.isImplicitOctalLiteral()):
461 return self.scanOctalLiteral(ch, start);
462 while (isDecimalDigit(self.ccode())):
463 number += self.source[self.index]
465 ch = self.source[self.index];
467 number += self.source[self.index]
469 while (isDecimalDigit(self.source[self.index])):
470 number += self.source[self.index]
472 ch = self.source[self.index]
473 if (ch == 'e' or ch == 'E'):
474 number += self.source[self.index]
476 ch = self.source[self.index]
477 if (ch == '+' or ch == '-'):
478 number += self.source[self.index]
480 if (isDecimalDigit(self.source[self.index])):
481 while (isDecimalDigit(self.source[self.index])):
482 number += self.source[self.index]
485 self.throwUnexpectedToken()
486 if (isIdentifierStart(self.source[self.index])):
487 self.throwUnexpectedToken();
489 'type': Token.NumericLiteral,
490 'value': float(number),
491 'lineNumber': self.lineNumber,
492 'lineStart': self.lineStart,
496 # 7.8.4 String Literals
498 def _interpret_regexp(self, string, flags):
499 '''Perform sctring escape - for regexp literals'''
501 self.length = len(string)
508 while (self.index < self.length):
509 template = '[%s]' if not inside_square else '%s'
510 ch = self.source[self.index]
513 ch = self.source[self.index]
515 if (not isLineTerminator(ch)):
517 digs = self.source[self.index:self.index + 4]
518 if len(digs) == 4 and all(isHexDigit(d) for d in digs):
519 st += template % unichr(int(digs, 16))
524 digs = self.source[self.index:self.index + 2]
525 if len(digs) == 2 and all(isHexDigit(d) for d in digs):
526 st += template % unichr(int(digs, 16))
530 # special meaning - single char.
544 # unescape special single characters like . so that they are interpreted literally
545 elif ch in REGEXP_SPECIAL_SINGLE:
562 st += template % u' \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff'
564 st += template % u'\u0000-\u0008\u000e-\u001f\u0021-\u009f\u00a1-\u167f\u1681-\u180d\u180f-\u1fff\u200b-\u2027\u202a-\u202e\u2030-\u205e\u2060-\u2fff\u3001-\ufefe\uff00-\uffff'
566 if isDecimalDigit(ch):
568 while self.index < self.length and isDecimalDigit(self.source[self.index]):
569 num += self.source[self.index]
574 st += ch # DONT ESCAPE!!!
577 if (ch == '\r' and self.source[self.index] == '\n'):
579 self.lineStart = self.index
584 inside_square = False
586 # print string, 'was transformed to', st
589 def scanStringLiteral(self):
593 quote = self.source[self.index]
594 assert quote == '\'' or quote == '"', 'String literal must starts with a quote'
598 while (self.index < self.length):
599 ch = self.source[self.index]
605 ch = self.source[self.index]
607 if (not isLineTerminator(ch)):
609 if (self.source[self.index] == '{'):
611 st += self.scanUnicodeCodePointEscape()
613 unescaped = self.scanHexEscape(ch)
615 self.throwUnexpectedToken() # with throw I don't know whats the difference
630 # self.throwUnexpectedToken() # again with throw....
633 octToDec = self.octalToDecimal(ch)
634 octal = octToDec.get('octal') or octal
635 st += unichr(octToDec['code'])
640 if (ch == '\r' and self.source[self.index] == '\n'):
642 self.lineStart = self.index
643 elif isLineTerminator(ch):
648 self.throwUnexpectedToken()
650 'type': Token.StringLiteral,
653 'lineNumber': self.lineNumber,
654 'lineStart': self.startLineStart,
658 def scanTemplate(self):
663 head = (self.source[self.index] == '`')
668 while (self.index < self.length):
669 ch = self.source[self.index]
677 if (self.source[self.index] == '{'):
678 self.state['curlyStack'].append('${')
684 ch = self.source[self.index]
686 if (not isLineTerminator(ch)):
694 if (self.source[self.index] == '{'):
696 cooked += self.scanUnicodeCodePointEscape()
699 unescaped = self.scanHexEscape(ch)
713 if isDecimalDigit(self.ccode()):
714 # Illegal: \01 \02 and so on
715 self.throwError(Messages.TemplateOctalLiteral)
717 elif (isOctalDigit(ch)):
719 self.throwError(Messages.TemplateOctalLiteral)
724 if (ch == '\r' and self.source[self.index] == '\n'):
726 self.lineStart = self.index
727 elif (isLineTerminator(ch)):
729 if (ch == '\r' and self.source[self.index] == '\n'):
731 self.lineStart = self.index
736 self.throwUnexpectedToken()
739 self.state['curlyStack'].pop();
742 'type': Token.Template,
745 'raw': self.source[start + 1:self.index - rawOffset]},
748 'lineNumber': self.lineNumber,
749 'lineStart': self.lineStart,
753 def testRegExp(self, pattern, flags):
754 # todo: you should return python regexp object
755 return (pattern, flags)
757 def scanRegExpBody(self):
758 ch = self.source[self.index]
759 assert ch == '/', 'Regular expression literal must start with a slash'
765 while (self.index < self.length):
766 ch = self.source[self.index]
770 ch = self.source[self.index]
773 if (isLineTerminator(ch)):
774 self.throwUnexpectedToken(None, Messages.UnterminatedRegExp)
776 elif (isLineTerminator(ch)):
777 self.throwUnexpectedToken(None, Messages.UnterminatedRegExp)
788 self.throwUnexpectedToken(None, Messages.UnterminatedRegExp)
790 # Exclude leading and trailing slash.
796 def scanRegExpFlags(self):
799 while (self.index < self.length):
800 ch = self.source[self.index]
801 if (not isIdentifierPart(ch)):
804 if (ch == '\\' and self.index < self.length):
805 ch = self.source[self.index]
809 ch = self.scanHexEscape('u')
813 while restore < self.index:
814 st += self.source[restore]
820 self.tolerateUnexpectedToken()
823 self.tolerateUnexpectedToken()
831 def scanRegExp(self):
833 self.lookahead = None
837 body = self.scanRegExpBody()
838 flags = self.scanRegExpFlags()
839 value = self.testRegExp(body['value'], flags['value'])
842 'literal': body['literal'] + flags['literal'],
845 'pattern': body['value'],
846 'flags': flags['value']
851 def collectRegex(self):
853 return self.scanRegExp()
855 def isIdentifierName(self, token):
856 return token['type'] in (1, 3, 4, 5)
858 # def advanceSlash(self): ???
861 if (self.index >= self.length):
864 'lineNumber': self.lineNumber,
865 'lineStart': self.lineStart,
870 if isIdentifierStart(ch):
871 token = self.scanIdentifier()
872 if (self.strict and isStrictModeReservedWord(token['value'])):
873 token['type'] = Token.Keyword
875 # Very common: ( and ) and ;
876 if (ch == 0x28 or ch == 0x29 or ch == 0x3B):
877 return self.scanPunctuator()
879 # String literal starts with single quote (U+0027) or double quote (U+0022).
880 if (ch == 0x27 or ch == 0x22):
881 return self.scanStringLiteral()
883 # Dot (.) U+002E can also start a floating-point number, hence the need
884 # to check the next character.
886 if (isDecimalDigit(self.ccode(1))):
887 return self.scanNumericLiteral()
888 return self.scanPunctuator();
890 if (isDecimalDigit(ch)):
891 return self.scanNumericLiteral()
893 # Slash (/) U+002F can also start a regex.
894 # if (extra.tokenize && ch == 0x2F):
895 # return advanceSlash();
897 # Template literals start with ` (U+0060) for template head
898 # or } (U+007D) for template middle or template tail.
899 if (ch == 0x60 or (ch == 0x7D and self.state['curlyStack'][len(self.state['curlyStack']) - 1] == '${')):
900 return self.scanTemplate()
901 return self.scanPunctuator();
903 # def collectToken(self):
906 # 'line': self.lineNumber,
907 # 'column': self.index - self.lineStart}}
909 # token = self.advance()
912 # 'line': self.lineNumber,
913 # 'column': self.index - self.lineStart}
914 # if (token['type'] != Token.EOF):
915 # value = self.source[token['start']: token['end']]
917 # 'type': TokenName[token['type']],
919 # 'range': [token['start'], token['end']],
921 # if (token.get('regex')):
923 # 'pattern': token['regex']['pattern'],
924 # 'flags': token['regex']['flags']}
925 # self.extra['tokens'].append(entry)
932 self.lastIndex = self.index
933 self.lastLineNumber = self.lineNumber
934 self.lastLineStart = self.lineStart
938 token = self.lookahead
940 self.startIndex = self.index
941 self.startLineNumber = self.lineNumber
942 self.startLineStart = self.lineStart
944 self.lookahead = self.advance()
945 self.scanning = False
953 self.lastIndex = self.index
954 self.lastLineNumber = self.lineNumber
955 self.lastLineStart = self.lineStart
957 self.startIndex = self.index
958 self.startLineNumber = self.lineNumber
959 self.startLineStart = self.lineStart
961 self.lookahead = self.advance()
962 self.scanning = False
964 def createError(self, line, pos, description):
965 global ENABLE_PYIMPORT
966 if ENABLE_JS2PY_ERRORS:
967 old_pyimport = ENABLE_PYIMPORT # ENABLE_PYIMPORT will be affected by js2py import
970 from js2py.base import ERRORS, Js, JsToPyException
972 raise Exception("ENABLE_JS2PY_ERRORS was set to True, but Js2Py was not found!")
973 ENABLE_PYIMPORT = old_pyimport
974 error = ERRORS['SyntaxError']('Line ' + unicode(line) + ': ' + unicode(description))
975 error.put('index', Js(pos))
976 error.put('lineNumber', Js(line))
977 error.put('column', Js(pos - (self.lineStart if self.scanning else self.lastLineStart) + 1))
978 error.put('description', Js(description))
979 return JsToPyException(error)
981 return JsSyntaxError('Line ' + unicode(line) + ': ' + unicode(description))
986 def throwError(self, messageFormat, *args):
987 msg = messageFormat % tuple(unicode(e) for e in args)
988 raise self.createError(self.lastLineNumber, self.lastIndex, msg);
990 def tolerateError(self, messageFormat, *args):
991 return self.throwError(messageFormat, *args)
993 # Throw an exception because of the token.
995 def unexpectedTokenError(self, token={}, message=''):
996 msg = message or Messages.UnexpectedToken
1000 if typ == Token.EOF:
1001 msg = Messages.UnexpectedEOS
1002 elif (typ == Token.Identifier):
1003 msg = Messages.UnexpectedIdentifier
1004 elif (typ == Token.NumericLiteral):
1005 msg = Messages.UnexpectedNumber
1006 elif (typ == Token.StringLiteral):
1007 msg = Messages.UnexpectedString
1008 elif (typ == Token.Template):
1009 msg = Messages.UnexpectedTemplate
1011 msg = Messages.UnexpectedToken;
1012 if (typ == Token.Keyword):
1013 if (isFutureReservedWord(token['value'])):
1014 msg = Messages.UnexpectedReserved
1015 elif (self.strict and isStrictModeReservedWord(token['value'])):
1016 msg = Messages.StrictReservedWord
1017 value = token['value']['raw'] if (typ == Token.Template) else token.get('value')
1020 msg = msg.replace('%s', unicode(value))
1022 return (self.createError(token['lineNumber'], token['start'], msg) if (token and token.get('lineNumber')) else
1023 self.createError(self.lineNumber if self.scanning else self.lastLineNumber,
1024 self.index if self.scanning else self.lastIndex, msg))
1026 def throwUnexpectedToken(self, token={}, message=''):
1027 raise self.unexpectedTokenError(token, message)
1029 def tolerateUnexpectedToken(self, token={}, message=''):
1030 self.throwUnexpectedToken(token, message)
1032 # Expect the next token to match the specified punctuator.
1033 # If not, an exception will be thrown.
1035 def expect(self, value):
1037 if (token['type'] != Token.Punctuator or token['value'] != value):
1038 self.throwUnexpectedToken(token)
1041 # * @name expectCommaSeparator
1042 # * @description Quietly expect a comma when in tolerant mode, otherwise delegates
1043 # * to <code>expect(value)</code>
1046 def expectCommaSeparator(self):
1049 # Expect the next token to match the specified keyword.
1050 # If not, an exception will be thrown.
1052 def expectKeyword(self, keyword):
1054 if (token['type'] != Token.Keyword or token['value'] != keyword):
1055 self.throwUnexpectedToken(token)
1057 # Return true if the next token matches the specified punctuator.
1059 def match(self, value):
1060 return self.lookahead['type'] == Token.Punctuator and self.lookahead['value'] == value
1062 # Return true if the next token matches the specified keyword
1064 def matchKeyword(self, keyword):
1065 return self.lookahead['type'] == Token.Keyword and self.lookahead['value'] == keyword
1067 # Return true if the next token matches the specified contextual keyword
1068 # (where an identifier is sometimes a keyword depending on the context)
1070 def matchContextualKeyword(self, keyword):
1071 return self.lookahead['type'] == Token.Identifier and self.lookahead['value'] == keyword
1073 # Return true if the next token is an assignment operator
1075 def matchAssign(self):
1076 if (self.lookahead['type'] != Token.Punctuator):
1078 op = self.lookahead['value']
1079 return op in ('=', '*=', '/=', '%=', '+=', '-=', '<<=', '>>=', '>>>=', '&=', '^=', '|=')
1081 def consumeSemicolon(self):
1082 # Catch the very common case first: immediately a semicolon (U+003B).
1084 if (self.at(self.startIndex) == ';' or self.match(';')):
1088 if (self.hasLineTerminator):
1091 # TODO: FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
1092 self.lastIndex = self.startIndex
1093 self.lastLineNumber = self.startLineNumber
1094 self.lastLineStart = self.startLineStart
1096 if (self.lookahead['type'] != Token.EOF and not self.match('}')):
1097 self.throwUnexpectedToken(self.lookahead)
1099 # // Cover grammar support.
1101 # // When an assignment expression position starts with an left parenthesis, the determination of the type
1102 # // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
1103 # // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
1105 # // There are three productions that can be parsed in a parentheses pair that needs to be determined
1106 # // after the outermost pair is closed. They are:
1108 # // 1. AssignmentExpression
1109 # // 2. BindingElements
1110 # // 3. AssignmentTargets
1112 # // In order to avoid exponential backtracking, we use two flags to denote if the production can be
1113 # // binding element or assignment target.
1115 # // The three productions have the relationship:
1117 # // BindingElements <= AssignmentTargets <= AssignmentExpression
1119 # // with a single exception that CoverInitializedName when used directly in an Expression, generates
1120 # // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
1121 # // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
1123 # // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
1124 # // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
1125 # // the CoverInitializedName check is conducted.
1127 # // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
1128 # // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
1129 # // pattern. The CoverInitializedName check is deferred.
1131 def isolateCoverGrammar(self, parser):
1132 oldIsBindingElement = self.isBindingElement
1133 oldIsAssignmentTarget = self.isAssignmentTarget
1134 oldFirstCoverInitializedNameError = self.firstCoverInitializedNameError
1135 self.isBindingElement = true
1136 self.isAssignmentTarget = true
1137 self.firstCoverInitializedNameError = null
1139 if (self.firstCoverInitializedNameError != null):
1140 self.throwUnexpectedToken(self.firstCoverInitializedNameError)
1141 self.isBindingElement = oldIsBindingElement
1142 self.isAssignmentTarget = oldIsAssignmentTarget
1143 self.firstCoverInitializedNameError = oldFirstCoverInitializedNameError
1146 def inheritCoverGrammar(self, parser):
1147 oldIsBindingElement = self.isBindingElement
1148 oldIsAssignmentTarget = self.isAssignmentTarget
1149 oldFirstCoverInitializedNameError = self.firstCoverInitializedNameError
1150 self.isBindingElement = true
1151 self.isAssignmentTarget = true
1152 self.firstCoverInitializedNameError = null
1154 self.isBindingElement = self.isBindingElement and oldIsBindingElement
1155 self.isAssignmentTarget = self.isAssignmentTarget and oldIsAssignmentTarget
1156 self.firstCoverInitializedNameError = oldFirstCoverInitializedNameError or self.firstCoverInitializedNameError
1159 def parseArrayPattern(self):
1163 while (not self.match(']')):
1164 if (self.match(',')):
1166 elements.append(null)
1168 if (self.match('...')):
1171 rest = self.parseVariableIdentifier()
1172 elements.append(restNode.finishRestElement(rest))
1175 elements.append(self.parsePatternWithDefault())
1176 if (not self.match(']')):
1179 return node.finishArrayPattern(elements)
1181 def parsePropertyPattern(self):
1183 computed = self.match('[')
1184 if (self.lookahead['type'] == Token.Identifier):
1185 key = self.parseVariableIdentifier()
1186 if (self.match('=')):
1188 init = self.parseAssignmentExpression()
1189 return node.finishProperty(
1190 'init', key, false, WrappingNode(key).finishAssignmentPattern(key, init), false, false)
1191 elif (not self.match(':')):
1192 return node.finishProperty('init', key, false, key, false, true)
1194 key = self.parseObjectPropertyKey()
1196 init = self.parsePatternWithDefault()
1197 return node.finishProperty('init', key, computed, init, false, false)
1199 def parseObjectPattern(self):
1203 while (not self.match('}')):
1204 properties.append(self.parsePropertyPattern())
1205 if (not self.match('}')):
1208 return node.finishObjectPattern(properties)
1210 def parsePattern(self):
1211 if (self.lookahead['type'] == Token.Identifier):
1212 return self.parseVariableIdentifier()
1213 elif (self.match('[')):
1214 return self.parseArrayPattern()
1215 elif (self.match('{')):
1216 return self.parseObjectPattern()
1217 self.throwUnexpectedToken(self.lookahead)
1219 def parsePatternWithDefault(self):
1220 startToken = self.lookahead
1222 pattern = self.parsePattern()
1223 if (self.match('=')):
1225 right = self.isolateCoverGrammar(self.parseAssignmentExpression)
1226 pattern = WrappingNode(startToken).finishAssignmentPattern(pattern, right)
1229 # 11.1.4 Array Initialiser
1231 def parseArrayInitialiser(self):
1237 while (not self.match(']')):
1238 if (self.match(',')):
1240 elements.append(null)
1241 elif (self.match('...')):
1244 restSpread.finishSpreadElement(self.inheritCoverGrammar(self.parseAssignmentExpression))
1245 if (not self.match(']')):
1246 self.isAssignmentTarget = self.isBindingElement = false
1248 elements.append(restSpread)
1250 elements.append(self.inheritCoverGrammar(self.parseAssignmentExpression))
1251 if (not self.match(']')):
1255 return node.finishArrayExpression(elements)
1257 # 11.1.5 Object Initialiser
1259 def parsePropertyFunction(self, node, paramInfo):
1261 self.isAssignmentTarget = self.isBindingElement = false;
1263 previousStrict = self.strict;
1264 body = self.isolateCoverGrammar(self.parseFunctionSourceElements);
1266 if (self.strict and paramInfo['firstRestricted']):
1267 self.tolerateUnexpectedToken(paramInfo['firstRestricted'], paramInfo.get('message'))
1268 if (self.strict and paramInfo['stricted']):
1269 self.tolerateUnexpectedToken(paramInfo['stricted'], paramInfo.get('message'));
1271 self.strict = previousStrict;
1272 return node.finishFunctionExpression(null, paramInfo['params'], paramInfo['defaults'], body)
1274 def parsePropertyMethodFunction(self):
1277 params = self.parseParams();
1278 method = self.parsePropertyFunction(node, params);
1281 def parseObjectPropertyKey(self):
1286 # // Note: This function is called only from parseObjectProperty(), where
1287 # // EOF and Punctuator tokens are already filtered out.
1291 if typ in [Token.StringLiteral, Token.NumericLiteral]:
1292 if self.strict and token.get('octal'):
1293 self.tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
1294 return node.finishLiteral(token);
1295 elif typ in (Token.Identifier, Token.BooleanLiteral, Token.NullLiteral, Token.Keyword):
1296 return node.finishIdentifier(token['value']);
1297 elif typ == Token.Punctuator:
1298 if (token['value'] == '['):
1299 expr = self.isolateCoverGrammar(self.parseAssignmentExpression)
1302 self.throwUnexpectedToken(token)
1304 def lookaheadPropertyName(self):
1305 typ = self.lookahead['type']
1306 if typ in (Token.Identifier, Token.StringLiteral, Token.BooleanLiteral, Token.NullLiteral, Token.NumericLiteral,
1309 if typ == Token.Punctuator:
1310 return self.lookahead['value'] == '['
1313 # // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
1314 # // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
1315 # // This can only be determined after we consumed up to the left parentheses.
1317 # // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
1318 # // is responsible to visit other options.
1319 def tryParseMethodDefinition(self, token, key, computed, node):
1320 if (token['type'] == Token.Identifier):
1321 # check for `get` and `set`;
1323 if (token['value'] == 'get' and self.lookaheadPropertyName()):
1324 computed = self.match('[');
1325 key = self.parseObjectPropertyKey()
1329 value = self.parsePropertyFunction(methodNode, {
1333 'firstRestricted': null,
1336 return node.finishProperty('get', key, computed, value, false, false)
1337 elif (token['value'] == 'set' and self.lookaheadPropertyName()):
1338 computed = self.match('[')
1339 key = self.parseObjectPropertyKey()
1347 'firstRestricted': null,
1350 if (self.match(')')):
1351 self.tolerateUnexpectedToken(self.lookahead);
1353 self.parseParam(options);
1354 if (options['defaultCount'] == 0):
1355 options['defaults'] = []
1358 value = self.parsePropertyFunction(methodNode, options);
1359 return node.finishProperty('set', key, computed, value, false, false);
1360 if (self.match('(')):
1361 value = self.parsePropertyMethodFunction();
1362 return node.finishProperty('init', key, computed, value, true, false)
1365 def checkProto(self, key, computed, hasProto):
1366 if (computed == false and (key['type'] == Syntax.Identifier and key['name'] == '__proto__' or
1367 key['type'] == Syntax.Literal and key['value'] == '__proto__')):
1368 if (hasProto['value']):
1369 self.tolerateError(Messages.DuplicateProtoProperty);
1371 hasProto['value'] = true;
1373 def parseObjectProperty(self, hasProto):
1374 token = self.lookahead
1377 computed = self.match('[');
1378 key = self.parseObjectPropertyKey();
1379 maybeMethod = self.tryParseMethodDefinition(token, key, computed, node)
1382 self.checkProto(maybeMethod['key'], maybeMethod['computed'], hasProto);
1385 # // init property or short hand property.
1386 self.checkProto(key, computed, hasProto);
1388 if (self.match(':')):
1390 value = self.inheritCoverGrammar(self.parseAssignmentExpression)
1391 return node.finishProperty('init', key, computed, value, false, false)
1393 if (token['type'] == Token.Identifier):
1394 if (self.match('=')):
1395 self.firstCoverInitializedNameError = self.lookahead;
1397 value = self.isolateCoverGrammar(self.parseAssignmentExpression);
1398 return node.finishProperty('init', key, computed,
1399 WrappingNode(token).finishAssignmentPattern(key, value), false, true)
1400 return node.finishProperty('init', key, computed, key, false, true)
1401 self.throwUnexpectedToken(self.lookahead)
1403 def parseObjectInitialiser(self):
1405 hasProto = {'value': false}
1410 while (not self.match('}')):
1411 properties.append(self.parseObjectProperty(hasProto));
1413 if (not self.match('}')):
1414 self.expectCommaSeparator()
1416 return node.finishObjectExpression(properties)
1418 def reinterpretExpressionAsPattern(self, expr):
1419 typ = (expr['type'])
1420 if typ in (Syntax.Identifier, Syntax.MemberExpression, Syntax.RestElement, Syntax.AssignmentPattern):
1422 elif typ == Syntax.SpreadElement:
1423 expr['type'] = Syntax.RestElement
1424 self.reinterpretExpressionAsPattern(expr.argument)
1425 elif typ == Syntax.ArrayExpression:
1426 expr['type'] = Syntax.ArrayPattern
1427 for i in xrange(len(expr['elements'])):
1428 if (expr['elements'][i] != null):
1429 self.reinterpretExpressionAsPattern(expr['elements'][i])
1430 elif typ == Syntax.ObjectExpression:
1431 expr['type'] = Syntax.ObjectPattern
1432 for i in xrange(len(expr['properties'])):
1433 self.reinterpretExpressionAsPattern(expr['properties'][i]['value']);
1434 elif Syntax.AssignmentExpression:
1435 expr['type'] = Syntax.AssignmentPattern;
1436 self.reinterpretExpressionAsPattern(expr['left'])
1438 # // Allow other node type for tolerant parsing.
1441 def parseTemplateElement(self, option):
1443 if (self.lookahead['type'] != Token.Template or (option['head'] and not self.lookahead['head'])):
1444 self.throwUnexpectedToken()
1449 return node.finishTemplateElement({'raw': token['value']['raw'], 'cooked': token['value']['cooked']},
1452 def parseTemplateLiteral(self):
1455 quasi = self.parseTemplateElement({'head': true})
1459 while (not quasi['tail']):
1460 expressions.append(self.parseExpression());
1461 quasi = self.parseTemplateElement({'head': false});
1462 quasis.append(quasi)
1463 return node.finishTemplateLiteral(quasis, expressions)
1465 # 11.1.6 The Grouping Operator
1467 def parseGroupExpression(self):
1470 if (self.match(')')):
1472 if (not self.match('=>')):
1475 'type': PlaceHolders.ArrowParameterPlaceHolder,
1478 startToken = self.lookahead
1479 if (self.match('...')):
1480 expr = self.parseRestElement();
1482 if (not self.match('=>')):
1485 'type': PlaceHolders.ArrowParameterPlaceHolder,
1488 self.isBindingElement = true;
1489 expr = self.inheritCoverGrammar(self.parseAssignmentExpression);
1491 if (self.match(',')):
1492 self.isAssignmentTarget = false;
1493 expressions = [expr]
1495 while (self.startIndex < self.length):
1496 if (not self.match(',')):
1500 if (self.match('...')):
1501 if (not self.isBindingElement):
1502 self.throwUnexpectedToken(self.lookahead)
1503 expressions.append(self.parseRestElement())
1505 if (not self.match('=>')):
1507 self.isBindingElement = false
1508 for i in xrange(len(expressions)):
1509 self.reinterpretExpressionAsPattern(expressions[i])
1511 'type': PlaceHolders.ArrowParameterPlaceHolder,
1512 'params': expressions}
1513 expressions.append(self.inheritCoverGrammar(self.parseAssignmentExpression))
1514 expr = WrappingNode(startToken).finishSequenceExpression(expressions);
1517 if (self.match('=>')):
1518 if (not self.isBindingElement):
1519 self.throwUnexpectedToken(self.lookahead);
1520 if (expr['type'] == Syntax.SequenceExpression):
1521 for i in xrange(len(expr.expressions)):
1522 self.reinterpretExpressionAsPattern(expr['expressions'][i])
1524 self.reinterpretExpressionAsPattern(expr);
1526 'type': PlaceHolders.ArrowParameterPlaceHolder,
1527 'params': expr['expressions'] if expr['type'] == Syntax.SequenceExpression else [expr]}
1528 self.isBindingElement = false
1531 # 11.1 Primary Expressions
1533 def parsePrimaryExpression(self):
1534 if (self.match('(')):
1535 self.isBindingElement = false;
1536 return self.inheritCoverGrammar(self.parseGroupExpression)
1537 if (self.match('[')):
1538 return self.inheritCoverGrammar(self.parseArrayInitialiser)
1540 if (self.match('{')):
1541 return self.inheritCoverGrammar(self.parseObjectInitialiser)
1543 typ = self.lookahead['type']
1546 if (typ == Token.Identifier):
1547 expr = node.finishIdentifier(self.lex()['value']);
1548 elif (typ == Token.StringLiteral or typ == Token.NumericLiteral):
1549 self.isAssignmentTarget = self.isBindingElement = false
1550 if (self.strict and self.lookahead.get('octal')):
1551 self.tolerateUnexpectedToken(self.lookahead, Messages.StrictOctalLiteral)
1552 expr = node.finishLiteral(self.lex())
1553 elif (typ == Token.Keyword):
1554 self.isAssignmentTarget = self.isBindingElement = false
1555 if (self.matchKeyword('function')):
1556 return self.parseFunctionExpression()
1557 if (self.matchKeyword('this')):
1559 return node.finishThisExpression()
1560 if (self.matchKeyword('class')):
1561 return self.parseClassExpression()
1562 self.throwUnexpectedToken(self.lex())
1563 elif (typ == Token.BooleanLiteral):
1564 isAssignmentTarget = self.isBindingElement = false
1566 token['value'] = (token['value'] == 'true')
1567 expr = node.finishLiteral(token)
1568 elif (typ == Token.NullLiteral):
1569 self.isAssignmentTarget = self.isBindingElement = false
1571 token['value'] = null;
1572 expr = node.finishLiteral(token)
1573 elif (self.match('/') or self.match('/=')):
1574 self.isAssignmentTarget = self.isBindingElement = false;
1575 self.index = self.startIndex;
1576 token = self.scanRegExp(); # hehe, here you are!
1578 expr = node.finishLiteral(token);
1579 elif (typ == Token.Template):
1580 expr = self.parseTemplateLiteral()
1582 self.throwUnexpectedToken(self.lex());
1585 # 11.2 Left-Hand-Side Expressions
1587 def parseArguments(self):
1591 if (not self.match(')')):
1592 while (self.startIndex < self.length):
1593 args.append(self.isolateCoverGrammar(self.parseAssignmentExpression))
1594 if (self.match(')')):
1596 self.expectCommaSeparator()
1600 def parseNonComputedProperty(self):
1605 if (not self.isIdentifierName(token)):
1606 self.throwUnexpectedToken(token)
1607 return node.finishIdentifier(token['value'])
1609 def parseNonComputedMember(self):
1611 return self.parseNonComputedProperty();
1613 def parseComputedMember(self):
1616 expr = self.isolateCoverGrammar(self.parseExpression)
1621 def parseNewExpression(self):
1623 self.expectKeyword('new')
1624 callee = self.isolateCoverGrammar(self.parseLeftHandSideExpression)
1625 args = self.parseArguments() if self.match('(') else []
1627 self.isAssignmentTarget = self.isBindingElement = false
1629 return node.finishNewExpression(callee, args)
1631 def parseLeftHandSideExpressionAllowCall(self):
1632 previousAllowIn = self.state['allowIn']
1634 startToken = self.lookahead;
1635 self.state['allowIn'] = true;
1637 if (self.matchKeyword('super') and self.state['inFunctionBody']):
1640 expr = expr.finishSuper()
1641 if (not self.match('(') and not self.match('.') and not self.match('[')):
1642 self.throwUnexpectedToken(self.lookahead);
1644 expr = self.inheritCoverGrammar(
1645 self.parseNewExpression if self.matchKeyword('new') else self.parsePrimaryExpression)
1647 if (self.match('.')):
1648 self.isBindingElement = false;
1649 self.isAssignmentTarget = true;
1650 property = self.parseNonComputedMember();
1651 expr = WrappingNode(startToken).finishMemberExpression('.', expr, property)
1652 elif (self.match('(')):
1653 self.isBindingElement = false;
1654 self.isAssignmentTarget = false;
1655 args = self.parseArguments();
1656 expr = WrappingNode(startToken).finishCallExpression(expr, args)
1657 elif (self.match('[')):
1658 self.isBindingElement = false;
1659 self.isAssignmentTarget = true;
1660 property = self.parseComputedMember();
1661 expr = WrappingNode(startToken).finishMemberExpression('[', expr, property)
1662 elif (self.lookahead['type'] == Token.Template and self.lookahead['head']):
1663 quasi = self.parseTemplateLiteral()
1664 expr = WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi)
1667 self.state['allowIn'] = previousAllowIn
1671 def parseLeftHandSideExpression(self):
1672 assert self.state['allowIn'], 'callee of new expression always allow in keyword.'
1674 startToken = self.lookahead
1676 if (self.matchKeyword('super') and self.state['inFunctionBody']):
1679 expr = expr.finishSuper();
1680 if (not self.match('[') and not self.match('.')):
1681 self.throwUnexpectedToken(self.lookahead)
1683 expr = self.inheritCoverGrammar(
1684 self.parseNewExpression if self.matchKeyword('new') else self.parsePrimaryExpression);
1687 if (self.match('[')):
1688 self.isBindingElement = false;
1689 self.isAssignmentTarget = true;
1690 property = self.parseComputedMember();
1691 expr = WrappingNode(startToken).finishMemberExpression('[', expr, property)
1692 elif (self.match('.')):
1693 self.isBindingElement = false;
1694 self.isAssignmentTarget = true;
1695 property = self.parseNonComputedMember();
1696 expr = WrappingNode(startToken).finishMemberExpression('.', expr, property);
1697 elif (self.lookahead['type'] == Token.Template and self.lookahead['head']):
1698 quasi = self.parseTemplateLiteral();
1699 expr = WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi)
1704 # 11.3 Postfix Expressions
1706 def parsePostfixExpression(self):
1707 startToken = self.lookahead
1709 expr = self.inheritCoverGrammar(self.parseLeftHandSideExpressionAllowCall)
1711 if (not self.hasLineTerminator and self.lookahead['type'] == Token.Punctuator):
1712 if (self.match('++') or self.match('--')):
1714 if (self.strict and expr.type == Syntax.Identifier and isRestrictedWord(expr.name)):
1715 self.tolerateError(Messages.StrictLHSPostfix)
1716 if (not self.isAssignmentTarget):
1717 self.tolerateError(Messages.InvalidLHSInAssignment);
1718 self.isAssignmentTarget = self.isBindingElement = false;
1721 expr = WrappingNode(startToken).finishPostfixExpression(token['value'], expr);
1724 # 11.4 Unary Operators
1726 def parseUnaryExpression(self):
1728 if (self.lookahead['type'] != Token.Punctuator and self.lookahead['type'] != Token.Keyword):
1729 expr = self.parsePostfixExpression();
1730 elif (self.match('++') or self.match('--')):
1731 startToken = self.lookahead;
1733 expr = self.inheritCoverGrammar(self.parseUnaryExpression);
1735 if (self.strict and expr.type == Syntax.Identifier and isRestrictedWord(expr.name)):
1736 self.tolerateError(Messages.StrictLHSPrefix)
1737 if (not self.isAssignmentTarget):
1738 self.tolerateError(Messages.InvalidLHSInAssignment)
1739 expr = WrappingNode(startToken).finishUnaryExpression(token['value'], expr)
1740 self.isAssignmentTarget = self.isBindingElement = false
1741 elif (self.match('+') or self.match('-') or self.match('~') or self.match('!')):
1742 startToken = self.lookahead;
1744 expr = self.inheritCoverGrammar(self.parseUnaryExpression);
1745 expr = WrappingNode(startToken).finishUnaryExpression(token['value'], expr)
1746 self.isAssignmentTarget = self.isBindingElement = false;
1747 elif (self.matchKeyword('delete') or self.matchKeyword('void') or self.matchKeyword('typeof')):
1748 startToken = self.lookahead;
1750 expr = self.inheritCoverGrammar(self.parseUnaryExpression);
1751 expr = WrappingNode(startToken).finishUnaryExpression(token['value'], expr);
1752 if (self.strict and expr.operator == 'delete' and expr.argument.type == Syntax.Identifier):
1753 self.tolerateError(Messages.StrictDelete)
1754 self.isAssignmentTarget = self.isBindingElement = false;
1756 expr = self.parsePostfixExpression()
1759 def binaryPrecedence(self, token, allowIn):
1762 if (typ != Token.Punctuator and typ != Token.Keyword):
1764 val = token['value']
1765 if val == 'in' and not allowIn:
1767 return PRECEDENCE.get(val, 0)
1769 # 11.5 Multiplicative Operators
1770 # 11.6 Additive Operators
1771 # 11.7 Bitwise Shift Operators
1772 # 11.8 Relational Operators
1773 # 11.9 Equality Operators
1774 # 11.10 Binary Bitwise Operators
1775 # 11.11 Binary Logical Operators
1777 def parseBinaryExpression(self):
1779 marker = self.lookahead;
1780 left = self.inheritCoverGrammar(self.parseUnaryExpression);
1782 token = self.lookahead;
1783 prec = self.binaryPrecedence(token, self.state['allowIn']);
1786 self.isAssignmentTarget = self.isBindingElement = false;
1787 token['prec'] = prec
1790 markers = [marker, self.lookahead];
1791 right = self.isolateCoverGrammar(self.parseUnaryExpression);
1793 stack = [left, token, right];
1796 prec = self.binaryPrecedence(self.lookahead, self.state['allowIn'])
1799 # Reduce: make a binary expression from the three topmost entries.
1800 while ((len(stack) > 2) and (prec <= stack[len(stack) - 2]['prec'])):
1801 right = stack.pop();
1802 operator = stack.pop()['value']
1805 expr = WrappingNode(markers[len(markers) - 1]).finishBinaryExpression(operator, left, right)
1810 token['prec'] = prec;
1811 stack.append(token);
1812 markers.append(self.lookahead);
1813 expr = self.isolateCoverGrammar(self.parseUnaryExpression);
1816 # Final reduce to clean-up the stack.
1821 expr = WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1]['value'], stack[i - 2], expr);
1825 # 11.12 Conditional Operator
1827 def parseConditionalExpression(self):
1829 startToken = self.lookahead
1831 expr = self.inheritCoverGrammar(self.parseBinaryExpression);
1832 if (self.match('?')):
1834 previousAllowIn = self.state['allowIn']
1835 self.state['allowIn'] = true;
1836 consequent = self.isolateCoverGrammar(self.parseAssignmentExpression);
1837 self.state['allowIn'] = previousAllowIn;
1839 alternate = self.isolateCoverGrammar(self.parseAssignmentExpression)
1841 expr = WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
1842 self.isAssignmentTarget = self.isBindingElement = false;
1845 # [ES6] 14.2 Arrow Function
1847 def parseConciseBody(self):
1848 if (self.match('{')):
1849 return self.parseFunctionSourceElements()
1850 return self.isolateCoverGrammar(self.parseAssignmentExpression)
1852 def checkPatternParam(self, options, param):
1854 if typ == Syntax.Identifier:
1855 self.validateParam(options, param, param.name);
1856 elif typ == Syntax.RestElement:
1857 self.checkPatternParam(options, param.argument)
1858 elif typ == Syntax.AssignmentPattern:
1859 self.checkPatternParam(options, param.left)
1860 elif typ == Syntax.ArrayPattern:
1861 for i in xrange(len(param.elements)):
1862 if (param.elements[i] != null):
1863 self.checkPatternParam(options, param.elements[i]);
1865 assert typ == Syntax.ObjectPattern, 'Invalid type'
1866 for i in xrange(len(param.properties)):
1867 self.checkPatternParam(options, param.properties[i]['value']);
1869 def reinterpretAsCoverFormalsList(self, expr):
1874 if typ == Syntax.Identifier:
1876 elif typ == PlaceHolders.ArrowParameterPlaceHolder:
1877 params = expr.params
1883 for i in xrange(le):
1885 if param.type == Syntax.AssignmentPattern:
1886 params[i] = param.left;
1887 defaults.append(param.right);
1889 self.checkPatternParam(options, param.left);
1891 self.checkPatternParam(options, param);
1893 defaults.append(null);
1894 if (options.get('message') == Messages.StrictParamDupe):
1895 token = options['stricted'] if self.strict else options['firstRestricted']
1896 self.throwUnexpectedToken(token, options.get('message'));
1897 if (defaultCount == 0):
1901 'defaults': defaults,
1902 'stricted': options['stricted'],
1903 'firstRestricted': options['firstRestricted'],
1904 'message': options.get('message')}
1906 def parseArrowFunctionExpression(self, options, node):
1907 if (self.hasLineTerminator):
1908 self.tolerateUnexpectedToken(self.lookahead)
1910 previousStrict = self.strict;
1912 body = self.parseConciseBody();
1914 if (self.strict and options['firstRestricted']):
1915 self.throwUnexpectedToken(options['firstRestricted'], options.get('message'));
1916 if (self.strict and options['stricted']):
1917 self.tolerateUnexpectedToken(options['stricted'], options['message']);
1919 self.strict = previousStrict
1921 return node.finishArrowFunctionExpression(options['params'], options['defaults'], body,
1922 body.type != Syntax.BlockStatement)
1924 # 11.13 Assignment Operators
1926 def parseAssignmentExpression(self):
1927 startToken = self.lookahead;
1928 token = self.lookahead;
1930 expr = self.parseConditionalExpression();
1932 if (expr.type == PlaceHolders.ArrowParameterPlaceHolder or self.match('=>')):
1933 self.isAssignmentTarget = self.isBindingElement = false;
1934 lis = self.reinterpretAsCoverFormalsList(expr)
1937 self.firstCoverInitializedNameError = null;
1938 return self.parseArrowFunctionExpression(lis, WrappingNode(startToken))
1941 if (self.matchAssign()):
1942 if (not self.isAssignmentTarget):
1943 self.tolerateError(Messages.InvalidLHSInAssignment)
1946 if (self.strict and expr.type == Syntax.Identifier and isRestrictedWord(expr.name)):
1947 self.tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
1948 if (not self.match('=')):
1949 self.isAssignmentTarget = self.isBindingElement = false;
1951 self.reinterpretExpressionAsPattern(expr)
1953 right = self.isolateCoverGrammar(self.parseAssignmentExpression)
1954 expr = WrappingNode(startToken).finishAssignmentExpression(token['value'], expr, right);
1955 self.firstCoverInitializedNameError = null
1958 # 11.14 Comma Operator
1960 def parseExpression(self):
1961 startToken = self.lookahead
1962 expr = self.isolateCoverGrammar(self.parseAssignmentExpression)
1964 if (self.match(',')):
1965 expressions = [expr];
1967 while (self.startIndex < self.length):
1968 if (not self.match(',')):
1971 expressions.append(self.isolateCoverGrammar(self.parseAssignmentExpression))
1972 expr = WrappingNode(startToken).finishSequenceExpression(expressions);
1977 def parseStatementListItem(self):
1978 if (self.lookahead['type'] == Token.Keyword):
1979 val = (self.lookahead['value'])
1981 if (self.sourceType != 'module'):
1982 self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalExportDeclaration)
1983 return self.parseExportDeclaration();
1984 elif val == 'import':
1985 if (self.sourceType != 'module'):
1986 self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalImportDeclaration);
1987 return self.parseImportDeclaration();
1988 elif val == 'const' or val == 'let':
1989 return self.parseLexicalDeclaration({'inFor': false});
1990 elif val == 'function':
1991 return self.parseFunctionDeclaration(Node());
1992 elif val == 'class':
1993 return self.parseClassDeclaration();
1994 elif ENABLE_PYIMPORT and val == 'pyimport': # <<<<< MODIFIED HERE
1995 return self.parsePyimportStatement()
1996 return self.parseStatement();
1998 def parsePyimportStatement(self):
1999 print(ENABLE_PYIMPORT)
2000 assert ENABLE_PYIMPORT
2003 n.finishPyimport(self.parseVariableIdentifier())
2004 self.consumeSemicolon()
2007 def parseStatementList(self):
2009 while (self.startIndex < self.length):
2010 if (self.match('}')):
2012 list.append(self.parseStatementListItem())
2015 def parseBlock(self):
2020 block = self.parseStatementList()
2024 return node.finishBlockStatement(block);
2026 # 12.2 Variable Statement
2028 def parseVariableIdentifier(self):
2033 if (token['type'] != Token.Identifier):
2034 if (self.strict and token['type'] == Token.Keyword and isStrictModeReservedWord(token['value'])):
2035 self.tolerateUnexpectedToken(token, Messages.StrictReservedWord);
2037 self.throwUnexpectedToken(token)
2038 return node.finishIdentifier(token['value'])
2040 def parseVariableDeclaration(self):
2044 d = self.parsePattern();
2047 if (self.strict and isRestrictedWord(d.name)):
2048 self.tolerateError(Messages.StrictVarName);
2050 if (self.match('=')):
2052 init = self.isolateCoverGrammar(self.parseAssignmentExpression);
2053 elif (d.type != Syntax.Identifier):
2055 return node.finishVariableDeclarator(d, init)
2057 def parseVariableDeclarationList(self):
2061 lis.append(self.parseVariableDeclaration())
2062 if (not self.match(',')):
2065 if not (self.startIndex < self.length):
2070 def parseVariableStatement(self, node):
2071 self.expectKeyword('var')
2073 declarations = self.parseVariableDeclarationList()
2075 self.consumeSemicolon()
2077 return node.finishVariableDeclaration(declarations)
2079 def parseLexicalBinding(self, kind, options):
2083 d = self.parsePattern();
2086 if (self.strict and d.type == Syntax.Identifier and isRestrictedWord(d.name)):
2087 self.tolerateError(Messages.StrictVarName);
2089 if (kind == 'const'):
2090 if (not self.matchKeyword('in')):
2092 init = self.isolateCoverGrammar(self.parseAssignmentExpression)
2093 elif ((not options['inFor'] and d.type != Syntax.Identifier) or self.match('=')):
2095 init = self.isolateCoverGrammar(self.parseAssignmentExpression);
2096 return node.finishVariableDeclarator(d, init)
2098 def parseBindingList(self, kind, options):
2102 list.append(self.parseLexicalBinding(kind, options));
2103 if (not self.match(',')):
2106 if not (self.startIndex < self.length):
2110 def parseLexicalDeclaration(self, options):
2113 kind = self.lex()['value']
2114 assert kind == 'let' or kind == 'const', 'Lexical declaration must be either let or const'
2115 declarations = self.parseBindingList(kind, options);
2116 self.consumeSemicolon();
2117 return node.finishLexicalDeclaration(declarations, kind);
2119 def parseRestElement(self):
2124 if (self.match('{')):
2125 self.throwError(Messages.ObjectPatternAsRestParameter)
2126 param = self.parseVariableIdentifier();
2127 if (self.match('=')):
2128 self.throwError(Messages.DefaultRestParameter);
2130 if (not self.match(')')):
2131 self.throwError(Messages.ParameterAfterRestParameter);
2132 return node.finishRestElement(param);
2134 # 12.3 Empty Statement
2136 def parseEmptyStatement(self, node):
2138 return node.finishEmptyStatement()
2140 # 12.4 Expression Statement
2142 def parseExpressionStatement(self, node):
2143 expr = self.parseExpression();
2144 self.consumeSemicolon();
2145 return node.finishExpressionStatement(expr);
2149 def parseIfStatement(self, node):
2150 self.expectKeyword('if');
2154 test = self.parseExpression();
2158 consequent = self.parseStatement();
2160 if (self.matchKeyword('else')):
2162 alternate = self.parseStatement();
2165 return node.finishIfStatement(test, consequent, alternate)
2167 # 12.6 Iteration Statements
2169 def parseDoWhileStatement(self, node):
2171 self.expectKeyword('do')
2173 oldInIteration = self.state['inIteration']
2174 self.state['inIteration'] = true
2176 body = self.parseStatement();
2178 self.state['inIteration'] = oldInIteration;
2180 self.expectKeyword('while');
2184 test = self.parseExpression();
2188 if (self.match(';')):
2190 return node.finishDoWhileStatement(body, test)
2192 def parseWhileStatement(self, node):
2194 self.expectKeyword('while')
2198 test = self.parseExpression()
2202 oldInIteration = self.state['inIteration']
2203 self.state['inIteration'] = true
2205 body = self.parseStatement()
2207 self.state['inIteration'] = oldInIteration
2209 return node.finishWhileStatement(test, body)
2211 def parseForStatement(self, node):
2212 previousAllowIn = self.state['allowIn']
2214 init = test = update = null
2216 self.expectKeyword('for')
2220 if (self.match(';')):
2223 if (self.matchKeyword('var')):
2227 self.state['allowIn'] = false;
2228 init = init.finishVariableDeclaration(self.parseVariableDeclarationList())
2229 self.state['allowIn'] = previousAllowIn
2231 if (len(init.declarations) == 1 and self.matchKeyword('in')):
2234 right = self.parseExpression()
2238 elif (self.matchKeyword('const') or self.matchKeyword('let')):
2240 kind = self.lex()['value']
2242 self.state['allowIn'] = false
2243 declarations = self.parseBindingList(kind, {'inFor': true})
2244 self.state['allowIn'] = previousAllowIn
2246 if (len(declarations) == 1 and declarations[0].init == null and self.matchKeyword('in')):
2247 init = init.finishLexicalDeclaration(declarations, kind);
2250 right = self.parseExpression();
2253 self.consumeSemicolon();
2254 init = init.finishLexicalDeclaration(declarations, kind);
2256 initStartToken = self.lookahead
2257 self.state['allowIn'] = false
2258 init = self.inheritCoverGrammar(self.parseAssignmentExpression);
2259 self.state['allowIn'] = previousAllowIn;
2261 if (self.matchKeyword('in')):
2262 if (not self.isAssignmentTarget):
2263 self.tolerateError(Messages.InvalidLHSInForIn)
2265 self.reinterpretExpressionAsPattern(init);
2267 right = self.parseExpression();
2270 if (self.match(',')):
2272 while (self.match(',')):
2274 initSeq.append(self.isolateCoverGrammar(self.parseAssignmentExpression))
2275 init = WrappingNode(initStartToken).finishSequenceExpression(initSeq)
2278 if ('left' not in locals()):
2279 if (not self.match(';')):
2280 test = self.parseExpression();
2284 if (not self.match(')')):
2285 update = self.parseExpression();
2289 oldInIteration = self.state['inIteration']
2290 self.state['inIteration'] = true;
2292 body = self.isolateCoverGrammar(self.parseStatement)
2294 self.state['inIteration'] = oldInIteration;
2296 return node.finishForStatement(init, test, update, body) if (
2297 'left' not in locals()) else node.finishForInStatement(left, right, body);
2299 # 12.7 The continue statement
2301 def parseContinueStatement(self, node):
2304 self.expectKeyword('continue');
2306 # Optimize the most common form: 'continue;'.
2307 if ord(self.source[self.startIndex]) == 0x3B:
2309 if (not self.state['inIteration']):
2310 self.throwError(Messages.IllegalContinue)
2311 return node.finishContinueStatement(null)
2312 if (self.hasLineTerminator):
2313 if (not self.state['inIteration']):
2314 self.throwError(Messages.IllegalContinue);
2315 return node.finishContinueStatement(null);
2317 if (self.lookahead['type'] == Token.Identifier):
2318 label = self.parseVariableIdentifier();
2320 key = '$' + label.name;
2321 if not key in self.state['labelSet']: # todo make sure its correct!
2322 self.throwError(Messages.UnknownLabel, label.name);
2323 self.consumeSemicolon()
2325 if (label == null and not self.state['inIteration']):
2326 self.throwError(Messages.IllegalContinue)
2327 return node.finishContinueStatement(label)
2329 # 12.8 The break statement
2331 def parseBreakStatement(self, node):
2334 self.expectKeyword('break');
2336 # Catch the very common case first: immediately a semicolon (U+003B).
2337 if (ord(self.source[self.lastIndex]) == 0x3B):
2340 if (not (self.state['inIteration'] or self.state['inSwitch'])):
2341 self.throwError(Messages.IllegalBreak)
2342 return node.finishBreakStatement(null)
2343 if (self.hasLineTerminator):
2344 if (not (self.state['inIteration'] or self.state['inSwitch'])):
2345 self.throwError(Messages.IllegalBreak);
2346 return node.finishBreakStatement(null);
2347 if (self.lookahead['type'] == Token.Identifier):
2348 label = self.parseVariableIdentifier();
2350 key = '$' + label.name;
2351 if not (key in self.state['labelSet']):
2352 self.throwError(Messages.UnknownLabel, label.name);
2353 self.consumeSemicolon();
2355 if (label == null and not (self.state['inIteration'] or self.state['inSwitch'])):
2356 self.throwError(Messages.IllegalBreak)
2357 return node.finishBreakStatement(label);
2359 # 12.9 The return statement
2361 def parseReturnStatement(self, node):
2364 self.expectKeyword('return');
2366 if (not self.state['inFunctionBody']):
2367 self.tolerateError(Messages.IllegalReturn);
2369 # 'return' followed by a space and an identifier is very common.
2370 if (ord(self.source[self.lastIndex]) == 0x20):
2371 if (isIdentifierStart(self.source[self.lastIndex + 1])):
2372 argument = self.parseExpression();
2373 self.consumeSemicolon();
2374 return node.finishReturnStatement(argument)
2375 if (self.hasLineTerminator):
2377 return node.finishReturnStatement(null)
2379 if (not self.match(';')):
2380 if (not self.match('}') and self.lookahead['type'] != Token.EOF):
2381 argument = self.parseExpression();
2382 self.consumeSemicolon();
2384 return node.finishReturnStatement(argument);
2386 # 12.10 The with statement
2388 def parseWithStatement(self, node):
2390 self.tolerateError(Messages.StrictModeWith)
2392 self.expectKeyword('with');
2396 obj = self.parseExpression();
2400 body = self.parseStatement();
2402 return node.finishWithStatement(obj, body);
2404 # 12.10 The swith statement
2406 def parseSwitchCase(self):
2410 if (self.matchKeyword('default')):
2414 self.expectKeyword('case');
2415 test = self.parseExpression();
2419 while (self.startIndex < self.length):
2420 if (self.match('}') or self.matchKeyword('default') or self.matchKeyword('case')):
2422 statement = self.parseStatementListItem()
2423 consequent.append(statement)
2424 return node.finishSwitchCase(test, consequent)
2426 def parseSwitchStatement(self, node):
2428 self.expectKeyword('switch');
2432 discriminant = self.parseExpression();
2440 if (self.match('}')):
2442 return node.finishSwitchStatement(discriminant, cases);
2444 oldInSwitch = self.state['inSwitch'];
2445 self.state['inSwitch'] = true;
2446 defaultFound = false;
2448 while (self.startIndex < self.length):
2449 if (self.match('}')):
2451 clause = self.parseSwitchCase();
2452 if (clause.test == null):
2454 self.throwError(Messages.MultipleDefaultsInSwitch);
2455 defaultFound = true;
2456 cases.append(clause);
2458 self.state['inSwitch'] = oldInSwitch;
2462 return node.finishSwitchStatement(discriminant, cases);
2464 # 12.13 The throw statement
2466 def parseThrowStatement(self, node):
2468 self.expectKeyword('throw');
2470 if (self.hasLineTerminator):
2471 self.throwError(Messages.NewlineAfterThrow);
2473 argument = self.parseExpression();
2475 self.consumeSemicolon();
2477 return node.finishThrowStatement(argument);
2479 # 12.14 The try statement
2481 def parseCatchClause(self):
2484 self.expectKeyword('catch');
2487 if (self.match(')')):
2488 self.throwUnexpectedToken(self.lookahead);
2489 param = self.parsePattern();
2492 if (self.strict and isRestrictedWord(param.name)):
2493 self.tolerateError(Messages.StrictCatchVariable);
2496 body = self.parseBlock();
2497 return node.finishCatchClause(param, body);
2499 def parseTryStatement(self, node):
2503 self.expectKeyword('try');
2505 block = self.parseBlock();
2507 if (self.matchKeyword('catch')):
2508 handler = self.parseCatchClause()
2510 if (self.matchKeyword('finally')):
2512 finalizer = self.parseBlock();
2514 if (not handler and not finalizer):
2515 self.throwError(Messages.NoCatchOrFinally)
2517 return node.finishTryStatement(block, handler, finalizer)
2519 # 12.15 The debugger statement
2521 def parseDebuggerStatement(self, node):
2522 self.expectKeyword('debugger');
2524 self.consumeSemicolon();
2526 return node.finishDebuggerStatement();
2530 def parseStatement(self):
2531 typ = self.lookahead['type']
2533 if (typ == Token.EOF):
2534 self.throwUnexpectedToken(self.lookahead)
2536 if (typ == Token.Punctuator and self.lookahead['value'] == '{'):
2537 return self.parseBlock()
2539 self.isAssignmentTarget = self.isBindingElement = true;
2541 val = self.lookahead['value']
2543 if (typ == Token.Punctuator):
2545 return self.parseEmptyStatement(node);
2547 return self.parseExpressionStatement(node);
2548 elif (typ == Token.Keyword):
2550 return self.parseBreakStatement(node);
2551 elif val == 'continue':
2552 return self.parseContinueStatement(node);
2553 elif val == 'debugger':
2554 return self.parseDebuggerStatement(node);
2556 return self.parseDoWhileStatement(node);
2558 return self.parseForStatement(node);
2559 elif val == 'function':
2560 return self.parseFunctionDeclaration(node);
2562 return self.parseIfStatement(node);
2563 elif val == 'return':
2564 return self.parseReturnStatement(node);
2565 elif val == 'switch':
2566 return self.parseSwitchStatement(node);
2567 elif val == 'throw':
2568 return self.parseThrowStatement(node);
2570 return self.parseTryStatement(node);
2572 return self.parseVariableStatement(node);
2573 elif val == 'while':
2574 return self.parseWhileStatement(node);
2576 return self.parseWithStatement(node);
2578 expr = self.parseExpression();
2580 # 12.12 Labelled Statements
2581 if ((expr.type == Syntax.Identifier) and self.match(':')):
2584 key = '$' + expr.name
2585 if key in self.state['labelSet']:
2586 self.throwError(Messages.Redeclaration, 'Label', expr.name);
2587 self.state['labelSet'][key] = true
2588 labeledBody = self.parseStatement()
2589 del self.state['labelSet'][key]
2590 return node.finishLabeledStatement(expr, labeledBody)
2591 self.consumeSemicolon();
2592 return node.finishExpressionStatement(expr)
2594 # 13 Function Definition
2596 def parseFunctionSourceElements(self):
2599 firstRestricted = None
2603 while (self.startIndex < self.length):
2604 if (self.lookahead['type'] != Token.StringLiteral):
2606 token = self.lookahead;
2608 statement = self.parseStatementListItem()
2609 body.append(statement)
2610 if (statement.expression.type != Syntax.Literal):
2611 # this is not directive
2613 directive = self.source[token['start'] + 1: token['end'] - 1]
2614 if (directive == 'use strict'):
2616 if (firstRestricted):
2617 self.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
2619 if (not firstRestricted and token.get('octal')):
2620 firstRestricted = token;
2622 oldLabelSet = self.state['labelSet']
2623 oldInIteration = self.state['inIteration']
2624 oldInSwitch = self.state['inSwitch']
2625 oldInFunctionBody = self.state['inFunctionBody']
2626 oldParenthesisCount = self.state['parenthesizedCount']
2628 self.state['labelSet'] = {}
2629 self.state['inIteration'] = false
2630 self.state['inSwitch'] = false
2631 self.state['inFunctionBody'] = true
2632 self.state['parenthesizedCount'] = 0
2634 while (self.startIndex < self.length):
2635 if (self.match('}')):
2637 body.append(self.parseStatementListItem())
2640 self.state['labelSet'] = oldLabelSet;
2641 self.state['inIteration'] = oldInIteration;
2642 self.state['inSwitch'] = oldInSwitch;
2643 self.state['inFunctionBody'] = oldInFunctionBody;
2644 self.state['parenthesizedCount'] = oldParenthesisCount;
2646 return node.finishBlockStatement(body)
2648 def validateParam(self, options, param, name):
2651 if (isRestrictedWord(name)):
2652 options['stricted'] = param;
2653 options['message'] = Messages.StrictParamName
2654 if key in options['paramSet']:
2655 options['stricted'] = param;
2656 options['message'] = Messages.StrictParamDupe;
2657 elif (not options['firstRestricted']):
2658 if (isRestrictedWord(name)):
2659 options['firstRestricted'] = param;
2660 options['message'] = Messages.StrictParamName;
2661 elif (isStrictModeReservedWord(name)):
2662 options['firstRestricted'] = param;
2663 options['message'] = Messages.StrictReservedWord;
2664 elif key in options['paramSet']:
2665 options['firstRestricted'] = param
2666 options['message'] = Messages.StrictParamDupe;
2667 options['paramSet'][key] = true
2669 def parseParam(self, options):
2670 token = self.lookahead
2672 if (token['value'] == '...'):
2673 param = self.parseRestElement();
2674 self.validateParam(options, param.argument, param.argument.name);
2675 options['params'].append(param);
2676 options['defaults'].append(null);
2678 param = self.parsePatternWithDefault();
2679 self.validateParam(options, token, token['value']);
2681 if (param.type == Syntax.AssignmentPattern):
2684 options['defaultCount'] += 1
2685 options['params'].append(param);
2686 options['defaults'].append(de)
2687 return not self.match(')')
2689 def parseParams(self, firstRestricted):
2694 'firstRestricted': firstRestricted}
2698 if (not self.match(')')):
2699 options['paramSet'] = {};
2700 while (self.startIndex < self.length):
2701 if (not self.parseParam(options)):
2706 if (options['defaultCount'] == 0):
2707 options['defaults'] = [];
2710 'params': options['params'],
2711 'defaults': options['defaults'],
2712 'stricted': options.get('stricted'),
2713 'firstRestricted': options.get('firstRestricted'),
2714 'message': options.get('message')}
2716 def parseFunctionDeclaration(self, node, identifierIsOptional=None):
2721 firstRestricted = None
2723 self.expectKeyword('function');
2724 if (identifierIsOptional or not self.match('(')):
2725 token = self.lookahead;
2726 d = self.parseVariableIdentifier();
2728 if (isRestrictedWord(token['value'])):
2729 self.tolerateUnexpectedToken(token, Messages.StrictFunctionName);
2731 if (isRestrictedWord(token['value'])):
2732 firstRestricted = token;
2733 message = Messages.StrictFunctionName;
2734 elif (isStrictModeReservedWord(token['value'])):
2735 firstRestricted = token;
2736 message = Messages.StrictReservedWord;
2738 tmp = self.parseParams(firstRestricted);
2739 params = tmp['params']
2740 defaults = tmp['defaults']
2741 stricted = tmp['stricted']
2742 firstRestricted = tmp['firstRestricted']
2743 if (tmp.get('message')):
2744 message = tmp['message'];
2746 previousStrict = self.strict;
2747 body = self.parseFunctionSourceElements();
2748 if (self.strict and firstRestricted):
2749 self.throwUnexpectedToken(firstRestricted, message);
2751 if (self.strict and stricted):
2752 self.tolerateUnexpectedToken(stricted, message);
2753 self.strict = previousStrict;
2755 return node.finishFunctionDeclaration(d, params, defaults, body);
2757 def parseFunctionExpression(self):
2762 firstRestricted = None
2765 self.expectKeyword('function');
2767 if (not self.match('(')):
2768 token = self.lookahead;
2769 id = self.parseVariableIdentifier();
2771 if (isRestrictedWord(token['value'])):
2772 self.tolerateUnexpectedToken(token, Messages.StrictFunctionName);
2774 if (isRestrictedWord(token['value'])):
2775 firstRestricted = token;
2776 message = Messages.StrictFunctionName;
2777 elif (isStrictModeReservedWord(token['value'])):
2778 firstRestricted = token;
2779 message = Messages.StrictReservedWord;
2780 tmp = self.parseParams(firstRestricted);
2781 params = tmp['params']
2782 defaults = tmp['defaults']
2783 stricted = tmp['stricted']
2784 firstRestricted = tmp['firstRestricted']
2785 if (tmp.get('message')):
2786 message = tmp['message']
2788 previousStrict = self.strict;
2789 body = self.parseFunctionSourceElements();
2790 if (self.strict and firstRestricted):
2791 self.throwUnexpectedToken(firstRestricted, message);
2792 if (self.strict and stricted):
2793 self.tolerateUnexpectedToken(stricted, message);
2794 self.strict = previousStrict;
2796 return node.finishFunctionExpression(id, params, defaults, body);
2798 # todo Translate parse class functions!
2800 def parseClassExpression(self):
2801 raise NotImplementedError()
2803 def parseClassDeclaration(self):
2804 raise NotImplementedError()
2808 def parseScriptBody(self):
2810 firstRestricted = None
2812 while (self.startIndex < self.length):
2813 token = self.lookahead;
2814 if (token['type'] != Token.StringLiteral):
2816 statement = self.parseStatementListItem();
2817 body.append(statement);
2818 if (statement.expression.type != Syntax.Literal):
2819 # this is not directive
2821 directive = self.source[token['start'] + 1: token['end'] - 1]
2822 if (directive == 'use strict'):
2824 if (firstRestricted):
2825 self.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral)
2827 if (not firstRestricted and token.get('octal')):
2828 firstRestricted = token;
2829 while (self.startIndex < self.length):
2830 statement = self.parseStatementListItem();
2831 # istanbul ignore if
2832 if (statement is None):
2834 body.append(statement);
2837 def parseProgram(self):
2841 body = self.parseScriptBody()
2842 return node.finishProgram(body)
2845 def parse(self, code, options={}):
2847 raise NotImplementedError('Options not implemented! You can only use default settings.')
2850 self.source = unicode(code) + ' \n ; //END' # I have to add it in order not to check for EOF every time
2852 self.lineNumber = 1 if len(self.source) > 0 else 0
2854 self.startIndex = self.index
2855 self.startLineNumber = self.lineNumber;
2856 self.startLineStart = self.lineStart;
2857 self.length = len(self.source)
2858 self.lookahead = null;
2862 'inFunctionBody': false,
2863 'inIteration': false,
2865 'lastCommentStart': -1,
2867 'parenthesizedCount': None}
2868 self.sourceType = 'script';
2869 self.strict = false;
2870 program = self.parseProgram();
2871 return node_to_dict(program)
2875 def parse(javascript_code):
2876 """Returns syntax tree of javascript_code.
2877 Same as PyJsParser().parse For your convenience :) """
2879 return p.parse(javascript_code)
2882 if __name__ == '__main__':
2887 f = open(test_path, 'rb')
2891 x = 'var $ = "Hello!"'
2895 dt = time.time() - t + 0.000000001
2901 print('Parsed everyting in', round(dt, 5), 'seconds.')
2902 print('Thats %d characters per second' % int(len(x) / dt))