recaptcha librerie
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
version = '4.0.1'
|
||||
__version__ = (4, 0, 1)
|
||||
|
||||
from .esprima import * # NOQA
|
||||
@@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals, print_function, division
|
||||
|
||||
import sys
|
||||
|
||||
from .esprima import parse, tokenize, Error, toDict
|
||||
from . import version
|
||||
|
||||
|
||||
def main():
|
||||
import json
|
||||
import time
|
||||
import optparse
|
||||
|
||||
usage = "usage: %prog [options] [file.js]"
|
||||
parser = optparse.OptionParser(usage=usage, version=version)
|
||||
parser.add_option("--comment", dest="comment",
|
||||
action="store_true", default=False,
|
||||
help="Gather all line and block comments in an array")
|
||||
parser.add_option("--attachComment", dest="attachComment",
|
||||
action="store_true", default=False,
|
||||
help="Attach comments to nodes")
|
||||
parser.add_option("--loc", dest="loc", default=False,
|
||||
action="store_true",
|
||||
help="Include line-column location info for each syntax node")
|
||||
parser.add_option("--range", dest="range", default=False,
|
||||
action="store_true",
|
||||
help="Include index-based range for each syntax node")
|
||||
parser.add_option("--raw", dest="raw", default=False,
|
||||
action="store_true",
|
||||
help="Display the raw value of literals")
|
||||
parser.add_option("--tokens", dest="tokens", default=False,
|
||||
action="store_true",
|
||||
help="List all tokens in an array")
|
||||
parser.add_option("--tolerant", dest="tolerant", default=False,
|
||||
action="store_true",
|
||||
help="Tolerate errors on a best-effort basis (experimental)")
|
||||
parser.add_option("--tokenize", dest="tokenize", default=False,
|
||||
action="store_true",
|
||||
help="Only tokenize, do not parse.")
|
||||
parser.add_option("--module", dest="sourceType", default='string',
|
||||
action="store_const", const='module',
|
||||
help="Tolerate errors on a best-effort basis (experimental)")
|
||||
parser.set_defaults(jsx=True, classProperties=True)
|
||||
opts, args = parser.parse_args()
|
||||
|
||||
if len(args) == 1:
|
||||
with open(args[0], 'rb') as f:
|
||||
code = f.read().decode('utf-8')
|
||||
elif sys.stdin.isatty():
|
||||
parser.print_help()
|
||||
return 64
|
||||
else:
|
||||
code = sys.stdin.read().decode('utf-8')
|
||||
|
||||
options = opts.__dict__
|
||||
do_tokenize = options.pop('tokenize')
|
||||
|
||||
t = time.time()
|
||||
try:
|
||||
if do_tokenize:
|
||||
del options['sourceType']
|
||||
del options['tokens']
|
||||
del options['raw']
|
||||
del options['jsx']
|
||||
res = toDict(tokenize(code, options=options))
|
||||
else:
|
||||
res = toDict(parse(code, options=options))
|
||||
except Error as e:
|
||||
res = e.toDict()
|
||||
dt = time.time() - t + 0.000000001
|
||||
|
||||
print(json.dumps(res, indent=4))
|
||||
print()
|
||||
print('Parsed everything in', round(dt, 5), 'seconds.')
|
||||
print('Thats %d characters per second' % (len(code) // dt))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
retval = main()
|
||||
sys.exit(retval)
|
||||
@@ -0,0 +1,125 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import sys
|
||||
|
||||
import unicodedata
|
||||
from collections import defaultdict
|
||||
|
||||
from .compat import uchr, xrange
|
||||
|
||||
# https://stackoverflow.com/questions/14245893/efficiently-list-all-characters-in-a-given-unicode-category
|
||||
U_CATEGORIES = defaultdict(list)
|
||||
for c in map(uchr, xrange(sys.maxunicode + 1)):
|
||||
U_CATEGORIES[unicodedata.category(c)].append(c)
|
||||
UNICODE_LETTER = set(
|
||||
U_CATEGORIES['Lu'] + U_CATEGORIES['Ll'] +
|
||||
U_CATEGORIES['Lt'] + U_CATEGORIES['Lm'] +
|
||||
U_CATEGORIES['Lo'] + U_CATEGORIES['Nl']
|
||||
)
|
||||
UNICODE_OTHER_ID_START = set((
|
||||
# Other_ID_Start
|
||||
'\u1885', '\u1886', '\u2118', '\u212E', '\u309B', '\u309C',
|
||||
# New in Unicode 8.0
|
||||
'\u08B3', '\u0AF9', '\u13F8', '\u9FCD', '\uAB60', '\U00010CC0', '\U000108E0', '\U0002B820',
|
||||
# New in Unicode 9.0
|
||||
'\u1C80', '\U000104DB', '\U0001E922',
|
||||
'\U0001EE00', '\U0001EE06', '\U0001EE0A',
|
||||
))
|
||||
UNICODE_OTHER_ID_CONTINUE = set((
|
||||
# Other_ID_Continue
|
||||
'\xB7', '\u0387', '\u1369', '\u136A', '\u136B', '\u136C',
|
||||
'\u136D', '\u136E', '\u136F', '\u1370', '\u1371', '\u19DA',
|
||||
# New in Unicode 8.0
|
||||
'\u08E3', '\uA69E', '\U00011730',
|
||||
# New in Unicode 9.0
|
||||
'\u08D4', '\u1DFB', '\uA8C5', '\U00011450',
|
||||
'\U0001EE03', '\U0001EE0B',
|
||||
))
|
||||
UNICODE_COMBINING_MARK = set(U_CATEGORIES['Mn'] + U_CATEGORIES['Mc'])
|
||||
UNICODE_DIGIT = set(U_CATEGORIES['Nd'])
|
||||
UNICODE_CONNECTOR_PUNCTUATION = set(U_CATEGORIES['Pc'])
|
||||
IDENTIFIER_START = UNICODE_LETTER.union(UNICODE_OTHER_ID_START).union(set(('$', '_', '\\')))
|
||||
IDENTIFIER_PART = IDENTIFIER_START.union(UNICODE_COMBINING_MARK).union(UNICODE_DIGIT).union(UNICODE_CONNECTOR_PUNCTUATION).union(set(('\u200D', '\u200C'))).union(UNICODE_OTHER_ID_CONTINUE)
|
||||
|
||||
WHITE_SPACE = set((
|
||||
'\x09', '\x0B', '\x0C', '\x20', '\xA0',
|
||||
'\u1680', '\u180E', '\u2000', '\u2001', '\u2002',
|
||||
'\u2003', '\u2004', '\u2005', '\u2006', '\u2007',
|
||||
'\u2008', '\u2009', '\u200A', '\u202F', '\u205F',
|
||||
'\u3000', '\uFEFF',
|
||||
))
|
||||
LINE_TERMINATOR = set(('\x0A', '\x0D', '\u2028', '\u2029'))
|
||||
|
||||
DECIMAL_CONV = dict((c, n) for n, c in enumerate('0123456789'))
|
||||
OCTAL_CONV = dict((c, n) for n, c in enumerate('01234567'))
|
||||
HEX_CONV = dict((c, n) for n, c in enumerate('0123456789abcdef'))
|
||||
for n, c in enumerate('ABCDEF', 10):
|
||||
HEX_CONV[c] = n
|
||||
DECIMAL_DIGIT = set(DECIMAL_CONV.keys())
|
||||
OCTAL_DIGIT = set(OCTAL_CONV.keys())
|
||||
HEX_DIGIT = set(HEX_CONV.keys())
|
||||
|
||||
|
||||
class Character:
|
||||
@staticmethod
|
||||
def fromCodePoint(code):
|
||||
return uchr(code)
|
||||
|
||||
# https://tc39.github.io/ecma262/#sec-white-space
|
||||
|
||||
@staticmethod
|
||||
def isWhiteSpace(ch):
|
||||
return ch in WHITE_SPACE
|
||||
|
||||
# https://tc39.github.io/ecma262/#sec-line-terminators
|
||||
|
||||
@staticmethod
|
||||
def isLineTerminator(ch):
|
||||
return ch in LINE_TERMINATOR
|
||||
|
||||
# https://tc39.github.io/ecma262/#sec-names-and-keywords
|
||||
|
||||
@staticmethod
|
||||
def isIdentifierStart(ch):
|
||||
return ch in IDENTIFIER_START
|
||||
|
||||
@staticmethod
|
||||
def isIdentifierPart(ch):
|
||||
return ch in IDENTIFIER_PART
|
||||
|
||||
# https://tc39.github.io/ecma262/#sec-literals-numeric-literals
|
||||
|
||||
@staticmethod
|
||||
def isDecimalDigit(ch):
|
||||
return ch in DECIMAL_DIGIT
|
||||
|
||||
@staticmethod
|
||||
def isHexDigit(ch):
|
||||
return ch in HEX_DIGIT
|
||||
|
||||
@staticmethod
|
||||
def isOctalDigit(ch):
|
||||
return ch in OCTAL_DIGIT
|
||||
@@ -0,0 +1,176 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .objects import Object
|
||||
from .nodes import Node
|
||||
from .syntax import Syntax
|
||||
|
||||
|
||||
class Comment(Node):
|
||||
def __init__(self, type, value, range=None, loc=None):
|
||||
self.type = type
|
||||
self.value = value
|
||||
self.range = range
|
||||
self.loc = loc
|
||||
|
||||
|
||||
class Entry(Object):
|
||||
def __init__(self, comment, start):
|
||||
self.comment = comment
|
||||
self.start = start
|
||||
|
||||
|
||||
class NodeInfo(Object):
|
||||
def __init__(self, node, start):
|
||||
self.node = node
|
||||
self.start = start
|
||||
|
||||
|
||||
class CommentHandler(object):
|
||||
def __init__(self):
|
||||
self.attach = False
|
||||
self.comments = []
|
||||
self.stack = []
|
||||
self.leading = []
|
||||
self.trailing = []
|
||||
|
||||
def insertInnerComments(self, node, metadata):
|
||||
# innnerComments for properties empty block
|
||||
# `function a(:/** comments **\/}`
|
||||
if node.type is Syntax.BlockStatement and not node.body:
|
||||
innerComments = []
|
||||
for i, entry in enumerate(self.leading):
|
||||
if metadata.end.offset >= entry.start:
|
||||
innerComments.append(entry.comment)
|
||||
self.leading[i] = None
|
||||
self.trailing[i] = None
|
||||
if innerComments:
|
||||
node.innerComments = innerComments
|
||||
self.leading = [v for v in self.leading if v is not None]
|
||||
self.trailing = [v for v in self.trailing if v is not None]
|
||||
|
||||
def findTrailingComments(self, metadata):
|
||||
trailingComments = []
|
||||
|
||||
if self.trailing:
|
||||
for i, entry in enumerate(self.trailing):
|
||||
if entry.start >= metadata.end.offset:
|
||||
trailingComments.append(entry.comment)
|
||||
if trailingComments:
|
||||
self.trailing = []
|
||||
return trailingComments
|
||||
|
||||
last = self.stack and self.stack[-1]
|
||||
if last and last.node.trailingComments:
|
||||
firstComment = last.node.trailingComments[0]
|
||||
if firstComment and firstComment.range[0] >= metadata.end.offset:
|
||||
trailingComments = last.node.trailingComments
|
||||
del last.node.trailingComments
|
||||
return trailingComments
|
||||
|
||||
def findLeadingComments(self, metadata):
|
||||
leadingComments = []
|
||||
|
||||
target = None
|
||||
while self.stack:
|
||||
entry = self.stack and self.stack[-1]
|
||||
if entry and entry.start >= metadata.start.offset:
|
||||
target = entry.node
|
||||
self.stack.pop()
|
||||
else:
|
||||
break
|
||||
|
||||
if target:
|
||||
if target.leadingComments:
|
||||
for i, comment in enumerate(target.leadingComments):
|
||||
if comment.range[1] <= metadata.start.offset:
|
||||
leadingComments.append(comment)
|
||||
target.leadingComments[i] = None
|
||||
if leadingComments:
|
||||
target.leadingComments = [v for v in target.leadingComments if v is not None]
|
||||
if not target.leadingComments:
|
||||
del target.leadingComments
|
||||
return leadingComments
|
||||
|
||||
for i, entry in enumerate(self.leading):
|
||||
if entry.start <= metadata.start.offset:
|
||||
leadingComments.append(entry.comment)
|
||||
self.leading[i] = None
|
||||
if leadingComments:
|
||||
self.leading = [v for v in self.leading if v is not None]
|
||||
|
||||
return leadingComments
|
||||
|
||||
def visitNode(self, node, metadata):
|
||||
if node.type is Syntax.Program and node.body:
|
||||
return
|
||||
|
||||
self.insertInnerComments(node, metadata)
|
||||
trailingComments = self.findTrailingComments(metadata)
|
||||
leadingComments = self.findLeadingComments(metadata)
|
||||
if leadingComments:
|
||||
node.leadingComments = leadingComments
|
||||
if trailingComments:
|
||||
node.trailingComments = trailingComments
|
||||
|
||||
self.stack.append(NodeInfo(
|
||||
node=node,
|
||||
start=metadata.start.offset
|
||||
))
|
||||
|
||||
def visitComment(self, node, metadata):
|
||||
type = 'Line' if node.type[0] == 'L' else 'Block'
|
||||
comment = Comment(
|
||||
type=type,
|
||||
value=node.value
|
||||
)
|
||||
if node.range:
|
||||
comment.range = node.range
|
||||
if node.loc:
|
||||
comment.loc = node.loc
|
||||
self.comments.append(comment)
|
||||
|
||||
if self.attach:
|
||||
entry = Entry(
|
||||
comment=Comment(
|
||||
type=type,
|
||||
value=node.value,
|
||||
range=[metadata.start.offset, metadata.end.offset]
|
||||
),
|
||||
start=metadata.start.offset
|
||||
)
|
||||
if node.loc:
|
||||
entry.comment.loc = node.loc
|
||||
node.type = type
|
||||
self.leading.append(entry)
|
||||
self.trailing.append(entry)
|
||||
|
||||
def visit(self, node, metadata):
|
||||
if node.type == 'LineComment':
|
||||
self.visitComment(node, metadata)
|
||||
elif node.type == 'BlockComment':
|
||||
self.visitComment(node, metadata)
|
||||
elif self.attach:
|
||||
self.visitNode(node, metadata)
|
||||
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import sys
|
||||
|
||||
PY3 = sys.version_info >= (3, 0)
|
||||
|
||||
if PY3:
|
||||
# Python 3:
|
||||
basestring = str
|
||||
long = int
|
||||
xrange = range
|
||||
unicode = str
|
||||
uchr = chr
|
||||
|
||||
def uord(ch):
|
||||
return ord(ch[0])
|
||||
|
||||
else:
|
||||
basestring = basestring
|
||||
long = long
|
||||
xrange = xrange
|
||||
unicode = unicode
|
||||
|
||||
try:
|
||||
# Python 2 UCS4:
|
||||
unichr(0x10000)
|
||||
uchr = unichr
|
||||
|
||||
def uord(ch):
|
||||
return ord(ch[0])
|
||||
|
||||
except ValueError:
|
||||
# Python 2 UCS2:
|
||||
def uchr(code):
|
||||
# UTF-16 Encoding
|
||||
if code <= 0xFFFF:
|
||||
return unichr(code)
|
||||
cu1 = ((code - 0x10000) >> 10) + 0xD800
|
||||
cu2 = ((code - 0x10000) & 1023) + 0xDC00
|
||||
return unichr(cu1) + unichr(cu2)
|
||||
|
||||
def uord(ch):
|
||||
cp = ord(ch[0])
|
||||
if cp >= 0xD800 and cp <= 0xDBFF:
|
||||
second = ord(ch[1])
|
||||
if second >= 0xDC00 and second <= 0xDFFF:
|
||||
first = cp
|
||||
cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000
|
||||
return cp
|
||||
@@ -0,0 +1,74 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .compat import unicode
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message, name=None, index=None, lineNumber=None, column=None, description=None):
|
||||
super(Error, self).__init__(message)
|
||||
self.message = message
|
||||
self.name = name
|
||||
self.index = index
|
||||
self.lineNumber = lineNumber
|
||||
self.column = column
|
||||
# self.description = description
|
||||
|
||||
def toString(self):
|
||||
return '%s: %s' % (self.__class__.__name__, self)
|
||||
|
||||
def toDict(self):
|
||||
d = dict((unicode(k), v) for k, v in self.__dict__.items() if v is not None)
|
||||
d['message'] = self.toString()
|
||||
return d
|
||||
|
||||
|
||||
class ErrorHandler:
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
self.tolerant = False
|
||||
|
||||
def recordError(self, error):
|
||||
self.errors.append(error.toDict())
|
||||
|
||||
def tolerate(self, error):
|
||||
if self.tolerant:
|
||||
self.recordError(error)
|
||||
else:
|
||||
raise error
|
||||
|
||||
def createError(self, index, line, col, description):
|
||||
msg = 'Line %s: %s' % (line, description)
|
||||
return Error(msg, index=index, lineNumber=line, column=col, description=description)
|
||||
|
||||
def throwError(self, index, line, col, description):
|
||||
raise self.createError(index, line, col, description)
|
||||
|
||||
def tolerateError(self, index, line, col, description):
|
||||
error = self.createError(index, line, col, description)
|
||||
if self.tolerant:
|
||||
self.recordError(error)
|
||||
else:
|
||||
raise error
|
||||
@@ -0,0 +1,125 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .comment_handler import CommentHandler
|
||||
from .error_handler import Error
|
||||
from .jsx_parser import JSXParser
|
||||
from .jsx_syntax import JSXSyntax
|
||||
from .objects import Array, toDict
|
||||
from .parser import Parser
|
||||
from .syntax import Syntax
|
||||
from .tokenizer import Tokenizer
|
||||
from .visitor import NodeVisitor
|
||||
from . import nodes
|
||||
from . import jsx_nodes
|
||||
|
||||
|
||||
__all__ = ['Syntax', 'JSXSyntax', 'Error', 'NodeVisitor', 'nodes', 'jsx_nodes',
|
||||
'parse', 'parseModule', 'parseScript', 'tokenize', 'toDict']
|
||||
|
||||
|
||||
def parse(code, options=None, delegate=None, **kwargs):
|
||||
options = {} if options is None else options.copy()
|
||||
options.update(kwargs)
|
||||
|
||||
# ESNext presset:
|
||||
if options.get('esnext', False):
|
||||
options['jsx'] = True
|
||||
options['classProperties'] = True
|
||||
|
||||
commentHandler = None
|
||||
|
||||
def proxyDelegate(node, metadata):
|
||||
if delegate:
|
||||
new_node = delegate(node, metadata)
|
||||
if new_node is not None:
|
||||
node = new_node
|
||||
if commentHandler:
|
||||
commentHandler.visit(node, metadata)
|
||||
return node
|
||||
|
||||
parserDelegate = None if delegate is None else proxyDelegate
|
||||
collectComment = options.get('comment', False)
|
||||
attachComment = options.get('attachComment', False)
|
||||
if collectComment or attachComment:
|
||||
commentHandler = CommentHandler()
|
||||
commentHandler.attach = attachComment
|
||||
options['comment'] = True
|
||||
parserDelegate = proxyDelegate
|
||||
|
||||
isModule = options.get('sourceType', 'script') == 'module'
|
||||
|
||||
if options.get('jsx', False):
|
||||
parser = JSXParser(code, options=options, delegate=parserDelegate)
|
||||
else:
|
||||
parser = Parser(code, options=options, delegate=parserDelegate)
|
||||
|
||||
ast = parser.parseModule() if isModule else parser.parseScript()
|
||||
|
||||
if collectComment and commentHandler:
|
||||
ast.comments = commentHandler.comments
|
||||
|
||||
if parser.config.tokens:
|
||||
ast.tokens = parser.tokens
|
||||
|
||||
if parser.config.tolerant:
|
||||
ast.errors = parser.errorHandler.errors
|
||||
|
||||
return ast
|
||||
|
||||
|
||||
def parseModule(code, options=None, delegate=None, **kwargs):
|
||||
kwargs['sourceType'] = 'module'
|
||||
return parse(code, options, delegate, **kwargs)
|
||||
|
||||
|
||||
def parseScript(code, options=None, delegate=None, **kwargs):
|
||||
kwargs['sourceType'] = 'script'
|
||||
return parse(code, options, delegate, **kwargs)
|
||||
|
||||
|
||||
def tokenize(code, options=None, delegate=None, **kwargs):
|
||||
options = {} if options is None else options.copy()
|
||||
options.update(kwargs)
|
||||
|
||||
tokenizer = Tokenizer(code, options)
|
||||
|
||||
tokens = Array()
|
||||
|
||||
try:
|
||||
while True:
|
||||
token = tokenizer.getNextToken()
|
||||
if not token:
|
||||
break
|
||||
if delegate:
|
||||
token = delegate(token)
|
||||
tokens.append(token)
|
||||
except Error as e:
|
||||
tokenizer.errorHandler.tolerate(e)
|
||||
|
||||
if tokenizer.errorHandler.tolerant:
|
||||
tokens.errors = tokenizer.errors()
|
||||
|
||||
return tokens
|
||||
@@ -0,0 +1,100 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .nodes import Node
|
||||
from .jsx_syntax import JSXSyntax
|
||||
|
||||
|
||||
class JSXClosingElement(Node):
|
||||
def __init__(self, name):
|
||||
self.type = JSXSyntax.JSXClosingElement
|
||||
self.name = name
|
||||
|
||||
|
||||
class JSXElement(Node):
|
||||
def __init__(self, openingElement, children, closingElement):
|
||||
self.type = JSXSyntax.JSXElement
|
||||
self.openingElement = openingElement
|
||||
self.children = children
|
||||
self.closingElement = closingElement
|
||||
|
||||
|
||||
class JSXEmptyExpression(Node):
|
||||
def __init__(self):
|
||||
self.type = JSXSyntax.JSXEmptyExpression
|
||||
|
||||
|
||||
class JSXExpressionContainer(Node):
|
||||
def __init__(self, expression):
|
||||
self.type = JSXSyntax.JSXExpressionContainer
|
||||
self.expression = expression
|
||||
|
||||
|
||||
class JSXIdentifier(Node):
|
||||
def __init__(self, name):
|
||||
self.type = JSXSyntax.JSXIdentifier
|
||||
self.name = name
|
||||
|
||||
|
||||
class JSXMemberExpression(Node):
|
||||
def __init__(self, object, property):
|
||||
self.type = JSXSyntax.JSXMemberExpression
|
||||
self.object = object
|
||||
self.property = property
|
||||
|
||||
|
||||
class JSXAttribute(Node):
|
||||
def __init__(self, name, value):
|
||||
self.type = JSXSyntax.JSXAttribute
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
|
||||
class JSXNamespacedName(Node):
|
||||
def __init__(self, namespace, name):
|
||||
self.type = JSXSyntax.JSXNamespacedName
|
||||
self.namespace = namespace
|
||||
self.name = name
|
||||
|
||||
|
||||
class JSXOpeningElement(Node):
|
||||
def __init__(self, name, selfClosing, attributes):
|
||||
self.type = JSXSyntax.JSXOpeningElement
|
||||
self.name = name
|
||||
self.selfClosing = selfClosing
|
||||
self.attributes = attributes
|
||||
|
||||
|
||||
class JSXSpreadAttribute(Node):
|
||||
def __init__(self, argument):
|
||||
self.type = JSXSyntax.JSXSpreadAttribute
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class JSXText(Node):
|
||||
def __init__(self, value, raw):
|
||||
self.type = JSXSyntax.JSXText
|
||||
self.value = value
|
||||
self.raw = raw
|
||||
@@ -0,0 +1,584 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .compat import uchr
|
||||
from .character import Character
|
||||
from . import jsx_nodes as JSXNode
|
||||
from .jsx_syntax import JSXSyntax
|
||||
from . import nodes as Node
|
||||
from .parser import Marker, Parser
|
||||
from .token import Token, TokenName
|
||||
from .xhtml_entities import XHTMLEntities
|
||||
|
||||
|
||||
class MetaJSXElement(object):
|
||||
def __init__(self, node=None, opening=None, closing=None, children=None):
|
||||
self.node = node
|
||||
self.opening = opening
|
||||
self.closing = closing
|
||||
self.children = children
|
||||
|
||||
|
||||
class JSXToken(object):
|
||||
Identifier = 100
|
||||
Text = 101
|
||||
|
||||
|
||||
class RawJSXToken(object):
|
||||
def __init__(self, type=None, value=None, lineNumber=None, lineStart=None, start=None, end=None):
|
||||
self.type = type
|
||||
self.value = value
|
||||
self.lineNumber = lineNumber
|
||||
self.lineStart = lineStart
|
||||
self.start = start
|
||||
self.end = end
|
||||
|
||||
|
||||
TokenName[JSXToken.Identifier] = "JSXIdentifier"
|
||||
TokenName[JSXToken.Text] = "JSXText"
|
||||
|
||||
|
||||
# Fully qualified element name, e.g. <svg:path> returns "svg:path"
|
||||
def getQualifiedElementName(elementName):
|
||||
typ = elementName.type
|
||||
if typ is JSXSyntax.JSXIdentifier:
|
||||
id = elementName
|
||||
qualifiedName = id.name
|
||||
elif typ is JSXSyntax.JSXNamespacedName:
|
||||
ns = elementName
|
||||
qualifiedName = getQualifiedElementName(ns.namespace) + ':' + getQualifiedElementName(ns.name)
|
||||
elif typ is JSXSyntax.JSXMemberExpression:
|
||||
expr = elementName
|
||||
qualifiedName = getQualifiedElementName(expr.object) + '.' + getQualifiedElementName(expr.property)
|
||||
|
||||
return qualifiedName
|
||||
|
||||
|
||||
class JSXParser(Parser):
|
||||
def __init__(self, code, options, delegate):
|
||||
super(JSXParser, self).__init__(code, options, delegate)
|
||||
|
||||
def parsePrimaryExpression(self):
|
||||
return self.parseJSXRoot() if self.match('<') else super(JSXParser, self).parsePrimaryExpression()
|
||||
|
||||
def startJSX(self):
|
||||
# Unwind the scanner before the lookahead token.
|
||||
self.scanner.index = self.startMarker.index
|
||||
self.scanner.lineNumber = self.startMarker.line
|
||||
self.scanner.lineStart = self.startMarker.index - self.startMarker.column
|
||||
|
||||
def finishJSX(self):
|
||||
# Prime the next lookahead.
|
||||
self.nextToken()
|
||||
|
||||
def reenterJSX(self):
|
||||
self.startJSX()
|
||||
self.expectJSX('}')
|
||||
|
||||
# Pop the closing '}' added from the lookahead.
|
||||
if self.config.tokens:
|
||||
self.tokens.pop()
|
||||
|
||||
def createJSXNode(self):
|
||||
self.collectComments()
|
||||
return Marker(
|
||||
index=self.scanner.index,
|
||||
line=self.scanner.lineNumber,
|
||||
column=self.scanner.index - self.scanner.lineStart
|
||||
)
|
||||
|
||||
def createJSXChildNode(self):
|
||||
return Marker(
|
||||
index=self.scanner.index,
|
||||
line=self.scanner.lineNumber,
|
||||
column=self.scanner.index - self.scanner.lineStart
|
||||
)
|
||||
|
||||
def scanXHTMLEntity(self, quote):
|
||||
result = '&'
|
||||
|
||||
valid = True
|
||||
terminated = False
|
||||
numeric = False
|
||||
hex = False
|
||||
|
||||
while not self.scanner.eof() and valid and not terminated:
|
||||
ch = self.scanner.source[self.scanner.index]
|
||||
if ch == quote:
|
||||
break
|
||||
|
||||
terminated = (ch == ';')
|
||||
result += ch
|
||||
self.scanner.index += 1
|
||||
if not terminated:
|
||||
length = len(result)
|
||||
if length == 2:
|
||||
# e.g. '{'
|
||||
numeric = (ch == '#')
|
||||
elif length == 3:
|
||||
if numeric:
|
||||
# e.g. 'A'
|
||||
hex = ch == 'x'
|
||||
valid = hex or Character.isDecimalDigit(ch)
|
||||
numeric = numeric and not hex
|
||||
else:
|
||||
valid = valid and not (numeric and not Character.isDecimalDigit(ch))
|
||||
valid = valid and not (hex and not Character.isHexDigit(ch))
|
||||
|
||||
if valid and terminated and len(result) > 2:
|
||||
# e.g. 'A' becomes just '#x41'
|
||||
st = result[1:-1]
|
||||
if numeric and len(st) > 1:
|
||||
result = uchr(int(st[1:], 10))
|
||||
elif hex and len(st) > 2:
|
||||
result = uchr(int(st[2:], 16))
|
||||
elif not numeric and not hex and st in XHTMLEntities:
|
||||
result = XHTMLEntities[st]
|
||||
|
||||
return result
|
||||
|
||||
# Scan the next JSX token. This replaces Scanner#lex when in JSX mode.
|
||||
|
||||
def lexJSX(self):
|
||||
ch = self.scanner.source[self.scanner.index]
|
||||
|
||||
# < > / : = { }
|
||||
if ch in ('<', '>', '/', ':', '=', '{', '}'):
|
||||
value = self.scanner.source[self.scanner.index]
|
||||
self.scanner.index += 1
|
||||
return RawJSXToken(
|
||||
type=Token.Punctuator,
|
||||
value=value,
|
||||
lineNumber=self.scanner.lineNumber,
|
||||
lineStart=self.scanner.lineStart,
|
||||
start=self.scanner.index - 1,
|
||||
end=self.scanner.index
|
||||
)
|
||||
|
||||
# " '
|
||||
if ch in ('\'', '"'):
|
||||
start = self.scanner.index
|
||||
quote = self.scanner.source[self.scanner.index]
|
||||
self.scanner.index += 1
|
||||
str = ''
|
||||
while not self.scanner.eof():
|
||||
ch = self.scanner.source[self.scanner.index]
|
||||
self.scanner.index += 1
|
||||
if ch == quote:
|
||||
break
|
||||
elif ch == '&':
|
||||
str += self.scanXHTMLEntity(quote)
|
||||
else:
|
||||
str += ch
|
||||
|
||||
return RawJSXToken(
|
||||
type=Token.StringLiteral,
|
||||
value=str,
|
||||
lineNumber=self.scanner.lineNumber,
|
||||
lineStart=self.scanner.lineStart,
|
||||
start=start,
|
||||
end=self.scanner.index
|
||||
)
|
||||
|
||||
# ... or .
|
||||
if ch == '.':
|
||||
start = self.scanner.index
|
||||
if self.scanner.source[start + 1:start + 3] == '..':
|
||||
value = '...'
|
||||
self.scanner.index += 3
|
||||
else:
|
||||
value = '.'
|
||||
self.scanner.index += 1
|
||||
return RawJSXToken(
|
||||
type=Token.Punctuator,
|
||||
value=value,
|
||||
lineNumber=self.scanner.lineNumber,
|
||||
lineStart=self.scanner.lineStart,
|
||||
start=start,
|
||||
end=self.scanner.index
|
||||
)
|
||||
|
||||
# `
|
||||
if ch == '`':
|
||||
# Only placeholder, since it will be rescanned as a real assignment expression.
|
||||
return RawJSXToken(
|
||||
type=Token.Template,
|
||||
value='',
|
||||
lineNumber=self.scanner.lineNumber,
|
||||
lineStart=self.scanner.lineStart,
|
||||
start=self.scanner.index,
|
||||
end=self.scanner.index
|
||||
)
|
||||
|
||||
# Identifier can not contain backslash (char code 92).
|
||||
if Character.isIdentifierStart(ch) and ch != '\\':
|
||||
start = self.scanner.index
|
||||
self.scanner.index += 1
|
||||
while not self.scanner.eof():
|
||||
ch = self.scanner.source[self.scanner.index]
|
||||
if Character.isIdentifierPart(ch) and ch != '\\':
|
||||
self.scanner.index += 1
|
||||
elif ch == '-':
|
||||
# Hyphen (char code 45) can be part of an identifier.
|
||||
self.scanner.index += 1
|
||||
else:
|
||||
break
|
||||
|
||||
id = self.scanner.source[start:self.scanner.index]
|
||||
return RawJSXToken(
|
||||
type=JSXToken.Identifier,
|
||||
value=id,
|
||||
lineNumber=self.scanner.lineNumber,
|
||||
lineStart=self.scanner.lineStart,
|
||||
start=start,
|
||||
end=self.scanner.index
|
||||
)
|
||||
|
||||
return self.scanner.lex()
|
||||
|
||||
def nextJSXToken(self):
|
||||
self.collectComments()
|
||||
|
||||
self.startMarker.index = self.scanner.index
|
||||
self.startMarker.line = self.scanner.lineNumber
|
||||
self.startMarker.column = self.scanner.index - self.scanner.lineStart
|
||||
token = self.lexJSX()
|
||||
self.lastMarker.index = self.scanner.index
|
||||
self.lastMarker.line = self.scanner.lineNumber
|
||||
self.lastMarker.column = self.scanner.index - self.scanner.lineStart
|
||||
|
||||
if self.config.tokens:
|
||||
self.tokens.append(self.convertToken(token))
|
||||
|
||||
return token
|
||||
|
||||
def nextJSXText(self):
|
||||
self.startMarker.index = self.scanner.index
|
||||
self.startMarker.line = self.scanner.lineNumber
|
||||
self.startMarker.column = self.scanner.index - self.scanner.lineStart
|
||||
|
||||
start = self.scanner.index
|
||||
|
||||
text = ''
|
||||
while not self.scanner.eof():
|
||||
ch = self.scanner.source[self.scanner.index]
|
||||
if ch in ('{', '<'):
|
||||
break
|
||||
|
||||
self.scanner.index += 1
|
||||
text += ch
|
||||
if Character.isLineTerminator(ch):
|
||||
self.scanner.lineNumber += 1
|
||||
if ch == '\r' and self.scanner.source[self.scanner.index] == '\n':
|
||||
self.scanner.index += 1
|
||||
|
||||
self.scanner.lineStart = self.scanner.index
|
||||
|
||||
self.lastMarker.index = self.scanner.index
|
||||
self.lastMarker.line = self.scanner.lineNumber
|
||||
self.lastMarker.column = self.scanner.index - self.scanner.lineStart
|
||||
|
||||
token = RawJSXToken(
|
||||
type=JSXToken.Text,
|
||||
value=text,
|
||||
lineNumber=self.scanner.lineNumber,
|
||||
lineStart=self.scanner.lineStart,
|
||||
start=start,
|
||||
end=self.scanner.index
|
||||
)
|
||||
|
||||
if text and self.config.tokens:
|
||||
self.tokens.append(self.convertToken(token))
|
||||
|
||||
return token
|
||||
|
||||
def peekJSXToken(self):
|
||||
state = self.scanner.saveState()
|
||||
self.scanner.scanComments()
|
||||
next = self.lexJSX()
|
||||
self.scanner.restoreState(state)
|
||||
|
||||
return next
|
||||
|
||||
# Expect the next JSX token to match the specified punctuator.
|
||||
# If not, an exception will be thrown.
|
||||
|
||||
def expectJSX(self, value):
|
||||
token = self.nextJSXToken()
|
||||
if token.type is not Token.Punctuator or token.value != value:
|
||||
self.throwUnexpectedToken(token)
|
||||
|
||||
# Return True if the next JSX token matches the specified punctuator.
|
||||
|
||||
def matchJSX(self, *value):
|
||||
next = self.peekJSXToken()
|
||||
return next.type is Token.Punctuator and next.value in value
|
||||
|
||||
def parseJSXIdentifier(self):
|
||||
node = self.createJSXNode()
|
||||
token = self.nextJSXToken()
|
||||
if token.type is not JSXToken.Identifier:
|
||||
self.throwUnexpectedToken(token)
|
||||
|
||||
return self.finalize(node, JSXNode.JSXIdentifier(token.value))
|
||||
|
||||
def parseJSXElementName(self):
|
||||
node = self.createJSXNode()
|
||||
elementName = self.parseJSXIdentifier()
|
||||
|
||||
if self.matchJSX(':'):
|
||||
namespace = elementName
|
||||
self.expectJSX(':')
|
||||
name = self.parseJSXIdentifier()
|
||||
elementName = self.finalize(node, JSXNode.JSXNamespacedName(namespace, name))
|
||||
elif self.matchJSX('.'):
|
||||
while self.matchJSX('.'):
|
||||
object = elementName
|
||||
self.expectJSX('.')
|
||||
property = self.parseJSXIdentifier()
|
||||
elementName = self.finalize(node, JSXNode.JSXMemberExpression(object, property))
|
||||
|
||||
return elementName
|
||||
|
||||
def parseJSXAttributeName(self):
|
||||
node = self.createJSXNode()
|
||||
|
||||
identifier = self.parseJSXIdentifier()
|
||||
if self.matchJSX(':'):
|
||||
namespace = identifier
|
||||
self.expectJSX(':')
|
||||
name = self.parseJSXIdentifier()
|
||||
attributeName = self.finalize(node, JSXNode.JSXNamespacedName(namespace, name))
|
||||
else:
|
||||
attributeName = identifier
|
||||
|
||||
return attributeName
|
||||
|
||||
def parseJSXStringLiteralAttribute(self):
|
||||
node = self.createJSXNode()
|
||||
token = self.nextJSXToken()
|
||||
if token.type is not Token.StringLiteral:
|
||||
self.throwUnexpectedToken(token)
|
||||
|
||||
raw = self.getTokenRaw(token)
|
||||
return self.finalize(node, Node.Literal(token.value, raw))
|
||||
|
||||
def parseJSXExpressionAttribute(self):
|
||||
node = self.createJSXNode()
|
||||
|
||||
self.expectJSX('{')
|
||||
self.finishJSX()
|
||||
|
||||
if self.match('}'):
|
||||
self.tolerateError('JSX attributes must only be assigned a non-empty expression')
|
||||
|
||||
expression = self.parseAssignmentExpression()
|
||||
self.reenterJSX()
|
||||
|
||||
return self.finalize(node, JSXNode.JSXExpressionContainer(expression))
|
||||
|
||||
def parseJSXAttributeValue(self):
|
||||
if self.matchJSX('{'):
|
||||
return self.parseJSXExpressionAttribute()
|
||||
if self.matchJSX('<'):
|
||||
return self.parseJSXElement()
|
||||
|
||||
return self.parseJSXStringLiteralAttribute()
|
||||
|
||||
def parseJSXNameValueAttribute(self):
|
||||
node = self.createJSXNode()
|
||||
name = self.parseJSXAttributeName()
|
||||
value = None
|
||||
if self.matchJSX('='):
|
||||
self.expectJSX('=')
|
||||
value = self.parseJSXAttributeValue()
|
||||
|
||||
return self.finalize(node, JSXNode.JSXAttribute(name, value))
|
||||
|
||||
def parseJSXSpreadAttribute(self):
|
||||
node = self.createJSXNode()
|
||||
self.expectJSX('{')
|
||||
self.expectJSX('...')
|
||||
|
||||
self.finishJSX()
|
||||
argument = self.parseAssignmentExpression()
|
||||
self.reenterJSX()
|
||||
|
||||
return self.finalize(node, JSXNode.JSXSpreadAttribute(argument))
|
||||
|
||||
def parseJSXAttributes(self):
|
||||
attributes = []
|
||||
|
||||
while not self.matchJSX('/', '>'):
|
||||
attribute = self.parseJSXSpreadAttribute() if self.matchJSX('{') else self.parseJSXNameValueAttribute()
|
||||
attributes.append(attribute)
|
||||
|
||||
return attributes
|
||||
|
||||
def parseJSXOpeningElement(self):
|
||||
node = self.createJSXNode()
|
||||
|
||||
self.expectJSX('<')
|
||||
name = self.parseJSXElementName()
|
||||
attributes = self.parseJSXAttributes()
|
||||
selfClosing = self.matchJSX('/')
|
||||
if selfClosing:
|
||||
self.expectJSX('/')
|
||||
|
||||
self.expectJSX('>')
|
||||
|
||||
return self.finalize(node, JSXNode.JSXOpeningElement(name, selfClosing, attributes))
|
||||
|
||||
def parseJSXBoundaryElement(self):
|
||||
node = self.createJSXNode()
|
||||
|
||||
self.expectJSX('<')
|
||||
if self.matchJSX('/'):
|
||||
self.expectJSX('/')
|
||||
elementName = self.parseJSXElementName()
|
||||
self.expectJSX('>')
|
||||
return self.finalize(node, JSXNode.JSXClosingElement(elementName))
|
||||
|
||||
name = self.parseJSXElementName()
|
||||
attributes = self.parseJSXAttributes()
|
||||
selfClosing = self.matchJSX('/')
|
||||
if selfClosing:
|
||||
self.expectJSX('/')
|
||||
|
||||
self.expectJSX('>')
|
||||
|
||||
return self.finalize(node, JSXNode.JSXOpeningElement(name, selfClosing, attributes))
|
||||
|
||||
def parseJSXEmptyExpression(self):
|
||||
node = self.createJSXChildNode()
|
||||
self.collectComments()
|
||||
self.lastMarker.index = self.scanner.index
|
||||
self.lastMarker.line = self.scanner.lineNumber
|
||||
self.lastMarker.column = self.scanner.index - self.scanner.lineStart
|
||||
return self.finalize(node, JSXNode.JSXEmptyExpression())
|
||||
|
||||
def parseJSXExpressionContainer(self):
|
||||
node = self.createJSXNode()
|
||||
self.expectJSX('{')
|
||||
|
||||
if self.matchJSX('}'):
|
||||
expression = self.parseJSXEmptyExpression()
|
||||
self.expectJSX('}')
|
||||
else:
|
||||
self.finishJSX()
|
||||
expression = self.parseAssignmentExpression()
|
||||
self.reenterJSX()
|
||||
|
||||
return self.finalize(node, JSXNode.JSXExpressionContainer(expression))
|
||||
|
||||
def parseJSXChildren(self):
|
||||
children = []
|
||||
|
||||
while not self.scanner.eof():
|
||||
node = self.createJSXChildNode()
|
||||
token = self.nextJSXText()
|
||||
if token.start < token.end:
|
||||
raw = self.getTokenRaw(token)
|
||||
child = self.finalize(node, JSXNode.JSXText(token.value, raw))
|
||||
children.append(child)
|
||||
|
||||
if self.scanner.source[self.scanner.index] == '{':
|
||||
container = self.parseJSXExpressionContainer()
|
||||
children.append(container)
|
||||
else:
|
||||
break
|
||||
|
||||
return children
|
||||
|
||||
def parseComplexJSXElement(self, el):
|
||||
stack = []
|
||||
|
||||
while not self.scanner.eof():
|
||||
el.children.extend(self.parseJSXChildren())
|
||||
node = self.createJSXChildNode()
|
||||
element = self.parseJSXBoundaryElement()
|
||||
if element.type is JSXSyntax.JSXOpeningElement:
|
||||
opening = element
|
||||
if opening.selfClosing:
|
||||
child = self.finalize(node, JSXNode.JSXElement(opening, [], None))
|
||||
el.children.append(child)
|
||||
else:
|
||||
stack.append(el)
|
||||
el = MetaJSXElement(
|
||||
node=node,
|
||||
opening=opening,
|
||||
closing=None,
|
||||
children=[],
|
||||
)
|
||||
|
||||
if element.type is JSXSyntax.JSXClosingElement:
|
||||
el.closing = element
|
||||
open = getQualifiedElementName(el.opening.name)
|
||||
close = getQualifiedElementName(el.closing.name)
|
||||
if open != close:
|
||||
self.tolerateError('Expected corresponding JSX closing tag for %0', open)
|
||||
|
||||
if stack:
|
||||
child = self.finalize(el.node, JSXNode.JSXElement(el.opening, el.children, el.closing))
|
||||
el = stack[-1]
|
||||
el.children.append(child)
|
||||
stack.pop()
|
||||
else:
|
||||
break
|
||||
|
||||
return el
|
||||
|
||||
def parseJSXElement(self):
|
||||
node = self.createJSXNode()
|
||||
|
||||
opening = self.parseJSXOpeningElement()
|
||||
children = []
|
||||
closing = None
|
||||
|
||||
if not opening.selfClosing:
|
||||
el = self.parseComplexJSXElement(MetaJSXElement(
|
||||
node=node,
|
||||
opening=opening,
|
||||
closing=closing,
|
||||
children=children
|
||||
))
|
||||
children = el.children
|
||||
closing = el.closing
|
||||
|
||||
return self.finalize(node, JSXNode.JSXElement(opening, children, closing))
|
||||
|
||||
def parseJSXRoot(self):
|
||||
# Pop the opening '<' added from the lookahead.
|
||||
if self.config.tokens:
|
||||
self.tokens.pop()
|
||||
|
||||
self.startJSX()
|
||||
element = self.parseJSXElement()
|
||||
self.finishJSX()
|
||||
|
||||
return element
|
||||
|
||||
def isStartOfExpression(self):
|
||||
return super(JSXParser, self).isStartOfExpression() or self.match('<')
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
class JSXSyntax:
|
||||
JSXAttribute = "JSXAttribute"
|
||||
JSXClosingElement = "JSXClosingElement"
|
||||
JSXElement = "JSXElement"
|
||||
JSXEmptyExpression = "JSXEmptyExpression"
|
||||
JSXExpressionContainer = "JSXExpressionContainer"
|
||||
JSXIdentifier = "JSXIdentifier"
|
||||
JSXMemberExpression = "JSXMemberExpression"
|
||||
JSXNamespacedName = "JSXNamespacedName"
|
||||
JSXOpeningElement = "JSXOpeningElement"
|
||||
JSXSpreadAttribute = "JSXSpreadAttribute"
|
||||
JSXText = "JSXText"
|
||||
@@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
# Error messages should be identical to V8.
|
||||
class Messages:
|
||||
ObjectPatternAsRestParameter = "Unexpected token {"
|
||||
BadImportCallArity = "Unexpected token"
|
||||
BadGetterArity = "Getter must not have any formal parameters"
|
||||
BadSetterArity = "Setter must have exactly one formal parameter"
|
||||
BadSetterRestParameter = "Setter function argument must not be a rest parameter"
|
||||
ConstructorIsAsync = "Class constructor may not be an async method"
|
||||
ConstructorSpecialMethod = "Class constructor may not be an accessor"
|
||||
DeclarationMissingInitializer = "Missing initializer in %0 declaration"
|
||||
DefaultRestParameter = "Unexpected token ="
|
||||
DefaultRestProperty = "Unexpected token ="
|
||||
DuplicateBinding = "Duplicate binding %0"
|
||||
DuplicateConstructor = "A class may only have one constructor"
|
||||
DuplicateProtoProperty = "Duplicate __proto__ fields are not allowed in object literals"
|
||||
ForInOfLoopInitializer = "%0 loop variable declaration may not have an initializer"
|
||||
GeneratorInLegacyContext = "Generator declarations are not allowed in legacy contexts"
|
||||
IllegalBreak = "Illegal break statement"
|
||||
IllegalContinue = "Illegal continue statement"
|
||||
IllegalExportDeclaration = "Unexpected token"
|
||||
IllegalImportDeclaration = "Unexpected token"
|
||||
IllegalLanguageModeDirective = "Illegal 'use strict' directive in function with non-simple parameter list"
|
||||
IllegalReturn = "Illegal return statement"
|
||||
InvalidEscapedReservedWord = "Keyword must not contain escaped characters"
|
||||
InvalidHexEscapeSequence = "Invalid hexadecimal escape sequence"
|
||||
InvalidLHSInAssignment = "Invalid left-hand side in assignment"
|
||||
InvalidLHSInForIn = "Invalid left-hand side in for-in"
|
||||
InvalidLHSInForLoop = "Invalid left-hand side in for-loop"
|
||||
InvalidModuleSpecifier = "Unexpected token"
|
||||
InvalidRegExp = "Invalid regular expression"
|
||||
LetInLexicalBinding = "let is disallowed as a lexically bound name"
|
||||
MissingFromClause = "Unexpected token"
|
||||
MultipleDefaultsInSwitch = "More than one default clause in switch statement"
|
||||
NewlineAfterThrow = "Illegal newline after throw"
|
||||
NoAsAfterImportNamespace = "Unexpected token"
|
||||
NoCatchOrFinally = "Missing catch or finally after try"
|
||||
ParameterAfterRestParameter = "Rest parameter must be last formal parameter"
|
||||
PropertyAfterRestProperty = "Unexpected token"
|
||||
Redeclaration = "%0 '%1' has already been declared"
|
||||
StaticPrototype = "Classes may not have static property named prototype"
|
||||
StrictCatchVariable = "Catch variable may not be eval or arguments in strict mode"
|
||||
StrictDelete = "Delete of an unqualified identifier in strict mode."
|
||||
StrictFunction = "In strict mode code, functions can only be declared at top level or inside a block"
|
||||
StrictFunctionName = "Function name may not be eval or arguments in strict mode"
|
||||
StrictLHSAssignment = "Assignment to eval or arguments is not allowed in strict mode"
|
||||
StrictLHSPostfix = "Postfix increment/decrement may not have eval or arguments operand in strict mode"
|
||||
StrictLHSPrefix = "Prefix increment/decrement may not have eval or arguments operand in strict mode"
|
||||
StrictModeWith = "Strict mode code may not include a with statement"
|
||||
StrictOctalLiteral = "Octal literals are not allowed in strict mode."
|
||||
StrictParamDupe = "Strict mode function may not have duplicate parameter names"
|
||||
StrictParamName = "Parameter name eval or arguments is not allowed in strict mode"
|
||||
StrictReservedWord = "Use of future reserved word in strict mode"
|
||||
StrictVarName = "Variable name may not be eval or arguments in strict mode"
|
||||
TemplateOctalLiteral = "Octal literals are not allowed in template strings."
|
||||
UnexpectedEOS = "Unexpected end of input"
|
||||
UnexpectedIdentifier = "Unexpected identifier"
|
||||
UnexpectedNumber = "Unexpected number"
|
||||
UnexpectedReserved = "Unexpected reserved word"
|
||||
UnexpectedString = "Unexpected string"
|
||||
UnexpectedTemplate = "Unexpected quasi %0"
|
||||
UnexpectedToken = "Unexpected token %0"
|
||||
UnexpectedTokenIllegal = "Unexpected token ILLEGAL"
|
||||
UnknownLabel = "Undefined label '%0'"
|
||||
UnterminatedRegExp = "Invalid regular expression: missing /"
|
||||
@@ -0,0 +1,620 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .objects import Object
|
||||
from .syntax import Syntax
|
||||
from .scanner import RegExp
|
||||
|
||||
|
||||
class Node(Object):
|
||||
def __dir__(self):
|
||||
return list(self.__dict__.keys())
|
||||
|
||||
def __iter__(self):
|
||||
return self.__iter__
|
||||
|
||||
def keys(self):
|
||||
return self.__dict__.keys()
|
||||
|
||||
def items(self):
|
||||
return self.__dict__.items()
|
||||
|
||||
|
||||
class ArrayExpression(Node):
|
||||
def __init__(self, elements):
|
||||
self.type = Syntax.ArrayExpression
|
||||
self.elements = elements
|
||||
|
||||
|
||||
class ArrayPattern(Node):
|
||||
def __init__(self, elements):
|
||||
self.type = Syntax.ArrayPattern
|
||||
self.elements = elements
|
||||
|
||||
|
||||
class ArrowFunctionExpression(Node):
|
||||
def __init__(self, params, body, expression):
|
||||
self.type = Syntax.ArrowFunctionExpression
|
||||
self.generator = False
|
||||
self.isAsync = False
|
||||
self.params = params
|
||||
self.body = body
|
||||
self.expression = expression
|
||||
|
||||
|
||||
class AssignmentExpression(Node):
|
||||
def __init__(self, operator, left, right):
|
||||
self.type = Syntax.AssignmentExpression
|
||||
self.operator = operator
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
|
||||
class AssignmentPattern(Node):
|
||||
def __init__(self, left, right):
|
||||
self.type = Syntax.AssignmentPattern
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
|
||||
class AsyncArrowFunctionExpression(Node):
|
||||
def __init__(self, params, body, expression):
|
||||
self.type = Syntax.ArrowFunctionExpression
|
||||
self.generator = False
|
||||
self.isAsync = True
|
||||
self.params = params
|
||||
self.body = body
|
||||
self.expression = expression
|
||||
|
||||
|
||||
class AsyncFunctionDeclaration(Node):
|
||||
def __init__(self, id, params, body):
|
||||
self.type = Syntax.FunctionDeclaration
|
||||
self.generator = False
|
||||
self.expression = False
|
||||
self.isAsync = True
|
||||
self.id = id
|
||||
self.params = params
|
||||
self.body = body
|
||||
|
||||
|
||||
class AsyncFunctionExpression(Node):
|
||||
def __init__(self, id, params, body):
|
||||
self.type = Syntax.FunctionExpression
|
||||
self.generator = False
|
||||
self.expression = False
|
||||
self.isAsync = True
|
||||
self.id = id
|
||||
self.params = params
|
||||
self.body = body
|
||||
|
||||
|
||||
class AwaitExpression(Node):
|
||||
def __init__(self, argument):
|
||||
self.type = Syntax.AwaitExpression
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class BinaryExpression(Node):
|
||||
def __init__(self, operator, left, right):
|
||||
self.type = Syntax.LogicalExpression if operator in ('||', '&&') else Syntax.BinaryExpression
|
||||
self.operator = operator
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
|
||||
class BlockStatement(Node):
|
||||
def __init__(self, body):
|
||||
self.type = Syntax.BlockStatement
|
||||
self.body = body
|
||||
|
||||
|
||||
class BreakStatement(Node):
|
||||
def __init__(self, label):
|
||||
self.type = Syntax.BreakStatement
|
||||
self.label = label
|
||||
|
||||
|
||||
class CallExpression(Node):
|
||||
def __init__(self, callee, args):
|
||||
self.type = Syntax.CallExpression
|
||||
self.callee = callee
|
||||
self.arguments = args
|
||||
|
||||
|
||||
class CatchClause(Node):
|
||||
def __init__(self, param, body):
|
||||
self.type = Syntax.CatchClause
|
||||
self.param = param
|
||||
self.body = body
|
||||
|
||||
|
||||
class ClassBody(Node):
|
||||
def __init__(self, body):
|
||||
self.type = Syntax.ClassBody
|
||||
self.body = body
|
||||
|
||||
|
||||
class ClassDeclaration(Node):
|
||||
def __init__(self, id, superClass, body):
|
||||
self.type = Syntax.ClassDeclaration
|
||||
self.id = id
|
||||
self.superClass = superClass
|
||||
self.body = body
|
||||
|
||||
|
||||
class ClassExpression(Node):
|
||||
def __init__(self, id, superClass, body):
|
||||
self.type = Syntax.ClassExpression
|
||||
self.id = id
|
||||
self.superClass = superClass
|
||||
self.body = body
|
||||
|
||||
|
||||
class ComputedMemberExpression(Node):
|
||||
def __init__(self, object, property):
|
||||
self.type = Syntax.MemberExpression
|
||||
self.computed = True
|
||||
self.object = object
|
||||
self.property = property
|
||||
|
||||
|
||||
class ConditionalExpression(Node):
|
||||
def __init__(self, test, consequent, alternate):
|
||||
self.type = Syntax.ConditionalExpression
|
||||
self.test = test
|
||||
self.consequent = consequent
|
||||
self.alternate = alternate
|
||||
|
||||
|
||||
class ContinueStatement(Node):
|
||||
def __init__(self, label):
|
||||
self.type = Syntax.ContinueStatement
|
||||
self.label = label
|
||||
|
||||
|
||||
class DebuggerStatement(Node):
|
||||
def __init__(self):
|
||||
self.type = Syntax.DebuggerStatement
|
||||
|
||||
|
||||
class Directive(Node):
|
||||
def __init__(self, expression, directive):
|
||||
self.type = Syntax.ExpressionStatement
|
||||
self.expression = expression
|
||||
self.directive = directive
|
||||
|
||||
|
||||
class DoWhileStatement(Node):
|
||||
def __init__(self, body, test):
|
||||
self.type = Syntax.DoWhileStatement
|
||||
self.body = body
|
||||
self.test = test
|
||||
|
||||
|
||||
class EmptyStatement(Node):
|
||||
def __init__(self):
|
||||
self.type = Syntax.EmptyStatement
|
||||
|
||||
|
||||
class ExportAllDeclaration(Node):
|
||||
def __init__(self, source):
|
||||
self.type = Syntax.ExportAllDeclaration
|
||||
self.source = source
|
||||
|
||||
|
||||
class ExportDefaultDeclaration(Node):
|
||||
def __init__(self, declaration):
|
||||
self.type = Syntax.ExportDefaultDeclaration
|
||||
self.declaration = declaration
|
||||
|
||||
|
||||
class ExportNamedDeclaration(Node):
|
||||
def __init__(self, declaration, specifiers, source):
|
||||
self.type = Syntax.ExportNamedDeclaration
|
||||
self.declaration = declaration
|
||||
self.specifiers = specifiers
|
||||
self.source = source
|
||||
|
||||
|
||||
class ExportSpecifier(Node):
|
||||
def __init__(self, local, exported):
|
||||
self.type = Syntax.ExportSpecifier
|
||||
self.exported = exported
|
||||
self.local = local
|
||||
|
||||
|
||||
class ExportDefaultSpecifier(Node):
|
||||
def __init__(self, local):
|
||||
self.type = Syntax.ExportDefaultSpecifier
|
||||
self.local = local
|
||||
|
||||
|
||||
class ExpressionStatement(Node):
|
||||
def __init__(self, expression):
|
||||
self.type = Syntax.ExpressionStatement
|
||||
self.expression = expression
|
||||
|
||||
|
||||
class ForInStatement(Node):
|
||||
def __init__(self, left, right, body):
|
||||
self.type = Syntax.ForInStatement
|
||||
self.each = False
|
||||
self.left = left
|
||||
self.right = right
|
||||
self.body = body
|
||||
|
||||
|
||||
class ForOfStatement(Node):
|
||||
def __init__(self, left, right, body):
|
||||
self.type = Syntax.ForOfStatement
|
||||
self.left = left
|
||||
self.right = right
|
||||
self.body = body
|
||||
|
||||
|
||||
class ForStatement(Node):
|
||||
def __init__(self, init, test, update, body):
|
||||
self.type = Syntax.ForStatement
|
||||
self.init = init
|
||||
self.test = test
|
||||
self.update = update
|
||||
self.body = body
|
||||
|
||||
|
||||
class FunctionDeclaration(Node):
|
||||
def __init__(self, id, params, body, generator):
|
||||
self.type = Syntax.FunctionDeclaration
|
||||
self.expression = False
|
||||
self.isAsync = False
|
||||
self.id = id
|
||||
self.params = params
|
||||
self.body = body
|
||||
self.generator = generator
|
||||
|
||||
|
||||
class FunctionExpression(Node):
|
||||
def __init__(self, id, params, body, generator):
|
||||
self.type = Syntax.FunctionExpression
|
||||
self.expression = False
|
||||
self.isAsync = False
|
||||
self.id = id
|
||||
self.params = params
|
||||
self.body = body
|
||||
self.generator = generator
|
||||
|
||||
|
||||
class Identifier(Node):
|
||||
def __init__(self, name):
|
||||
self.type = Syntax.Identifier
|
||||
self.name = name
|
||||
|
||||
|
||||
class IfStatement(Node):
|
||||
def __init__(self, test, consequent, alternate):
|
||||
self.type = Syntax.IfStatement
|
||||
self.test = test
|
||||
self.consequent = consequent
|
||||
self.alternate = alternate
|
||||
|
||||
|
||||
class Import(Node):
|
||||
def __init__(self):
|
||||
self.type = Syntax.Import
|
||||
|
||||
|
||||
class ImportDeclaration(Node):
|
||||
def __init__(self, specifiers, source):
|
||||
self.type = Syntax.ImportDeclaration
|
||||
self.specifiers = specifiers
|
||||
self.source = source
|
||||
|
||||
|
||||
class ImportDefaultSpecifier(Node):
|
||||
def __init__(self, local):
|
||||
self.type = Syntax.ImportDefaultSpecifier
|
||||
self.local = local
|
||||
|
||||
|
||||
class ImportNamespaceSpecifier(Node):
|
||||
def __init__(self, local):
|
||||
self.type = Syntax.ImportNamespaceSpecifier
|
||||
self.local = local
|
||||
|
||||
|
||||
class ImportSpecifier(Node):
|
||||
def __init__(self, local, imported):
|
||||
self.type = Syntax.ImportSpecifier
|
||||
self.local = local
|
||||
self.imported = imported
|
||||
|
||||
|
||||
class LabeledStatement(Node):
|
||||
def __init__(self, label, body):
|
||||
self.type = Syntax.LabeledStatement
|
||||
self.label = label
|
||||
self.body = body
|
||||
|
||||
|
||||
class Literal(Node):
|
||||
def __init__(self, value, raw):
|
||||
self.type = Syntax.Literal
|
||||
self.value = value
|
||||
self.raw = raw
|
||||
|
||||
|
||||
class MetaProperty(Node):
|
||||
def __init__(self, meta, property):
|
||||
self.type = Syntax.MetaProperty
|
||||
self.meta = meta
|
||||
self.property = property
|
||||
|
||||
|
||||
class MethodDefinition(Node):
|
||||
def __init__(self, key, computed, value, kind, isStatic):
|
||||
self.type = Syntax.MethodDefinition
|
||||
self.key = key
|
||||
self.computed = computed
|
||||
self.value = value
|
||||
self.kind = kind
|
||||
self.static = isStatic
|
||||
|
||||
|
||||
class FieldDefinition(Node):
|
||||
def __init__(self, key, computed, value, kind, isStatic):
|
||||
self.type = Syntax.FieldDefinition
|
||||
self.key = key
|
||||
self.computed = computed
|
||||
self.value = value
|
||||
self.kind = kind
|
||||
self.static = isStatic
|
||||
|
||||
|
||||
class Module(Node):
|
||||
def __init__(self, body):
|
||||
self.type = Syntax.Program
|
||||
self.sourceType = 'module'
|
||||
self.body = body
|
||||
|
||||
|
||||
class NewExpression(Node):
|
||||
def __init__(self, callee, args):
|
||||
self.type = Syntax.NewExpression
|
||||
self.callee = callee
|
||||
self.arguments = args
|
||||
|
||||
|
||||
class ObjectExpression(Node):
|
||||
def __init__(self, properties):
|
||||
self.type = Syntax.ObjectExpression
|
||||
self.properties = properties
|
||||
|
||||
|
||||
class ObjectPattern(Node):
|
||||
def __init__(self, properties):
|
||||
self.type = Syntax.ObjectPattern
|
||||
self.properties = properties
|
||||
|
||||
|
||||
class Property(Node):
|
||||
def __init__(self, kind, key, computed, value, method, shorthand):
|
||||
self.type = Syntax.Property
|
||||
self.key = key
|
||||
self.computed = computed
|
||||
self.value = value
|
||||
self.kind = kind
|
||||
self.method = method
|
||||
self.shorthand = shorthand
|
||||
|
||||
|
||||
class RegexLiteral(Node):
|
||||
def __init__(self, value, raw, pattern, flags):
|
||||
self.type = Syntax.Literal
|
||||
self.value = value
|
||||
self.raw = raw
|
||||
self.regex = RegExp(
|
||||
pattern=pattern,
|
||||
flags=flags,
|
||||
)
|
||||
|
||||
|
||||
class RestElement(Node):
|
||||
def __init__(self, argument):
|
||||
self.type = Syntax.RestElement
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class ReturnStatement(Node):
|
||||
def __init__(self, argument):
|
||||
self.type = Syntax.ReturnStatement
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class Script(Node):
|
||||
def __init__(self, body):
|
||||
self.type = Syntax.Program
|
||||
self.sourceType = 'script'
|
||||
self.body = body
|
||||
|
||||
|
||||
class SequenceExpression(Node):
|
||||
def __init__(self, expressions):
|
||||
self.type = Syntax.SequenceExpression
|
||||
self.expressions = expressions
|
||||
|
||||
|
||||
class SpreadElement(Node):
|
||||
def __init__(self, argument):
|
||||
self.type = Syntax.SpreadElement
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class StaticMemberExpression(Node):
|
||||
def __init__(self, object, property):
|
||||
self.type = Syntax.MemberExpression
|
||||
self.computed = False
|
||||
self.object = object
|
||||
self.property = property
|
||||
|
||||
|
||||
class Super(Node):
|
||||
def __init__(self):
|
||||
self.type = Syntax.Super
|
||||
|
||||
|
||||
class SwitchCase(Node):
|
||||
def __init__(self, test, consequent):
|
||||
self.type = Syntax.SwitchCase
|
||||
self.test = test
|
||||
self.consequent = consequent
|
||||
|
||||
|
||||
class SwitchStatement(Node):
|
||||
def __init__(self, discriminant, cases):
|
||||
self.type = Syntax.SwitchStatement
|
||||
self.discriminant = discriminant
|
||||
self.cases = cases
|
||||
|
||||
|
||||
class TaggedTemplateExpression(Node):
|
||||
def __init__(self, tag, quasi):
|
||||
self.type = Syntax.TaggedTemplateExpression
|
||||
self.tag = tag
|
||||
self.quasi = quasi
|
||||
|
||||
|
||||
class TemplateElement(Node):
|
||||
class Value(Object):
|
||||
def __init__(self, raw, cooked):
|
||||
self.raw = raw
|
||||
self.cooked = cooked
|
||||
|
||||
def __init__(self, raw, cooked, tail):
|
||||
self.type = Syntax.TemplateElement
|
||||
self.value = TemplateElement.Value(raw, cooked)
|
||||
self.tail = tail
|
||||
|
||||
|
||||
class TemplateLiteral(Node):
|
||||
def __init__(self, quasis, expressions):
|
||||
self.type = Syntax.TemplateLiteral
|
||||
self.quasis = quasis
|
||||
self.expressions = expressions
|
||||
|
||||
|
||||
class ThisExpression(Node):
|
||||
def __init__(self):
|
||||
self.type = Syntax.ThisExpression
|
||||
|
||||
|
||||
class ThrowStatement(Node):
|
||||
def __init__(self, argument):
|
||||
self.type = Syntax.ThrowStatement
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class TryStatement(Node):
|
||||
def __init__(self, block, handler, finalizer):
|
||||
self.type = Syntax.TryStatement
|
||||
self.block = block
|
||||
self.handler = handler
|
||||
self.finalizer = finalizer
|
||||
|
||||
|
||||
class UnaryExpression(Node):
|
||||
def __init__(self, operator, argument):
|
||||
self.type = Syntax.UnaryExpression
|
||||
self.prefix = True
|
||||
self.operator = operator
|
||||
self.argument = argument
|
||||
|
||||
|
||||
class UpdateExpression(Node):
|
||||
def __init__(self, operator, argument, prefix):
|
||||
self.type = Syntax.UpdateExpression
|
||||
self.operator = operator
|
||||
self.argument = argument
|
||||
self.prefix = prefix
|
||||
|
||||
|
||||
class VariableDeclaration(Node):
|
||||
def __init__(self, declarations, kind):
|
||||
self.type = Syntax.VariableDeclaration
|
||||
self.declarations = declarations
|
||||
self.kind = kind
|
||||
|
||||
|
||||
class VariableDeclarator(Node):
|
||||
def __init__(self, id, init):
|
||||
self.type = Syntax.VariableDeclarator
|
||||
self.id = id
|
||||
self.init = init
|
||||
|
||||
|
||||
class WhileStatement(Node):
|
||||
def __init__(self, test, body):
|
||||
self.type = Syntax.WhileStatement
|
||||
self.test = test
|
||||
self.body = body
|
||||
|
||||
|
||||
class WithStatement(Node):
|
||||
def __init__(self, object, body):
|
||||
self.type = Syntax.WithStatement
|
||||
self.object = object
|
||||
self.body = body
|
||||
|
||||
|
||||
class YieldExpression(Node):
|
||||
def __init__(self, argument, delegate):
|
||||
self.type = Syntax.YieldExpression
|
||||
self.argument = argument
|
||||
self.delegate = delegate
|
||||
|
||||
|
||||
class ArrowParameterPlaceHolder(Node):
|
||||
def __init__(self, params):
|
||||
self.type = Syntax.ArrowParameterPlaceHolder
|
||||
self.params = params
|
||||
self.isAsync = False
|
||||
|
||||
|
||||
class AsyncArrowParameterPlaceHolder(Node):
|
||||
def __init__(self, params):
|
||||
self.type = Syntax.ArrowParameterPlaceHolder
|
||||
self.params = params
|
||||
self.isAsync = True
|
||||
|
||||
|
||||
class BlockComment(Node):
|
||||
def __init__(self, value):
|
||||
self.type = Syntax.BlockComment
|
||||
self.value = value
|
||||
|
||||
|
||||
class LineComment(Node):
|
||||
def __init__(self, value):
|
||||
self.type = Syntax.LineComment
|
||||
self.value = value
|
||||
@@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
|
||||
def toDict(value):
|
||||
from .visitor import ToDictVisitor
|
||||
return ToDictVisitor().visit(value)
|
||||
|
||||
|
||||
class Array(list):
|
||||
pass
|
||||
|
||||
|
||||
class Object(object):
|
||||
def toDict(self):
|
||||
from .visitor import ToDictVisitor
|
||||
return ToDictVisitor().visit(self)
|
||||
|
||||
def __repr__(self):
|
||||
from .visitor import ReprVisitor
|
||||
return ReprVisitor().visit(self)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return None
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
class Syntax:
|
||||
AssignmentExpression = "AssignmentExpression"
|
||||
AssignmentPattern = "AssignmentPattern"
|
||||
ArrayExpression = "ArrayExpression"
|
||||
ArrayPattern = "ArrayPattern"
|
||||
ArrowFunctionExpression = "ArrowFunctionExpression"
|
||||
AwaitExpression = "AwaitExpression"
|
||||
BlockStatement = "BlockStatement"
|
||||
BinaryExpression = "BinaryExpression"
|
||||
BreakStatement = "BreakStatement"
|
||||
CallExpression = "CallExpression"
|
||||
CatchClause = "CatchClause"
|
||||
ClassBody = "ClassBody"
|
||||
ClassDeclaration = "ClassDeclaration"
|
||||
ClassExpression = "ClassExpression"
|
||||
ConditionalExpression = "ConditionalExpression"
|
||||
ContinueStatement = "ContinueStatement"
|
||||
DoWhileStatement = "DoWhileStatement"
|
||||
DebuggerStatement = "DebuggerStatement"
|
||||
EmptyStatement = "EmptyStatement"
|
||||
ExportAllDeclaration = "ExportAllDeclaration"
|
||||
ExportDefaultDeclaration = "ExportDefaultDeclaration"
|
||||
ExportNamedDeclaration = "ExportNamedDeclaration"
|
||||
ExportSpecifier = "ExportSpecifier"
|
||||
ExportDefaultSpecifier = "ExportDefaultSpecifier"
|
||||
ExpressionStatement = "ExpressionStatement"
|
||||
ForStatement = "ForStatement"
|
||||
ForOfStatement = "ForOfStatement"
|
||||
ForInStatement = "ForInStatement"
|
||||
FunctionDeclaration = "FunctionDeclaration"
|
||||
FunctionExpression = "FunctionExpression"
|
||||
Identifier = "Identifier"
|
||||
IfStatement = "IfStatement"
|
||||
Import = "Import"
|
||||
ImportDeclaration = "ImportDeclaration"
|
||||
ImportDefaultSpecifier = "ImportDefaultSpecifier"
|
||||
ImportNamespaceSpecifier = "ImportNamespaceSpecifier"
|
||||
ImportSpecifier = "ImportSpecifier"
|
||||
Literal = "Literal"
|
||||
LabeledStatement = "LabeledStatement"
|
||||
LogicalExpression = "LogicalExpression"
|
||||
MemberExpression = "MemberExpression"
|
||||
MetaProperty = "MetaProperty"
|
||||
MethodDefinition = "MethodDefinition"
|
||||
FieldDefinition = "FieldDefinition"
|
||||
NewExpression = "NewExpression"
|
||||
ObjectExpression = "ObjectExpression"
|
||||
ObjectPattern = "ObjectPattern"
|
||||
Program = "Program"
|
||||
Property = "Property"
|
||||
RestElement = "RestElement"
|
||||
ReturnStatement = "ReturnStatement"
|
||||
SequenceExpression = "SequenceExpression"
|
||||
SpreadElement = "SpreadElement"
|
||||
Super = "Super"
|
||||
SwitchCase = "SwitchCase"
|
||||
SwitchStatement = "SwitchStatement"
|
||||
TaggedTemplateExpression = "TaggedTemplateExpression"
|
||||
TemplateElement = "TemplateElement"
|
||||
TemplateLiteral = "TemplateLiteral"
|
||||
ThisExpression = "ThisExpression"
|
||||
ThrowStatement = "ThrowStatement"
|
||||
TryStatement = "TryStatement"
|
||||
UnaryExpression = "UnaryExpression"
|
||||
UpdateExpression = "UpdateExpression"
|
||||
VariableDeclaration = "VariableDeclaration"
|
||||
VariableDeclarator = "VariableDeclarator"
|
||||
WhileStatement = "WhileStatement"
|
||||
WithStatement = "WithStatement"
|
||||
YieldExpression = "YieldExpression"
|
||||
|
||||
ArrowParameterPlaceHolder = "ArrowParameterPlaceHolder"
|
||||
BlockComment = "BlockComment"
|
||||
LineComment = "LineComment"
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
class Token:
|
||||
BooleanLiteral = 1
|
||||
EOF = 2
|
||||
Identifier = 3
|
||||
Keyword = 4
|
||||
NullLiteral = 5
|
||||
NumericLiteral = 6
|
||||
Punctuator = 7
|
||||
StringLiteral = 8
|
||||
RegularExpression = 9
|
||||
Template = 10
|
||||
|
||||
|
||||
TokenName = {}
|
||||
TokenName[Token.BooleanLiteral] = "Boolean"
|
||||
TokenName[Token.EOF] = "<end>"
|
||||
TokenName[Token.Identifier] = "Identifier"
|
||||
TokenName[Token.Keyword] = "Keyword"
|
||||
TokenName[Token.NullLiteral] = "Null"
|
||||
TokenName[Token.NumericLiteral] = "Numeric"
|
||||
TokenName[Token.Punctuator] = "Punctuator"
|
||||
TokenName[Token.StringLiteral] = "String"
|
||||
TokenName[Token.RegularExpression] = "RegularExpression"
|
||||
TokenName[Token.Template] = "Template"
|
||||
@@ -0,0 +1,193 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from collections import deque
|
||||
|
||||
from .objects import Object
|
||||
from .error_handler import ErrorHandler
|
||||
from .scanner import Scanner, SourceLocation, Position, RegExp
|
||||
from .token import Token, TokenName
|
||||
|
||||
|
||||
class BufferEntry(Object):
|
||||
def __init__(self, type, value, regex=None, range=None, loc=None):
|
||||
self.type = type
|
||||
self.value = value
|
||||
self.regex = regex
|
||||
self.range = range
|
||||
self.loc = loc
|
||||
|
||||
|
||||
class Reader(object):
|
||||
def __init__(self):
|
||||
self.values = []
|
||||
self.curly = self.paren = -1
|
||||
|
||||
# A function following one of those tokens is an expression.
|
||||
def beforeFunctionExpression(self, t):
|
||||
return t in (
|
||||
'(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
|
||||
'return', 'case', 'delete', 'throw', 'void',
|
||||
# assignment operators
|
||||
'=', '+=', '-=', '*=', '**=', '/=', '%=', '<<=', '>>=', '>>>=',
|
||||
'&=', '|=', '^=', ',',
|
||||
# binary/unary operators
|
||||
'+', '-', '*', '**', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
|
||||
'|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
|
||||
'<=', '<', '>', '!=', '!=='
|
||||
)
|
||||
|
||||
# Determine if forward slash (/) is an operator or part of a regular expression
|
||||
# https://github.com/mozilla/sweet.js/wiki/design
|
||||
def isRegexStart(self):
|
||||
if not self.values:
|
||||
return True
|
||||
|
||||
previous = self.values[-1]
|
||||
regex = previous is not None
|
||||
|
||||
if previous in (
|
||||
'this',
|
||||
']',
|
||||
):
|
||||
regex = False
|
||||
elif previous == ')':
|
||||
keyword = self.values[self.paren - 1]
|
||||
regex = keyword in ('if', 'while', 'for', 'with')
|
||||
|
||||
elif previous == '}':
|
||||
# Dividing a function by anything makes little sense,
|
||||
# but we have to check for that.
|
||||
regex = True
|
||||
if len(self.values) >= 3 and self.values[self.curly - 3] == 'function':
|
||||
# Anonymous function, e.g. function(){} /42
|
||||
check = self.values[self.curly - 4]
|
||||
regex = not self.beforeFunctionExpression(check) if check else False
|
||||
elif len(self.values) >= 4 and self.values[self.curly - 4] == 'function':
|
||||
# Named function, e.g. function f(){} /42/
|
||||
check = self.values[self.curly - 5]
|
||||
regex = not self.beforeFunctionExpression(check) if check else True
|
||||
|
||||
return regex
|
||||
|
||||
def append(self, token):
|
||||
if token.type in (Token.Punctuator, Token.Keyword):
|
||||
if token.value == '{':
|
||||
self.curly = len(self.values)
|
||||
elif token.value == '(':
|
||||
self.paren = len(self.values)
|
||||
self.values.append(token.value)
|
||||
else:
|
||||
self.values.append(None)
|
||||
|
||||
|
||||
class Config(Object):
|
||||
def __init__(self, tolerant=None, comment=None, range=None, loc=None, **options):
|
||||
self.tolerant = tolerant
|
||||
self.comment = comment
|
||||
self.range = range
|
||||
self.loc = loc
|
||||
for k, v in options.items():
|
||||
setattr(self, k, v)
|
||||
|
||||
|
||||
class Tokenizer(object):
|
||||
def __init__(self, code, options):
|
||||
self.config = Config(**options)
|
||||
|
||||
self.errorHandler = ErrorHandler()
|
||||
self.errorHandler.tolerant = self.config.tolerant
|
||||
self.scanner = Scanner(code, self.errorHandler)
|
||||
self.scanner.trackComment = self.config.comment
|
||||
|
||||
self.trackRange = self.config.range
|
||||
self.trackLoc = self.config.loc
|
||||
self.buffer = deque()
|
||||
self.reader = Reader()
|
||||
|
||||
def errors(self):
|
||||
return self.errorHandler.errors
|
||||
|
||||
def getNextToken(self):
|
||||
if not self.buffer:
|
||||
|
||||
comments = self.scanner.scanComments()
|
||||
if self.scanner.trackComment:
|
||||
for e in comments:
|
||||
value = self.scanner.source[e.slice[0]:e.slice[1]]
|
||||
comment = BufferEntry(
|
||||
type='BlockComment' if e.multiLine else 'LineComment',
|
||||
value=value
|
||||
)
|
||||
if self.trackRange:
|
||||
comment.range = e.range
|
||||
if self.trackLoc:
|
||||
comment.loc = e.loc
|
||||
self.buffer.append(comment)
|
||||
|
||||
if not self.scanner.eof():
|
||||
if self.trackLoc:
|
||||
loc = SourceLocation(
|
||||
start=Position(
|
||||
line=self.scanner.lineNumber,
|
||||
column=self.scanner.index - self.scanner.lineStart
|
||||
),
|
||||
end=Position(),
|
||||
)
|
||||
|
||||
maybeRegex = self.scanner.source[self.scanner.index] == '/' and self.reader.isRegexStart()
|
||||
if maybeRegex:
|
||||
state = self.scanner.saveState()
|
||||
try:
|
||||
token = self.scanner.scanRegExp()
|
||||
except Exception:
|
||||
self.scanner.restoreState(state)
|
||||
token = self.scanner.lex()
|
||||
else:
|
||||
token = self.scanner.lex()
|
||||
|
||||
self.reader.append(token)
|
||||
|
||||
entry = BufferEntry(
|
||||
type=TokenName[token.type],
|
||||
value=self.scanner.source[token.start:token.end]
|
||||
)
|
||||
if self.trackRange:
|
||||
entry.range = [token.start, token.end]
|
||||
if self.trackLoc:
|
||||
loc.end = Position(
|
||||
line=self.scanner.lineNumber,
|
||||
column=self.scanner.index - self.scanner.lineStart
|
||||
)
|
||||
entry.loc = loc
|
||||
if token.type is Token.RegularExpression:
|
||||
entry.regex = RegExp(
|
||||
pattern=token.pattern,
|
||||
flags=token.flags,
|
||||
)
|
||||
|
||||
self.buffer.append(entry)
|
||||
|
||||
return self.buffer.popleft() if self.buffer else None
|
||||
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import re
|
||||
|
||||
from .compat import unicode
|
||||
|
||||
|
||||
def format(messageFormat, *args):
|
||||
def formatter(m):
|
||||
formatter.idx += 1
|
||||
assert formatter.idx < len(args), 'Message reference must be in range'
|
||||
return unicode(args[formatter.idx])
|
||||
formatter.idx = -1
|
||||
return format.re.sub(formatter, messageFormat)
|
||||
|
||||
|
||||
format.re = re.compile(r'%(\d)')
|
||||
@@ -0,0 +1,288 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import json
|
||||
import types
|
||||
from collections import deque
|
||||
|
||||
from .objects import Object
|
||||
from .compat import PY3, unicode
|
||||
|
||||
|
||||
class VisitRecursionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Visited(object):
|
||||
def __init__(self, result):
|
||||
if isinstance(result, Visited):
|
||||
result = result.result
|
||||
self.result = result
|
||||
|
||||
|
||||
class Visitor(object):
|
||||
"""
|
||||
An Object visitor base class that walks the abstract syntax tree and calls a
|
||||
visitor function for every Object found. This function may return a value
|
||||
which is forwarded by the `visit` method.
|
||||
|
||||
This class is meant to be subclassed, with the subclass adding visitor
|
||||
methods.
|
||||
|
||||
Per default the visitor functions for the nodes are ``'visit_'`` +
|
||||
class name of the Object. So a `Module` Object visit function would
|
||||
be `visit_Module`. This behavior can be changed by overriding
|
||||
the `visit` method. If no visitor function exists for an Object
|
||||
(return value `None`) the `generic_visit` visitor is used instead.
|
||||
"""
|
||||
|
||||
def __call__(self, obj, metadata):
|
||||
return self.transform(obj, metadata)
|
||||
|
||||
def transform(self, obj, metadata):
|
||||
"""Transform an Object."""
|
||||
if isinstance(obj, Object):
|
||||
method = 'transform_' + obj.__class__.__name__
|
||||
transformer = getattr(self, method, self.transform_Object)
|
||||
new_obj = transformer(obj, metadata)
|
||||
if new_obj is not None and obj is not new_obj:
|
||||
obj = new_obj
|
||||
return obj
|
||||
|
||||
def transform_Object(self, obj, metadata):
|
||||
"""Called if no explicit transform function exists for an Object."""
|
||||
return obj
|
||||
|
||||
def generic_visit(self, obj):
|
||||
return self.visit(self.visit_Object(obj))
|
||||
|
||||
def visit(self, obj):
|
||||
"""Visit an Object."""
|
||||
if not hasattr(self, 'visitors'):
|
||||
self._visit_context = {}
|
||||
self._visit_count = 0
|
||||
try:
|
||||
self._visit_count += 1
|
||||
stack = deque()
|
||||
stack.append((obj, None))
|
||||
last_result = None
|
||||
while stack:
|
||||
try:
|
||||
last, visited = stack[-1]
|
||||
if isinstance(last, types.GeneratorType):
|
||||
stack.append((last.send(last_result), None))
|
||||
last_result = None
|
||||
elif isinstance(last, Visited):
|
||||
stack.pop()
|
||||
last_result = last.result
|
||||
elif isinstance(last, Object):
|
||||
if last in self._visit_context:
|
||||
if self._visit_context[last] == self.visit_Object:
|
||||
visitor = self.visit_RecursionError
|
||||
else:
|
||||
visitor = self.visit_Object
|
||||
else:
|
||||
method = 'visit_' + last.__class__.__name__
|
||||
visitor = getattr(self, method, self.visit_Object)
|
||||
self._visit_context[last] = visitor
|
||||
stack.pop()
|
||||
stack.append((visitor(last), last))
|
||||
else:
|
||||
method = 'visit_' + last.__class__.__name__
|
||||
visitor = getattr(self, method, self.visit_Generic)
|
||||
stack.pop()
|
||||
stack.append((visitor(last), None))
|
||||
except StopIteration:
|
||||
stack.pop()
|
||||
if visited and visited in self._visit_context:
|
||||
del self._visit_context[visited]
|
||||
return last_result
|
||||
finally:
|
||||
self._visit_count -= 1
|
||||
if self._visit_count <= 0:
|
||||
self._visit_context = {}
|
||||
|
||||
def visit_RecursionError(self, obj):
|
||||
raise VisitRecursionError
|
||||
|
||||
def visit_Object(self, obj):
|
||||
"""Called if no explicit visitor function exists for an Object."""
|
||||
yield obj.__dict__
|
||||
yield Visited(obj)
|
||||
|
||||
def visit_Generic(self, obj):
|
||||
"""Called if no explicit visitor function exists for an object."""
|
||||
yield Visited(obj)
|
||||
|
||||
def visit_list(self, obj):
|
||||
for item in obj:
|
||||
yield item
|
||||
yield Visited(obj)
|
||||
|
||||
visit_Array = visit_list
|
||||
|
||||
def visit_dict(self, obj):
|
||||
for field, value in list(obj.items()):
|
||||
if not field.startswith('_'):
|
||||
yield value
|
||||
yield Visited(obj)
|
||||
|
||||
|
||||
class NodeVisitor(Visitor):
|
||||
pass
|
||||
|
||||
|
||||
class ReprVisitor(Visitor):
|
||||
def visit(self, obj, indent=4, nl="\n", sp="", skip=()):
|
||||
self.level = 0
|
||||
if isinstance(indent, int):
|
||||
indent = " " * indent
|
||||
self.indent = indent
|
||||
self.nl = nl
|
||||
self.sp = sp
|
||||
self.skip = skip
|
||||
return super(ReprVisitor, self).visit(obj)
|
||||
|
||||
def visit_RecursionError(self, obj):
|
||||
yield Visited("...")
|
||||
|
||||
def visit_Object(self, obj):
|
||||
value_repr = yield obj.__dict__
|
||||
yield Visited(value_repr)
|
||||
|
||||
def visit_Generic(self, obj):
|
||||
yield Visited(repr(obj))
|
||||
|
||||
def visit_list(self, obj):
|
||||
indent1 = self.indent * self.level
|
||||
indent2 = indent1 + self.indent
|
||||
self.level += 1
|
||||
try:
|
||||
items = []
|
||||
for item in obj:
|
||||
v = yield item
|
||||
items.append(v)
|
||||
if items:
|
||||
value_repr = "[%s%s%s%s%s%s%s]" % (
|
||||
self.sp,
|
||||
self.nl,
|
||||
indent2,
|
||||
(",%s%s%s" % (self.nl, self.sp, indent2)).join(items),
|
||||
self.nl,
|
||||
indent1,
|
||||
self.sp,
|
||||
)
|
||||
else:
|
||||
value_repr = "[]"
|
||||
finally:
|
||||
self.level -= 1
|
||||
|
||||
yield Visited(value_repr)
|
||||
|
||||
visit_Array = visit_list
|
||||
|
||||
def visit_dict(self, obj):
|
||||
indent1 = self.indent * self.level
|
||||
indent2 = indent1 + self.indent
|
||||
self.level += 1
|
||||
try:
|
||||
items = []
|
||||
for k, item in obj.items():
|
||||
if item is not None and not k.startswith('_') and k not in self.skip:
|
||||
v = yield item
|
||||
items.append("%s: %s" % (k, v))
|
||||
if items:
|
||||
value_repr = "{%s%s%s%s%s%s%s}" % (
|
||||
self.sp,
|
||||
self.nl,
|
||||
indent2,
|
||||
(",%s%s%s" % (self.nl, self.sp, indent2)).join(items),
|
||||
self.nl,
|
||||
indent1,
|
||||
self.sp,
|
||||
)
|
||||
else:
|
||||
value_repr = "{}"
|
||||
finally:
|
||||
self.level -= 1
|
||||
|
||||
yield Visited(value_repr)
|
||||
|
||||
if PY3:
|
||||
def visit_str(self, obj):
|
||||
value_repr = json.dumps(obj)
|
||||
yield Visited(value_repr)
|
||||
else:
|
||||
def visit_unicode(self, obj):
|
||||
value_repr = json.dumps(obj)
|
||||
yield Visited(value_repr)
|
||||
|
||||
def visit_SourceLocation(self, obj):
|
||||
old_indent, self.indent = self.indent, ""
|
||||
old_nl, self.nl = self.nl, ""
|
||||
old_sp, self.sp = self.sp, ""
|
||||
try:
|
||||
yield obj
|
||||
finally:
|
||||
self.indent = old_indent
|
||||
self.nl = old_nl
|
||||
self.sp = old_sp
|
||||
|
||||
|
||||
class ToDictVisitor(Visitor):
|
||||
map = {
|
||||
'isAsync': 'async',
|
||||
'allowAwait': 'await',
|
||||
}
|
||||
|
||||
def visit_RecursionError(self, obj):
|
||||
yield Visited({
|
||||
'error': "Infinite recursion detected...",
|
||||
})
|
||||
|
||||
def visit_Object(self, obj):
|
||||
obj = yield obj.__dict__
|
||||
yield Visited(obj)
|
||||
|
||||
def visit_list(self, obj):
|
||||
items = []
|
||||
for item in obj:
|
||||
v = yield item
|
||||
items.append(v)
|
||||
yield Visited(items)
|
||||
|
||||
visit_Array = visit_list
|
||||
|
||||
def visit_dict(self, obj):
|
||||
items = []
|
||||
for k, item in obj.items():
|
||||
if item is not None and not k.startswith('_'):
|
||||
v = yield item
|
||||
k = unicode(k)
|
||||
items.append((self.map.get(k, k), v))
|
||||
yield Visited(dict(items))
|
||||
|
||||
def visit_SRE_Pattern(self, obj):
|
||||
yield Visited({})
|
||||
@@ -0,0 +1,281 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# Generated by generate-xhtml-entities.js. DO NOT MODIFY!
|
||||
|
||||
XHTMLEntities = {
|
||||
'quot': "\u0022",
|
||||
'amp': "\u0026",
|
||||
'apos': "\u0027",
|
||||
'gt': "\u003E",
|
||||
'nbsp': "\u00A0",
|
||||
'iexcl': "\u00A1",
|
||||
'cent': "\u00A2",
|
||||
'pound': "\u00A3",
|
||||
'curren': "\u00A4",
|
||||
'yen': "\u00A5",
|
||||
'brvbar': "\u00A6",
|
||||
'sect': "\u00A7",
|
||||
'uml': "\u00A8",
|
||||
'copy': "\u00A9",
|
||||
'ordf': "\u00AA",
|
||||
'laquo': "\u00AB",
|
||||
'not': "\u00AC",
|
||||
'shy': "\u00AD",
|
||||
'reg': "\u00AE",
|
||||
'macr': "\u00AF",
|
||||
'deg': "\u00B0",
|
||||
'plusmn': "\u00B1",
|
||||
'sup2': "\u00B2",
|
||||
'sup3': "\u00B3",
|
||||
'acute': "\u00B4",
|
||||
'micro': "\u00B5",
|
||||
'para': "\u00B6",
|
||||
'middot': "\u00B7",
|
||||
'cedil': "\u00B8",
|
||||
'sup1': "\u00B9",
|
||||
'ordm': "\u00BA",
|
||||
'raquo': "\u00BB",
|
||||
'frac14': "\u00BC",
|
||||
'frac12': "\u00BD",
|
||||
'frac34': "\u00BE",
|
||||
'iquest': "\u00BF",
|
||||
'Agrave': "\u00C0",
|
||||
'Aacute': "\u00C1",
|
||||
'Acirc': "\u00C2",
|
||||
'Atilde': "\u00C3",
|
||||
'Auml': "\u00C4",
|
||||
'Aring': "\u00C5",
|
||||
'AElig': "\u00C6",
|
||||
'Ccedil': "\u00C7",
|
||||
'Egrave': "\u00C8",
|
||||
'Eacute': "\u00C9",
|
||||
'Ecirc': "\u00CA",
|
||||
'Euml': "\u00CB",
|
||||
'Igrave': "\u00CC",
|
||||
'Iacute': "\u00CD",
|
||||
'Icirc': "\u00CE",
|
||||
'Iuml': "\u00CF",
|
||||
'ETH': "\u00D0",
|
||||
'Ntilde': "\u00D1",
|
||||
'Ograve': "\u00D2",
|
||||
'Oacute': "\u00D3",
|
||||
'Ocirc': "\u00D4",
|
||||
'Otilde': "\u00D5",
|
||||
'Ouml': "\u00D6",
|
||||
'times': "\u00D7",
|
||||
'Oslash': "\u00D8",
|
||||
'Ugrave': "\u00D9",
|
||||
'Uacute': "\u00DA",
|
||||
'Ucirc': "\u00DB",
|
||||
'Uuml': "\u00DC",
|
||||
'Yacute': "\u00DD",
|
||||
'THORN': "\u00DE",
|
||||
'szlig': "\u00DF",
|
||||
'agrave': "\u00E0",
|
||||
'aacute': "\u00E1",
|
||||
'acirc': "\u00E2",
|
||||
'atilde': "\u00E3",
|
||||
'auml': "\u00E4",
|
||||
'aring': "\u00E5",
|
||||
'aelig': "\u00E6",
|
||||
'ccedil': "\u00E7",
|
||||
'egrave': "\u00E8",
|
||||
'eacute': "\u00E9",
|
||||
'ecirc': "\u00EA",
|
||||
'euml': "\u00EB",
|
||||
'igrave': "\u00EC",
|
||||
'iacute': "\u00ED",
|
||||
'icirc': "\u00EE",
|
||||
'iuml': "\u00EF",
|
||||
'eth': "\u00F0",
|
||||
'ntilde': "\u00F1",
|
||||
'ograve': "\u00F2",
|
||||
'oacute': "\u00F3",
|
||||
'ocirc': "\u00F4",
|
||||
'otilde': "\u00F5",
|
||||
'ouml': "\u00F6",
|
||||
'divide': "\u00F7",
|
||||
'oslash': "\u00F8",
|
||||
'ugrave': "\u00F9",
|
||||
'uacute': "\u00FA",
|
||||
'ucirc': "\u00FB",
|
||||
'uuml': "\u00FC",
|
||||
'yacute': "\u00FD",
|
||||
'thorn': "\u00FE",
|
||||
'yuml': "\u00FF",
|
||||
'OElig': "\u0152",
|
||||
'oelig': "\u0153",
|
||||
'Scaron': "\u0160",
|
||||
'scaron': "\u0161",
|
||||
'Yuml': "\u0178",
|
||||
'fnof': "\u0192",
|
||||
'circ': "\u02C6",
|
||||
'tilde': "\u02DC",
|
||||
'Alpha': "\u0391",
|
||||
'Beta': "\u0392",
|
||||
'Gamma': "\u0393",
|
||||
'Delta': "\u0394",
|
||||
'Epsilon': "\u0395",
|
||||
'Zeta': "\u0396",
|
||||
'Eta': "\u0397",
|
||||
'Theta': "\u0398",
|
||||
'Iota': "\u0399",
|
||||
'Kappa': "\u039A",
|
||||
'Lambda': "\u039B",
|
||||
'Mu': "\u039C",
|
||||
'Nu': "\u039D",
|
||||
'Xi': "\u039E",
|
||||
'Omicron': "\u039F",
|
||||
'Pi': "\u03A0",
|
||||
'Rho': "\u03A1",
|
||||
'Sigma': "\u03A3",
|
||||
'Tau': "\u03A4",
|
||||
'Upsilon': "\u03A5",
|
||||
'Phi': "\u03A6",
|
||||
'Chi': "\u03A7",
|
||||
'Psi': "\u03A8",
|
||||
'Omega': "\u03A9",
|
||||
'alpha': "\u03B1",
|
||||
'beta': "\u03B2",
|
||||
'gamma': "\u03B3",
|
||||
'delta': "\u03B4",
|
||||
'epsilon': "\u03B5",
|
||||
'zeta': "\u03B6",
|
||||
'eta': "\u03B7",
|
||||
'theta': "\u03B8",
|
||||
'iota': "\u03B9",
|
||||
'kappa': "\u03BA",
|
||||
'lambda': "\u03BB",
|
||||
'mu': "\u03BC",
|
||||
'nu': "\u03BD",
|
||||
'xi': "\u03BE",
|
||||
'omicron': "\u03BF",
|
||||
'pi': "\u03C0",
|
||||
'rho': "\u03C1",
|
||||
'sigmaf': "\u03C2",
|
||||
'sigma': "\u03C3",
|
||||
'tau': "\u03C4",
|
||||
'upsilon': "\u03C5",
|
||||
'phi': "\u03C6",
|
||||
'chi': "\u03C7",
|
||||
'psi': "\u03C8",
|
||||
'omega': "\u03C9",
|
||||
'thetasym': "\u03D1",
|
||||
'upsih': "\u03D2",
|
||||
'piv': "\u03D6",
|
||||
'ensp': "\u2002",
|
||||
'emsp': "\u2003",
|
||||
'thinsp': "\u2009",
|
||||
'zwnj': "\u200C",
|
||||
'zwj': "\u200D",
|
||||
'lrm': "\u200E",
|
||||
'rlm': "\u200F",
|
||||
'ndash': "\u2013",
|
||||
'mdash': "\u2014",
|
||||
'lsquo': "\u2018",
|
||||
'rsquo': "\u2019",
|
||||
'sbquo': "\u201A",
|
||||
'ldquo': "\u201C",
|
||||
'rdquo': "\u201D",
|
||||
'bdquo': "\u201E",
|
||||
'dagger': "\u2020",
|
||||
'Dagger': "\u2021",
|
||||
'bull': "\u2022",
|
||||
'hellip': "\u2026",
|
||||
'permil': "\u2030",
|
||||
'prime': "\u2032",
|
||||
'Prime': "\u2033",
|
||||
'lsaquo': "\u2039",
|
||||
'rsaquo': "\u203A",
|
||||
'oline': "\u203E",
|
||||
'frasl': "\u2044",
|
||||
'euro': "\u20AC",
|
||||
'image': "\u2111",
|
||||
'weierp': "\u2118",
|
||||
'real': "\u211C",
|
||||
'trade': "\u2122",
|
||||
'alefsym': "\u2135",
|
||||
'larr': "\u2190",
|
||||
'uarr': "\u2191",
|
||||
'rarr': "\u2192",
|
||||
'darr': "\u2193",
|
||||
'harr': "\u2194",
|
||||
'crarr': "\u21B5",
|
||||
'lArr': "\u21D0",
|
||||
'uArr': "\u21D1",
|
||||
'rArr': "\u21D2",
|
||||
'dArr': "\u21D3",
|
||||
'hArr': "\u21D4",
|
||||
'forall': "\u2200",
|
||||
'part': "\u2202",
|
||||
'exist': "\u2203",
|
||||
'empty': "\u2205",
|
||||
'nabla': "\u2207",
|
||||
'isin': "\u2208",
|
||||
'notin': "\u2209",
|
||||
'ni': "\u220B",
|
||||
'prod': "\u220F",
|
||||
'sum': "\u2211",
|
||||
'minus': "\u2212",
|
||||
'lowast': "\u2217",
|
||||
'radic': "\u221A",
|
||||
'prop': "\u221D",
|
||||
'infin': "\u221E",
|
||||
'ang': "\u2220",
|
||||
'and': "\u2227",
|
||||
'or': "\u2228",
|
||||
'cap': "\u2229",
|
||||
'cup': "\u222A",
|
||||
'int': "\u222B",
|
||||
'there4': "\u2234",
|
||||
'sim': "\u223C",
|
||||
'cong': "\u2245",
|
||||
'asymp': "\u2248",
|
||||
'ne': "\u2260",
|
||||
'equiv': "\u2261",
|
||||
'le': "\u2264",
|
||||
'ge': "\u2265",
|
||||
'sub': "\u2282",
|
||||
'sup': "\u2283",
|
||||
'nsub': "\u2284",
|
||||
'sube': "\u2286",
|
||||
'supe': "\u2287",
|
||||
'oplus': "\u2295",
|
||||
'otimes': "\u2297",
|
||||
'perp': "\u22A5",
|
||||
'sdot': "\u22C5",
|
||||
'lceil': "\u2308",
|
||||
'rceil': "\u2309",
|
||||
'lfloor': "\u230A",
|
||||
'rfloor': "\u230B",
|
||||
'loz': "\u25CA",
|
||||
'spades': "\u2660",
|
||||
'clubs': "\u2663",
|
||||
'hearts': "\u2665",
|
||||
'diams': "\u2666",
|
||||
'lang': "\u27E8",
|
||||
'rang': "\u27E9",
|
||||
}
|
||||
Reference in New Issue
Block a user