# The MIT License # # Copyright 2014, 2015 Piotr Dabkowski # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the 'Software'), # to deal in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of # the Software, and to permit persons to whom the Software is furnished to do so, subject # to the following conditions: # # The above copyright notice and this permission notice shall be included in all copies or # substantial portions of the Software. # # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE from __future__ import unicode_literals from .pyjsparserdata import * from .std_nodes import * from pprint import pprint import sys __all__ = ['PyJsParser', 'parse', 'ENABLE_JS2PY_ERRORS', 'ENABLE_PYIMPORT', 'JsSyntaxError'] REGEXP_SPECIAL_SINGLE = ('\\', '^', '$', '*', '+', '?', '.', '[', ']', '(', ')', '{', '{', '|', '-') ENABLE_PYIMPORT = False ENABLE_JS2PY_ERRORS = False PY3 = sys.version_info >= (3,0) if PY3: basestring = str long = int xrange = range unicode = str ESPRIMA_VERSION = '2.2.0' DEBUG = False # Small naming convention changes # len -> leng # id -> d # type -> typ # str -> st true = True false = False null = None class PyJsParser: """ Usage: parser = PyJsParser() parser.parse('var JavaScriptCode = 5.1') """ def __init__(self): self.clean() def test(self, code): pprint(self.parse(code)) def clean(self): self.strict = None self.sourceType = None self.index = 0 self.lineNumber = 1 self.lineStart = 0 self.hasLineTerminator = None self.lastIndex = None self.lastLineNumber = None self.lastLineStart = None self.startIndex = None self.startLineNumber = None self.startLineStart = None self.scanning = None self.lookahead = None self.state = None self.extra = None self.isBindingElement = None self.isAssignmentTarget = None self.firstCoverInitializedNameError = None # 7.4 Comments def skipSingleLineComment(self, offset): start = self.index - offset; while self.index < self.length: ch = self.source[self.index]; self.index += 1 if isLineTerminator(ch): if (ord(ch) == 13 and ord(self.source[self.index]) == 10): self.index += 1 self.lineNumber += 1 self.hasLineTerminator = True self.lineStart = self.index return { 'type': 'Line', 'value': self.source[start + offset:self.index-2], 'leading': True, 'trailing': False, 'loc': None, } def skipMultiLineComment(self): start = self.index while self.index < self.length: ch = ord(self.source[self.index]) if isLineTerminator(ch): if (ch == 0x0D and ord(self.source[self.index + 1]) == 0x0A): self.index += 1 self.lineNumber += 1 self.index += 1 self.hasLineTerminator = True self.lineStart = self.index elif ch == 0x2A: # Block comment ends with '*/'. if ord(self.source[self.index + 1]) == 0x2F: self.index += 2 return { 'type': 'Block', 'value': self.source[start:self.index-2], 'leading': True, 'trailing': False, 'loc': None, } self.index += 1 else: self.index += 1 self.tolerateUnexpectedToken() def skipComment(self): self.hasLineTerminator = False startIndex = self.index start = (self.index == 0) comments = [] while self.index < self.length: ch = ord(self.source[self.index]) if isWhiteSpace(ch): self.index += 1 elif isLineTerminator(ch): self.hasLineTerminator = True self.index += 1 if (ch == 0x0D and ord(self.source[self.index]) == 0x0A): self.index += 1 self.lineNumber += 1 self.lineStart = self.index start = True elif (ch == 0x2F): # U+002F is '/' ch = ord(self.source[self.index + 1]) if (ch == 0x2F): self.index += 2 comments.append(self.skipSingleLineComment(2)) start = True elif (ch == 0x2A): # U+002A is '*' self.index += 2 comments.append(self.skipMultiLineComment()) else: break elif (start and ch == 0x2D): # U+002D is '-' # U+003E is '>' if (ord(self.source[self.index + 1]) == 0x2D) and (ord(self.source[self.index + 2]) == 0x3E): # '-->' is a single-line comment self.index += 3 self.skipSingleLineComment(3) else: break elif (ch == 0x3C): # U+003C is '<' if self.source[self.index + 1: self.index + 4] == '!--': #