[javascriptlint-commit] SF.net SVN: javascriptlint:[334] trunk
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2013-10-08 16:36:50
|
Revision: 334
http://sourceforge.net/p/javascriptlint/code/334
Author: matthiasmiller
Date: 2013-10-08 16:36:44 +0000 (Tue, 08 Oct 2013)
Log Message:
-----------
Change the parser to only use offsets internally and to convert offsets to line/col only when reporting errors.
Modified Paths:
--------------
trunk/javascriptlint/htmlparse.py
trunk/javascriptlint/jsparse.py
trunk/javascriptlint/lint.py
trunk/javascriptlint/warnings.py
trunk/jsengine/__init__.py
trunk/jsengine/parser/__init__.py
trunk/jsengine/structs.py
trunk/jsengine/tokenizer/__init__.py
trunk/test.py
Modified: trunk/javascriptlint/htmlparse.py
===================================================================
--- trunk/javascriptlint/htmlparse.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/htmlparse.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -2,18 +2,25 @@
import HTMLParser
import unittest
+from jsengine.structs import NodePos, NodePositions
+
class _Parser(HTMLParser.HTMLParser):
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self._tags = []
+ self._node_positions = None
+ def feed(self, data):
+ # Reset line numbers whenever we get data.
+ self._node_positions = None
+ HTMLParser.HTMLParser.feed(self, data)
+
def handle_starttag(self, tag, attributes):
if tag.lower() == 'script':
attr = dict(attributes)
self._tags.append({
'type': 'start',
- 'lineno': self.lineno,
- 'offset': self.offset,
+ 'offset': self._getoffset(),
'len': len(self.get_starttag_text()),
'attr': attr
})
@@ -22,8 +29,7 @@
if tag.lower() == 'script':
self._tags.append({
'type': 'end',
- 'lineno': self.lineno,
- 'offset': self.offset,
+ 'offset': self._getoffset(),
})
def unknown_decl(self, data):
@@ -33,9 +39,16 @@
def gettags(self):
return self._tags
+ def _getoffset(self):
+ # htmlparse returns 1-based line numbers. Calculate the offset of the
+ # script's contents.
+ if self._node_positions is None:
+ self._node_positions = NodePositions(self.rawdata)
+ pos = NodePos(self.lineno - 1, self.offset)
+ return self._node_positions.to_offset(pos)
+
+
def findscripttags(s):
- """ Note that the lineno is 1-based.
- """
parser = _Parser()
parser.feed(s)
parser.close()
Modified: trunk/javascriptlint/jsparse.py
===================================================================
--- trunk/javascriptlint/jsparse.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/jsparse.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -16,7 +16,8 @@
return True
return jsengine.parser.is_valid_version(jsversion.version)
-def findpossiblecomments(script, node_positions):
+def findpossiblecomments(script, script_offset):
+ assert not script_offset is None
pos = 0
single_line_re = r"//[^\r\n]*"
multi_line_re = r"/\*(.*?)\*/"
@@ -41,38 +42,34 @@
start_offset = match.start()
end_offset = match.end()-1
- start_pos = node_positions.from_offset(start_offset)
- end_pos = node_positions.from_offset(end_offset)
- comment_node = ParseNode(kind.COMMENT, opcode, start_pos, end_pos,
- comment_text, [])
+ comment_node = ParseNode(kind.COMMENT, opcode,
+ script_offset + start_offset,
+ script_offset + end_offset, comment_text, [])
comments.append(comment_node)
# Start searching immediately after the start of the comment in case
# this one was within a string or a regexp.
pos = match.start()+1
-def parse(script, jsversion, error_callback, startpos=None):
- """ All node positions will be relative to startpos. This allows scripts
- to be embedded in a file (for example, HTML).
+def parse(script, jsversion, error_callback, start_offset=0):
+ """ All node positions will be relative to start_offset. This allows
+ scripts to be embedded in a file (for example, HTML).
"""
- startpos = startpos or NodePos(0, 0)
+ assert not start_offset is None
jsversion = jsversion or JSVersion.default()
assert isvalidversion(jsversion), jsversion
if jsversion.e4x:
- error_callback(startpos.line, startpos.col, 'e4x_deprecated', {})
+ error_callback(start_offset, 'e4x_deprecated', {})
return jsengine.parser.parse(script, jsversion.version,
- error_callback,
- startpos)
+ error_callback, start_offset)
-def filtercomments(possible_comments, node_positions, root_node):
+def filtercomments(possible_comments, root_node):
comment_ignore_ranges = NodeRanges()
def process(node):
if node.kind == tok.STRING or \
(node.kind == tok.OBJECT and node.opcode == op.REGEXP):
- start_offset = node_positions.to_offset(node.start_pos())
- end_offset = node_positions.to_offset(node.end_pos())
- comment_ignore_ranges.add(start_offset, end_offset)
+ comment_ignore_ranges.add(node.start_offset, node.end_offset)
for kid in node.kids:
if kid:
process(kid)
@@ -80,25 +77,22 @@
comments = []
for comment in possible_comments:
- start_offset = node_positions.to_offset(comment.start_pos())
- end_offset = node_positions.to_offset(comment.end_pos())
- if comment_ignore_ranges.has(start_offset):
+ if comment_ignore_ranges.has(comment.start_offset):
continue
- comment_ignore_ranges.add(start_offset, end_offset)
+ comment_ignore_ranges.add(comment.start_offset, comment.end_offset)
comments.append(comment)
return comments
-def findcomments(script, root_node, start_pos=None):
- node_positions = NodePositions(script, start_pos)
- possible_comments = findpossiblecomments(script, node_positions)
- return filtercomments(possible_comments, node_positions, root_node)
+def findcomments(script, root_node, start_offset=0):
+ possible_comments = findpossiblecomments(script, start_offset)
+ return filtercomments(possible_comments, root_node)
def is_compilable_unit(script, jsversion):
jsversion = jsversion or JSVersion.default()
assert isvalidversion(jsversion)
return jsengine.parser.is_compilable_unit(script, jsversion.version)
-def _dump_node(node, depth=0):
+def _dump_node(node, node_positions, depth=0):
if node is None:
print ' '*depth,
print '(None)'
@@ -107,7 +101,8 @@
print ' '*depth,
print '%s, %s' % (repr(node.kind), repr(node.opcode))
print ' '*depth,
- print '%s - %s' % (node.start_pos(), node.end_pos())
+ print '%s - %s' % (node_positions.from_offset(node.start_offset),
+ node_positions.from_offset(node.end_offset))
if hasattr(node, 'atom'):
print ' '*depth,
print 'atom: %s' % node.atom
@@ -116,13 +111,14 @@
print '(no semicolon)'
print
for node in node.kids:
- _dump_node(node, depth+1)
+ _dump_node(node, node_positions, depth+1)
def dump_tree(script):
def error_callback(line, col, msg, msg_args):
print '(%i, %i): %s', (line, col, msg)
node = parse(script, None, error_callback)
- _dump_node(node)
+ node_positions = NodePositions(script)
+ _dump_node(node, node_positions)
class TestComments(unittest.TestCase):
def _test(self, script, expected_comments):
@@ -230,42 +226,42 @@
class TestLineOffset(unittest.TestCase):
def testErrorPos(self):
- def geterror(script, startpos):
+ def geterror(script, start_offset):
errors = []
- def onerror(line, col, msg, msg_args):
- errors.append((line, col, msg, msg_args))
- parse(script, None, onerror, startpos)
+ def onerror(offset, msg, msg_args):
+ errors.append((offset, msg, msg_args))
+ parse(script, None, onerror, start_offset)
self.assertEquals(len(errors), 1)
return errors[0]
- self.assertEquals(geterror(' ?', None), (0, 1, 'syntax_error', {}))
- self.assertEquals(geterror('\n ?', None), (1, 1, 'syntax_error', {}))
- self.assertEquals(geterror(' ?', NodePos(1, 1)), (1, 2, 'syntax_error', {}))
- self.assertEquals(geterror('\n ?', NodePos(1, 1)), (2, 1, 'syntax_error', {}))
+ self.assertEquals(geterror(' ?', 0), (1, 'syntax_error', {}))
+ self.assertEquals(geterror('\n ?', 0), (2, 'syntax_error', {}))
+ self.assertEquals(geterror(' ?', 2), (3, 'syntax_error', {}))
+ self.assertEquals(geterror('\n ?', 2), (4, 'syntax_error', {}))
def testNodePos(self):
- def getnodepos(script, startpos):
- root = parse(script, None, None, startpos)
+ def getnodepos(script, start_offset):
+ root = parse(script, None, None, start_offset)
self.assertEquals(root.kind, tok.LC)
var, = root.kids
self.assertEquals(var.kind, tok.VAR)
- return var.start_pos()
- self.assertEquals(getnodepos('var x;', None), NodePos(0, 0))
- self.assertEquals(getnodepos(' var x;', None), NodePos(0, 1))
- self.assertEquals(getnodepos('\n\n var x;', None), NodePos(2, 1))
- self.assertEquals(getnodepos('var x;', NodePos(3, 4)), NodePos(3, 4))
- self.assertEquals(getnodepos(' var x;', NodePos(3, 4)), NodePos(3, 5))
- self.assertEquals(getnodepos('\n\n var x;', NodePos(3, 4)), NodePos(5, 1))
+ return var.start_offset
+ self.assertEquals(getnodepos('var x;', 0), 0)
+ self.assertEquals(getnodepos(' var x;', 0), 1)
+ self.assertEquals(getnodepos('\n\n var x;', 0), 3)
+ self.assertEquals(getnodepos('var x;', 7), 7)
+ self.assertEquals(getnodepos(' var x;', 7), 8)
+ self.assertEquals(getnodepos('\n\n var x;', 7), 10)
def testComments(self):
- def testcomment(comment, startpos, expectedpos):
+ def testcomment(comment, startpos, expected_offset):
root = parse(comment, None, None, startpos)
comment, = findcomments(comment, root, startpos)
- self.assertEquals(comment.start_pos(), expectedpos)
+ self.assertEquals(comment.start_offset, expected_offset)
for comment in ('/*comment*/', '//comment'):
- testcomment(comment, None, NodePos(0, 0))
- testcomment(' %s' % comment, None, NodePos(0, 1))
- testcomment('\n\n %s' % comment, None, NodePos(2, 1))
- testcomment('%s' % comment, NodePos(3, 4), NodePos(3, 4))
- testcomment(' %s' % comment, NodePos(3, 4), NodePos(3, 5))
- testcomment('\n\n %s' % comment, NodePos(3, 4), NodePos(5, 1))
+ testcomment(comment, 0, 0)
+ testcomment(' %s' % comment, 0, 1)
+ testcomment('\n\n %s' % comment, 0, 3)
+ testcomment('%s' % comment, 7, 7)
+ testcomment(' %s' % comment, 7, 8)
+ testcomment('\n\n %s' % comment, 7, 10)
if __name__ == '__main__':
unittest.main()
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/lint.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -140,7 +140,7 @@
# sorted by node position.
unreferenced = [(key[0], key[1], node) for key, node
in unreferenced.items()]
- unreferenced.sort(key=lambda x: x[2].start_pos())
+ unreferenced.sort(key=lambda x: x[2].start_offset)
return {
'unreferenced': unreferenced,
@@ -214,8 +214,8 @@
# Conditionally add it to an inner scope.
assert self._node
- if (node.start_pos() >= self._node.start_pos() and \
- node.end_pos() <= self._node.end_pos()):
+ if (node.start_offset >= self._node.start_offset and \
+ node.end_offset <= self._node.end_offset):
return self
class _Script:
@@ -245,7 +245,6 @@
def _findhtmlscripts(contents, default_version):
starttag = None
- nodepos = jsparse.NodePositions(contents)
for tag in htmlparse.findscripttags(contents):
if tag['type'] == 'start':
# Ignore nested start tags.
@@ -265,13 +264,9 @@
# htmlparse returns 1-based line numbers. Calculate the
# position of the script's contents.
- tagpos = jsparse.NodePos(starttag['lineno']-1, starttag['offset'])
- tagoffset = nodepos.to_offset(tagpos)
- startoffset = tagoffset + starttag['len']
- startpos = nodepos.from_offset(startoffset)
- endpos = jsparse.NodePos(tag['lineno']-1, tag['offset'])
- endoffset = nodepos.to_offset(endpos)
- script = contents[startoffset:endoffset]
+ start_offset = starttag['offset'] + starttag['len']
+ end_offset = tag['offset']
+ script = contents[start_offset:end_offset]
if not jsparse.isvalidversion(starttag['jsversion']) or \
jsparse.is_compilable_unit(script, starttag['jsversion']):
@@ -279,7 +274,7 @@
yield {
'type': 'inline',
'jsversion': starttag['jsversion'],
- 'pos': startpos,
+ 'offset': start_offset,
'contents': script,
}
starttag = None
@@ -294,8 +289,9 @@
import_path = import_path.replace('\\', os.sep)
import_path = os.path.join(os.path.dirname(path), import_path)
return lint_file(import_path, 'js', jsversion, encoding)
- def _lint_error(*args):
- return lint_error(normpath, *args)
+ def _lint_error(offset, errname, errdesc):
+ pos = node_positions.from_offset(offset)
+ return lint_error(normpath, pos.line, pos.col, errname, errdesc)
normpath = fs.normpath(path)
if normpath in lint_cache:
@@ -307,12 +303,13 @@
try:
contents = fs.readfile(path, encoding)
except IOError, error:
- _lint_error(0, 0, 'io_error', unicode(error))
+ lint_error(normpath, 0, 0, 'io_error', unicode(error))
return lint_cache[normpath]
+ node_positions = jsparse.NodePositions(contents)
script_parts = []
if kind == 'js':
- script_parts.append((None, jsversion or conf['default-version'], contents))
+ script_parts.append((0, jsversion or conf['default-version'], contents))
elif kind == 'html':
assert jsversion is None
for script in _findhtmlscripts(contents, conf['default-version']):
@@ -324,7 +321,7 @@
other = import_script(script['src'], script['jsversion'])
lint_cache[normpath].importscript(other)
elif script['type'] == 'inline':
- script_parts.append((script['pos'], script['jsversion'],
+ script_parts.append((script['offset'], script['jsversion'],
script['contents']))
else:
assert False, 'Invalid internal script type %s' % \
@@ -343,18 +340,18 @@
else:
lint_file(path, 'js', None, encoding)
-def _lint_script_part(scriptpos, jsversion, script, script_cache, conf,
+def _lint_script_part(script_offset, jsversion, script, script_cache, conf,
ignores, report_native, report_lint, import_callback):
- def parse_error(row, col, msg, msg_args):
+ def parse_error(offset, msg, msg_args):
if not msg in ('anon_no_return_value', 'no_return_value',
'redeclared_var', 'var_hides_arg'):
- parse_errors.append((jsparse.NodePos(row, col), msg, msg_args))
+ parse_errors.append((offset, msg, msg_args))
- def report(node, errname, pos=None, **errargs):
+ def report(node, errname, offset=0, **errargs):
if errname == 'empty_statement' and node.kind == tok.LC:
for pass_ in passes:
- if pass_.start_pos() > node.start_pos() and \
- pass_.end_pos() < node.end_pos():
+ if pass_.start_offset > node.start_offset and \
+ pass_.end_offset < node.end_offset:
passes.remove(pass_)
return
@@ -363,12 +360,12 @@
# the next case/default.
assert node.kind in (tok.CASE, tok.DEFAULT)
prevnode = node.parent.kids[node.node_index-1]
- expectedfallthru = prevnode.end_pos(), node.start_pos()
+ expectedfallthru = prevnode.end_offset, node.start_offset
elif errname == 'missing_break_for_last_case':
# Find the end of the current case/default and the end of the
# switch.
assert node.parent.kind == tok.LC
- expectedfallthru = node.end_pos(), node.parent.end_pos()
+ expectedfallthru = node.end_offset, node.parent.end_offset
else:
expectedfallthru = None
@@ -377,11 +374,11 @@
for fallthru in fallthrus:
# Look for a fallthru between the end of the current case or
# default statement and the beginning of the next token.
- if fallthru.start_pos() > start and fallthru.end_pos() < end:
+ if fallthru.start_offset > start and fallthru.end_offset < end:
fallthrus.remove(fallthru)
return
- report_lint(node, errname, pos, **errargs)
+ report_lint(node, errname, offset, **errargs)
parse_errors = []
declares = []
@@ -390,8 +387,7 @@
fallthrus = []
passes = []
- node_positions = jsparse.NodePositions(script, scriptpos)
- possible_comments = jsparse.findpossiblecomments(script, node_positions)
+ possible_comments = jsparse.findpossiblecomments(script, script_offset)
# Check control comments for the correct version. It may be this comment
# isn't a valid comment (for example, it might be inside a string literal)
@@ -410,18 +406,18 @@
report(node, 'unsupported_version', version=parms)
if not jsparse.isvalidversion(jsversion):
- report_lint(jsversionnode, 'unsupported_version', scriptpos,
+ report_lint(jsversionnode, 'unsupported_version', script_offset,
version=jsversion.version)
return
- root = jsparse.parse(script, jsversion, parse_error, scriptpos)
+ root = jsparse.parse(script, jsversion, parse_error, script_offset)
if not root:
# Report errors and quit.
- for pos, msg, msg_args in parse_errors:
- report_native(pos, msg, msg_args)
+ for offset, msg, msg_args in parse_errors:
+ report_native(offset, msg, msg_args)
return
- comments = jsparse.filtercomments(possible_comments, node_positions, root)
+ comments = jsparse.filtercomments(possible_comments, root)
if jsversionnode is not None and jsversionnode not in comments:
# TODO
@@ -449,7 +445,7 @@
start_ignore = node
elif keyword == 'end':
if start_ignore:
- ignores.append((start_ignore.start_pos(), node.end_pos()))
+ ignores.append((start_ignore.start_offset, node.end_offset))
start_ignore = None
else:
report(node, 'mismatch_ctrl_comments')
@@ -471,8 +467,8 @@
# Report at the actual error of the location. Add two
# characters for the opening two characters.
if nested_comment >= 0:
- pos = node_positions.from_offset(node_positions.to_offset(comment.start_pos()) + 2 + nested_comment)
- report(comment, 'nested_comment', pos=pos)
+ offset = comment.start_offset + 2 + nested_comment
+ report(comment, 'nested_comment', offset=offset)
if comment.atom.lower().startswith('jsl:'):
report(comment, 'jsl_cc_not_understood')
elif comment.atom.startswith('@'):
@@ -481,8 +477,8 @@
report(start_ignore, 'mismatch_ctrl_comments')
# Wait to report parse errors until loading jsl:ignore directives.
- for pos, msg in parse_errors:
- report_native(pos, msg)
+ for offset, msg in parse_errors:
+ report_native(offset, msg)
# Find all visitors and convert them into "onpush" callbacks that call "report"
visitors = {
@@ -516,15 +512,15 @@
unused_scope.set_unused(name, node)
def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback):
- def report_lint(node, errname, pos=None, **errargs):
+ def report_lint(node, errname, offset=0, **errargs):
errdesc = warnings.format_error(errname, **errargs)
- _report(pos or node.start_pos(), errname, errdesc, True)
+ _report(offset or node.start_offset, errname, errdesc, True)
- def report_native(pos, errname, errargs):
+ def report_native(offset, errname, errargs):
errdesc = warnings.format_error(errname, **errargs)
- _report(pos, errname, errdesc, False)
+ _report(offset, errname, errdesc, False)
- def _report(pos, errname, errdesc, require_key):
+ def _report(offset, errname, errdesc, require_key):
try:
if not conf[errname]:
return
@@ -533,14 +529,14 @@
raise
for start, end in ignores:
- if pos >= start and pos <= end:
+ if offset >= start and offset <= end:
return
- return lint_error(pos.line, pos.col, errname, errdesc)
+ return lint_error(offset, errname, errdesc)
- for scriptpos, jsversion, script in script_parts:
+ for script_offset, jsversion, script in script_parts:
ignores = []
- _lint_script_part(scriptpos, jsversion, script, script_cache, conf, ignores,
+ _lint_script_part(script_offset, jsversion, script, script_cache, conf, ignores,
report_native, report_lint, import_callback)
scope = script_cache.scope
@@ -576,10 +572,10 @@
# TODO: This is ugly hardcoding to improve the error positioning of
# "missing_semicolon" errors.
if visitor.warning in ('missing_semicolon', 'missing_semicolon_for_lambda'):
- pos = warning.node.end_pos()
+ offset = warning.node.end_offset
else:
- pos = None
- report(warning.node, visitor.warning, pos=pos, **warning.errargs)
+ offset = None
+ report(warning.node, visitor.warning, offset=offset, **warning.errargs)
return onpush
def _warn_or_declare(scope, name, type_, node, report):
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/warnings.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -584,7 +584,7 @@
if filter(is_return_with_val, exit_points):
# If the function returns a value, find all returns without a value.
returns = filter(is_return_without_val, exit_points)
- returns.sort(key=lambda node: node.start_pos())
+ returns.sort(key=lambda node: node.start_offset)
if returns:
raise LintWarning(returns[0], name=name)
# Warn if the function sometimes exits naturally.
Modified: trunk/jsengine/__init__.py
===================================================================
--- trunk/jsengine/__init__.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/jsengine/__init__.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -10,12 +10,12 @@
)
class JSSyntaxError(BaseException):
- def __init__(self, pos, msg, msg_args=None):
+ def __init__(self, offset, msg, msg_args=None):
assert msg in _MESSAGES, msg
- self.pos = pos
+ self.offset = offset
self.msg = msg
self.msg_args = msg_args or {}
def __unicode__(self):
- return '%s: %s' % (self.pos, self.msg)
+ return '%s: %s' % (self.offset, self.msg)
def __repr__(self):
- return 'JSSyntaxError(%r, %r, %r)' % (self.pos, self.msg. self.msg_args)
+ return 'JSSyntaxError(%r, %r, %r)' % (self.offset, self.msg. self.msg_args)
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/jsengine/parser/__init__.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -22,16 +22,16 @@
"1.7",
]
-def _auto_semicolon(t, kind_, op_, startpos, endpos, atom, kids):
+def _auto_semicolon(t, kind_, op_, start_offset, end_offset, atom, kids):
nosemi = False
if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.RBRACE):
x = t.advance()
if x.tok != tok.SEMI:
- raise JSSyntaxError(x.startpos, 'semi_before_stmnt')
- endpos = x.endpos
+ raise JSSyntaxError(x.start_offset, 'semi_before_stmnt')
+ end_offset = x.end_offset
else:
nosemi = True
- return ParseNode(kind_, op_, startpos, endpos, atom, kids, nosemi)
+ return ParseNode(kind_, op_, start_offset, end_offset, atom, kids, nosemi)
def _function_arglist(t):
fn_args = []
@@ -39,8 +39,8 @@
while True:
x = t.expect(tok.NAME)
fn_args.append(ParseNode(kind.NAME, op.ARGNAME,
- x.startpos,
- x.endpos, x.atom, []))
+ x.start_offset,
+ x.end_offset, x.atom, []))
if t.peek().tok == tok.COMMA:
t.advance()
else:
@@ -50,23 +50,23 @@
def _primary_expression(t):
x = t.next_withregexp()
if x.tok == tok.THIS:
- return ParseNode(kind.PRIMARY, op.THIS, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.THIS, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.NAME:
- return ParseNode(kind.NAME, op.NAME, x.startpos, x.endpos, x.atom, [None])
+ return ParseNode(kind.NAME, op.NAME, x.start_offset, x.end_offset, x.atom, [None])
elif x.tok == tok.NULL:
- return ParseNode(kind.PRIMARY, op.NULL, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.NULL, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.TRUE:
- return ParseNode(kind.PRIMARY, op.TRUE, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.TRUE, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.FALSE:
- return ParseNode(kind.PRIMARY, op.FALSE, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.FALSE, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.STRING:
- return ParseNode(kind.STRING, op.STRING, x.startpos, x.endpos, x.atom, [])
+ return ParseNode(kind.STRING, op.STRING, x.start_offset, x.end_offset, x.atom, [])
elif x.tok == tok.REGEXP:
- return ParseNode(kind.OBJECT, op.REGEXP, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.OBJECT, op.REGEXP, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.NUMBER:
- return ParseNode(kind.NUMBER, None, x.startpos, x.endpos, x.atom, [])
+ return ParseNode(kind.NUMBER, None, x.start_offset, x.end_offset, x.atom, [])
elif x.tok == tok.LBRACKET:
- startpos = x.startpos
+ start_offset = x.start_offset
items = []
end_comma = None
if t.peek().tok != tok.RBRACKET:
@@ -83,18 +83,18 @@
# Expect a comma and use it if the value was missing.
x = t.expect(tok.COMMA)
comma = ParseNode(kind.COMMA, None,
- x.startpos, x.endpos, None, [])
+ x.start_offset, x.end_offset, None, [])
items[-1] = items[-1] or comma
# Check for the end.
if t.peek().tok == tok.RBRACKET:
end_comma = comma
break
- endpos = t.expect(tok.RBRACKET).endpos
- return ParseNode(kind.RB, None, startpos, endpos, None, items,
+ end_offset = t.expect(tok.RBRACKET).end_offset
+ return ParseNode(kind.RB, None, start_offset, end_offset, None, items,
end_comma=end_comma)
elif x.tok == tok.LBRACE:
- startpos = x.startpos
+ start_offset = x.start_offset
kids = []
# TODO: get/set
end_comma = None
@@ -104,50 +104,50 @@
break
elif x.tok == tok.STRING:
t.expect(tok.STRING)
- key = ParseNode(kind.STRING, None, x.startpos,
- x.endpos, x.atom, [])
+ key = ParseNode(kind.STRING, None, x.start_offset,
+ x.end_offset, x.atom, [])
elif x.tok == tok.NUMBER:
t.expect(tok.NUMBER)
- key = ParseNode(kind.NUMBER, None, x.startpos,
- x.endpos, x.atom, [])
+ key = ParseNode(kind.NUMBER, None, x.start_offset,
+ x.end_offset, x.atom, [])
else:
x = t.expect_identifiername()
- key = ParseNode(kind.NAME, None, x.startpos, x.endpos,
+ key = ParseNode(kind.NAME, None, x.start_offset, x.end_offset,
x.atom, [])
t.expect(tok.COLON)
value = _assignment_expression(t, True)
- kids.append(ParseNode(kind.COLON, None, key.startpos,
- value.endpos, None, [key, value]))
+ kids.append(ParseNode(kind.COLON, None, key.start_offset,
+ value.end_offset, None, [key, value]))
if t.peek().tok == tok.COMMA:
x = t.advance()
end_comma = ParseNode(kind.COMMA, None,
- x.startpos, x.endpos, None, [])
+ x.start_offset, x.end_offset, None, [])
else:
end_comma = None
break
- endpos = t.expect(tok.RBRACE).endpos
- return ParseNode(kind.RC, None, startpos, endpos, None, kids,
+ end_offset = t.expect(tok.RBRACE).end_offset
+ return ParseNode(kind.RC, None, start_offset, end_offset, None, kids,
end_comma=end_comma)
elif x.tok == tok.LPAREN:
- startpos = x.startpos
+ start_offset = x.start_offset
kid = _expression(t, True)
- endpos = t.expect(tok.RPAREN).endpos
- return ParseNode(kind.RP, None, startpos, endpos, None, [kid])
+ end_offset = t.expect(tok.RPAREN).end_offset
+ return ParseNode(kind.RP, None, start_offset, end_offset, None, [kid])
else:
- raise JSSyntaxError(x.startpos, 'syntax_error')
+ raise JSSyntaxError(x.start_offset, 'syntax_error')
def _function_declaration(t, named_opcode):
node = _function_expression(t, named_opcode)
# Convert anonymous functions in expressions.
if node.opcode == op.ANONFUNOBJ:
- node = _auto_semicolon(t, kind.SEMI, None, node.startpos, node.endpos,
+ node = _auto_semicolon(t, kind.SEMI, None, node.start_offset, node.end_offset,
None, [node])
return node
def _function_expression(t, named_opcode):
- startpos = t.expect(tok.FUNCTION).startpos
+ start_offset = t.expect(tok.FUNCTION).start_offset
if t.peek().tok == tok.NAME:
fn_name = t.expect(tok.NAME).atom
opcode = named_opcode
@@ -157,12 +157,12 @@
t.expect(tok.LPAREN)
fn_args = _function_arglist(t)
t.expect(tok.RPAREN)
- fn_body_startpos = t.expect(tok.LBRACE).startpos
+ fn_body_start_offset = t.expect(tok.LBRACE).start_offset
kids = _sourceelements(t, tok.RBRACE)
- fn_body_endpos = t.expect(tok.RBRACE).endpos
- fn_body = ParseNode(kind.LC, None, fn_body_startpos,
- fn_body_endpos, None, kids)
- return ParseNode(kind.FUNCTION, opcode, startpos, fn_body.endpos,
+ fn_body_end_offset = t.expect(tok.RBRACE).end_offset
+ fn_body = ParseNode(kind.LC, None, fn_body_start_offset,
+ fn_body_end_offset, None, kids)
+ return ParseNode(kind.FUNCTION, opcode, start_offset, fn_body.end_offset,
fn_name, [fn_body], fn_args=fn_args)
def _argument_list(t):
@@ -177,17 +177,17 @@
return args
def _new_expression(t):
- startpos = t.expect(tok.NEW).startpos
+ start_offset = t.expect(tok.NEW).start_offset
expr = _member_expression(t)
# If no (), this is a variant of the NewExpression
if t.peek().tok == tok.LPAREN:
t.expect(tok.LPAREN)
args = _argument_list(t)
- endpos = t.expect(tok.RPAREN).endpos
+ end_offset = t.expect(tok.RPAREN).end_offset
else:
args = []
- endpos = expr.endpos
- return ParseNode(kind.NEW, op.NEW, startpos, endpos,
+ end_offset = expr.end_offset
+ return ParseNode(kind.NEW, op.NEW, start_offset, end_offset,
None, [expr] + args)
def _member_expression(t, _recurse=True):
@@ -203,13 +203,13 @@
if t.peek().tok == tok.LBRACKET:
t.advance()
expr = _expression(t, True)
- endpos = t.expect(tok.RBRACKET).endpos
- kid = ParseNode(kind.LB, op.GETELEM, kid.startpos, endpos,
+ end_offset = t.expect(tok.RBRACKET).end_offset
+ kid = ParseNode(kind.LB, op.GETELEM, kid.start_offset, end_offset,
None, [kid, expr])
elif t.peek().tok == tok.DOT:
t.advance()
expr = t.expect_identifiername()
- kid = ParseNode(kind.DOT, op.GETPROP, kid.startpos, expr.endpos,
+ kid = ParseNode(kind.DOT, op.GETPROP, kid.start_offset, expr.end_offset,
expr.atom, [kid])
else:
return kid
@@ -224,21 +224,21 @@
if x.tok == tok.LPAREN:
t.expect(tok.LPAREN)
args = _argument_list(t)
- endpos = t.expect(tok.RPAREN).endpos
- expr = ParseNode(kind.LP, op.CALL, expr.startpos,
- endpos, None, [expr] + args)
+ end_offset = t.expect(tok.RPAREN).end_offset
+ expr = ParseNode(kind.LP, op.CALL, expr.start_offset,
+ end_offset, None, [expr] + args)
elif x.tok == tok.LBRACKET:
t.expect(tok.LBRACKET)
lookup = _expression(t, True)
- endpos = t.expect(tok.RBRACKET).endpos
+ end_offset = t.expect(tok.RBRACKET).end_offset
expr = ParseNode(kind.LB, op.GETELEM,
- expr.startpos, endpos,
+ expr.start_offset, end_offset,
None, [expr, lookup])
elif x.tok == tok.DOT:
t.expect(tok.DOT)
lookup = t.expect_identifiername()
expr = ParseNode(kind.DOT, op.GETPROP,
- expr.startpos, lookup.endpos,
+ expr.start_offset, lookup.end_offset,
lookup.atom, [expr])
else:
return expr
@@ -251,17 +251,17 @@
def _postfix_expression(t):
kid = _lefthandside_expression(t)
if t.peek_sameline().tok == tok.INC:
- endpos = t.expect(tok.INC).endpos
+ end_offset = t.expect(tok.INC).end_offset
if kid.kind == kind.DOT and kid.opcode == op.GETPROP:
opcode = op.PROPINC
else:
opcode = op.NAMEINC
return ParseNode(kind.INC, opcode,
- kid.startpos, endpos, None, [kid])
+ kid.start_offset, end_offset, None, [kid])
elif t.peek_sameline().tok == tok.DEC:
- endpos = t.expect(tok.DEC).endpos
+ end_offset = t.expect(tok.DEC).end_offset
return ParseNode(kind.DEC, op.NAMEDEC,
- kid.startpos, endpos, None, [kid])
+ kid.start_offset, end_offset, None, [kid])
else:
return kid
@@ -280,9 +280,9 @@
x = t.peek()
if x.tok in _UNARY:
kind_, op_ = _UNARY[x.tok]
- startpos = t.advance().startpos
+ start_offset = t.advance().start_offset
kid = _unary_expression(t)
- return ParseNode(kind_, op_, startpos, kid.endpos, None, [kid])
+ return ParseNode(kind_, op_, start_offset, kid.end_offset, None, [kid])
else:
return _postfix_expression(t)
@@ -300,7 +300,7 @@
t.advance()
kids.append(child_expr_callback(t))
expr = ParseNode(kind_, op_,
- kids[0].startpos, kids[1].endpos,
+ kids[0].start_offset, kids[1].end_offset,
None, kids)
_MULTIPLICATIVE = {
@@ -359,7 +359,7 @@
t.advance()
right = _equality_expression(t, allowin)
left = ParseNode(kind.BITAND, op.BITAND,
- left.startpos, right.endpos,
+ left.start_offset, right.end_offset,
None, [left, right])
return left
@@ -369,7 +369,7 @@
t.advance()
right = _bitwise_and_expression(t, allowin)
left = ParseNode(kind.BITXOR, op.BITXOR,
- left.startpos, right.endpos,
+ left.start_offset, right.end_offset,
None, [left, right])
return left
@@ -379,7 +379,7 @@
t.advance()
right = _bitwise_xor_expression(t, allowin)
left = ParseNode(kind.BITOR, op.BITOR,
- left.startpos, right.endpos,
+ left.start_offset, right.end_offset,
None, [left, right])
return left
@@ -396,7 +396,7 @@
right = exprs.pop()
left = exprs[-1]
exprs[-1] = ParseNode(kind.AND, op.AND,
- left.startpos, right.endpos,
+ left.start_offset, right.end_offset,
None, [left, right])
return exprs[0]
@@ -413,7 +413,7 @@
right = exprs.pop()
left = exprs[-1]
exprs[-1] = ParseNode(kind.OR, op.OR,
- left.startpos, right.endpos,
+ left.start_offset, right.end_offset,
None, [left, right])
return exprs[0]
@@ -425,7 +425,7 @@
t.expect(tok.COLON)
else_ = _assignment_expression(t, allowin)
return ParseNode(kind.HOOK, None,
- kid.startpos, else_.endpos,
+ kid.start_offset, else_.end_offset,
None, [kid, if_, else_])
else:
return kid
@@ -463,12 +463,12 @@
assert kid.opcode == op.CALL
kid.opcode = op.SETCALL
else:
- raise JSSyntaxError(left.startpos, 'invalid_assign')
+ raise JSSyntaxError(left.start_offset, 'invalid_assign')
kind_, op_ = _ASSIGNS[t.peek().tok]
t.advance()
right = _assignment_expression(t, allowin)
return ParseNode(kind_, op_,
- left.startpos, right.endpos, None, [left, right])
+ left.start_offset, right.end_offset, None, [left, right])
else:
return left
@@ -479,8 +479,8 @@
t.advance()
items.append(_assignment_expression(t, allowin))
if len(items) > 1:
- return ParseNode(kind.COMMA, None, items[0].startpos,
- items[-1].endpos, None, items)
+ return ParseNode(kind.COMMA, None, items[0].start_offset,
+ items[-1].end_offset, None, items)
else:
return items[0]
@@ -493,8 +493,8 @@
t.advance()
value = _assignment_expression(t, allowin)
nodes.append(ParseNode(kind.NAME, op.SETNAME if value else op.NAME,
- x.startpos,
- value.endpos if value else x.endpos,
+ x.start_offset,
+ value.end_offset if value else x.end_offset,
x.atom, [value]))
if t.peek().tok == tok.COMMA:
@@ -504,27 +504,27 @@
def _block_statement(t):
kids = []
- startpos = t.expect(tok.LBRACE).startpos
+ start_offset = t.expect(tok.LBRACE).start_offset
while t.peek().tok != tok.RBRACE:
kids.append(_statement(t))
- endpos = t.expect(tok.RBRACE).endpos
- return ParseNode(kind.LC, None, startpos, endpos, None, kids)
+ end_offset = t.expect(tok.RBRACE).end_offset
+ return ParseNode(kind.LC, None, start_offset, end_offset, None, kids)
def _empty_statement(t):
# EMPTY STATEMENT
x = t.expect(tok.SEMI)
- return ParseNode(kind.SEMI, None, x.startpos, x.endpos, None, [None])
+ return ParseNode(kind.SEMI, None, x.start_offset, x.end_offset, None, [None])
def _var_statement(t):
# VARIABLE STATEMENT
- startpos = t.expect(tok.VAR).startpos
+ start_offset = t.expect(tok.VAR).start_offset
nodes = _variable_declaration(t, True)
return _auto_semicolon(t, kind.VAR, op.DEFVAR,
- startpos, nodes[-1].endpos, None, nodes)
+ start_offset, nodes[-1].end_offset, None, nodes)
def _if_statement(t):
# IF STATEMENT
- startpos = t.expect(tok.IF).startpos
+ start_offset = t.expect(tok.IF).start_offset
t.expect(tok.LPAREN)
condition = _expression(t, True)
t.expect(tok.RPAREN)
@@ -534,38 +534,38 @@
else_body = _statement(t)
else:
else_body = None
- endpos = else_body.endpos if else_body else if_body.endpos
- return ParseNode(kind.IF, None, startpos,
- endpos, None, [condition, if_body, else_body])
+ end_offset = else_body.end_offset if else_body else if_body.end_offset
+ return ParseNode(kind.IF, None, start_offset,
+ end_offset, None, [condition, if_body, else_body])
def _do_statement(t):
- startpos = t.expect(tok.DO).startpos
+ start_offset = t.expect(tok.DO).start_offset
code = _statement(t)
t.expect(tok.WHILE)
t.expect(tok.LPAREN)
expr = _expression(t, True)
endtoken = t.expect(tok.RPAREN)
return _auto_semicolon(t, kind.DO, None,
- startpos, endtoken.endpos, None, [code, expr])
+ start_offset, endtoken.end_offset, None, [code, expr])
def _while_statement(t):
- startpos = t.expect(tok.WHILE).startpos
+ start_offset = t.expect(tok.WHILE).start_offset
t.expect(tok.LPAREN)
expr = _expression(t, True)
t.expect(tok.RPAREN)
code = _statement(t)
return ParseNode(kind.WHILE, None,
- startpos, code.endpos, None, [expr, code])
+ start_offset, code.end_offset, None, [expr, code])
def _for_statement(t):
- for_startpos = t.expect(tok.FOR).startpos
+ for_start_offset = t.expect(tok.FOR).start_offset
t.expect(tok.LPAREN)
for_exprs = []
if t.peek().tok == tok.VAR:
- var_startpos = t.advance().startpos
+ var_start_offset = t.advance().start_offset
kids = _variable_declaration(t, False)
- vars = ParseNode(kind.VAR, op.DEFVAR, var_startpos, kids[-1].endpos,
+ vars = ParseNode(kind.VAR, op.DEFVAR, var_start_offset, kids[-1].end_offset,
None, kids)
if t.peek().tok == tok.IN:
@@ -589,8 +589,8 @@
for_exprs = [expr, None, None]
if len(for_exprs) == 2:
- condition = ParseNode(kind.IN, None, for_exprs[0].startpos,
- for_exprs[-1].endpos, None, for_exprs)
+ condition = ParseNode(kind.IN, None, for_exprs[0].start_offset,
+ for_exprs[-1].end_offset, None, for_exprs)
else:
x = t.expect(tok.SEMI)
if t.peek().tok != tok.SEMI:
@@ -605,12 +605,12 @@
body = _statement(t)
return ParseNode(kind.FOR,
op.FORIN if condition.kind == kind.IN else None,
- for_startpos, body.endpos,
+ for_start_offset, body.end_offset,
None, [condition, body])
def _continue_statement(t):
endtoken = t.expect(tok.CONTINUE)
- startpos = endtoken.startpos
+ start_offset = endtoken.start_offset
if t.peek_sameline().tok == tok.NAME:
endtoken = t.expect(tok.NAME)
@@ -618,11 +618,11 @@
else:
name = None
# TODO: Validate Scope Labels
- return _auto_semicolon(t, kind.CONTINUE, None, startpos, endtoken.endpos, name, [])
+ return _auto_semicolon(t, kind.CONTINUE, None, start_offset, endtoken.end_offset, name, [])
def _break_statement(t):
endtoken = t.expect(tok.BREAK)
- startpos = endtoken.startpos
+ start_offset = endtoken.start_offset
if t.peek_sameline().tok == tok.NAME:
endtoken = t.expect(tok.NAME)
@@ -630,11 +630,11 @@
else:
name = None
# TODO: Validate Scope Labels
- return _auto_semicolon(t, kind.BREAK, None, startpos, endtoken.endpos, name, [])
+ return _auto_semicolon(t, kind.BREAK, None, start_offset, endtoken.end_offset, name, [])
def _return_statement(t):
endtoken = t.expect(tok.RETURN)
- startpos = endtoken.startpos
+ start_offset = endtoken.start_offset
if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.SEMI, tok.RBRACE):
expr = _expression(t, True)
@@ -642,108 +642,108 @@
else:
expr = None
# TODO: Validate Scope Labels
- return _auto_semicolon(t, kind.RETURN, None, startpos, endtoken.endpos,
+ return _auto_semicolon(t, kind.RETURN, None, start_offset, endtoken.end_offset,
None, [expr])
def _with_statement(t):
- startpos = t.expect(tok.WITH).startpos
+ start_offset = t.expect(tok.WITH).start_offset
t.expect(tok.LPAREN)
expr = _expression(t, True)
t.expect(tok.RPAREN)
body = _statement(t)
- return ParseNode(kind.WITH, None, startpos, body.endpos, None, [expr, body])
+ return ParseNode(kind.WITH, None, start_offset, body.end_offset, None, [expr, body])
def _switch_statement(t):
- switch_startpos = t.expect(tok.SWITCH).startpos
+ switch_start_offset = t.expect(tok.SWITCH).start_offset
t.expect(tok.LPAREN)
expr = _expression(t, True)
t.expect(tok.RPAREN)
- lc_startpos = t.expect(tok.LBRACE).startpos
+ lc_start_offset = t.expect(tok.LBRACE).start_offset
cases = []
while t.peek().tok != tok.RBRACE:
case_kind = None
case_expr = None
if t.peek().tok == tok.CASE:
- case_startpos = t.advance().startpos
+ case_start_offset = t.advance().start_offset
case_kind = kind.CASE
case_expr = _expression(t, True)
elif t.peek().tok == tok.DEFAULT:
- case_startpos = t.advance().startpos
+ case_start_offset = t.advance().start_offset
case_kind = kind.DEFAULT
else:
- raise JSSyntaxError(t.peek().startpos, 'invalid_case')
+ raise JSSyntaxError(t.peek().start_offset, 'invalid_case')
- case_endpos = t.expect(tok.COLON).endpos
+ case_end_offset = t.expect(tok.COLON).end_offset
statements = []
while t.peek().tok not in (tok.DEFAULT, tok.CASE, tok.RBRACE):
statements.append(_statement(t))
if statements:
- statements_startpos = statements[0].startpos
- statements_endpos = statements[-1].endpos
- case_endpos = statements[-1].endpos
+ statements_start_offset = statements[0].start_offset
+ statements_end_offset = statements[-1].end_offset
+ case_end_offset = statements[-1].end_offset
else:
- statements_startpos = case_endpos
- statements_endpos = case_endpos
+ statements_start_offset = case_end_offset
+ statements_end_offset = case_end_offset
- cases.append(ParseNode(case_kind, None, case_startpos, case_endpos,
+ cases.append(ParseNode(case_kind, None, case_start_offset, case_end_offset,
None, [
case_expr,
- ParseNode(kind.LC, None, statements_startpos,
- statements_endpos, None, statements)
+ ParseNode(kind.LC, None, statements_start_offset,
+ statements_end_offset, None, statements)
]))
- rc_endpos = t.expect(tok.RBRACE).endpos
- return ParseNode(kind.SWITCH, None, switch_startpos, rc_endpos,
+ rc_end_offset = t.expect(tok.RBRACE).end_offset
+ return ParseNode(kind.SWITCH, None, switch_start_offset, rc_end_offset,
None, [expr,
- ParseNode(kind.LC, None, lc_startpos, rc_endpos, None, cases)])
+ ParseNode(kind.LC, None, lc_start_offset, rc_end_offset, None, cases)])
def _throw_statement(t):
# TODO: Validate Scope
- startpos = t.expect(tok.THROW).startpos
+ start_offset = t.expect(tok.THROW).start_offset
if t.peek_sameline().tok == tok.EOL:
- raise JSSyntaxError(t.peek_sameline().startpos, 'expected_statement')
+ raise JSSyntaxError(t.peek_sameline().start_offset, 'expected_statement')
expr = _expression(t, True)
- return _auto_semicolon(t, kind.THROW, op.THROW, startpos, expr.endpos,
+ return _auto_semicolon(t, kind.THROW, op.THROW, start_offset, expr.end_offset,
None, [expr])
def _try_statement(t):
- try_startpos = t.expect(tok.TRY).startpos
+ try_start_offset = t.expect(tok.TRY).start_offset
try_node = _block_statement(t)
catch_node = None
finally_node = None
- try_endpos = None
+ try_end_offset = None
if t.peek().tok == tok.CATCH:
- catch_startpos = t.advance().startpos
+ catch_start_offset = t.advance().start_offset
t.expect(tok.LPAREN)
x = t.expect(tok.NAME)
- catch_expr = ParseNode(kind.NAME, None, x.startpos, x.endpos,
+ catch_expr = ParseNode(kind.NAME, None, x.start_offset, x.end_offset,
x.atom, [None])
t.expect(tok.RPAREN)
catch_block = _block_statement(t)
- catch_endpos = catch_block.endpos
+ catch_end_offset = catch_block.end_offset
catch_node = \
ParseNode(kind.RESERVED, None, None, None, None, [
ParseNode(kind.LEXICALSCOPE, op.LEAVEBLOCK,
- catch_startpos, catch_endpos, None, [
- ParseNode(kind.CATCH, None, catch_startpos,
- catch_endpos, None,
+ catch_start_offset, catch_end_offset, None, [
+ ParseNode(kind.CATCH, None, catch_start_offset,
+ catch_end_offset, None,
[catch_expr, None, catch_block])
])
])
- try_endpos = catch_endpos
+ try_end_offset = catch_end_offset
if t.peek().tok == tok.FINALLY:
t.advance()
finally_node = _block_statement(t)
- try_endpos = finally_node.endpos
+ try_end_offset = finally_node.end_offset
if not catch_node and not finally_node:
- raise JSSyntaxError(try_endpos, 'invalid_catch')
+ raise JSSyntaxError(try_end_offset, 'invalid_catch')
- return ParseNode(kind.TRY, None, try_startpos, try_endpos,
+ return ParseNode(kind.TRY, None, try_start_offset, try_end_offset,
None,
[try_node, catch_node, finally_node])
@@ -779,7 +779,7 @@
elif x.tok == tok.TRY:
return _try_statement(t)
elif x.tok == tok.EOF:
- raise JSSyntaxError(x.startpos, 'unexpected_eof')
+ raise JSSyntaxError(x.start_offset, 'unexpected_eof')
elif x.tok == tok.FUNCTION:
return _function_declaration(t, op.CLOSURE) #TODO: warn, since this is not reliable
@@ -788,13 +788,13 @@
if expr.kind == tok.NAME and t.peek().tok == tok.COLON:
t.expect(tok.COLON)
stmt = _statement(t)
- return ParseNode(kind.COLON, op.NAME, expr.startpos,
- stmt.endpos, expr.atom, [stmt])
+ return ParseNode(kind.COLON, op.NAME, expr.start_offset,
+ stmt.end_offset, expr.atom, [stmt])
- return _auto_semicolon(t, kind.SEMI, None, expr.startpos, expr.endpos,
+ return _auto_semicolon(t, kind.SEMI, None, expr.start_offset, expr.end_offset,
None, [expr])
else:
- raise JSSyntaxError(x.startpos, 'syntax_error')
+ raise JSSyntaxError(x.start_offset, 'syntax_error')
def _sourceelements(t, end_tok):
nodes = []
@@ -807,13 +807,14 @@
else:
nodes.append(_statement(t))
-def parsestring(s, startpos=None):
- stream = tokenizer.TokenStream(s, startpos)
+def parsestring(s, start_offset=0):
+ assert not start_offset is None
+ stream = tokenizer.TokenStream(s, start_offset)
t = tokenizer.Tokenizer(stream)
nodes = _sourceelements(t, tok.EOF)
- lc_endpos = t.expect(tok.EOF).endpos
- lc_startpos = nodes[-1].startpos if nodes else lc_endpos
- return ParseNode(kind.LC, None, lc_startpos, lc_endpos, None, nodes)
+ lc_end_offset = t.expect(tok.EOF).end_offset
+ lc_start_offset = nodes[-1].start_offset if nodes else lc_end_offset
+ return ParseNode(kind.LC, None, lc_start_offset, lc_end_offset, None, nodes)
def is_valid_version(version):
return version in _VERSIONS
@@ -824,14 +825,13 @@
assert kid.parent is node
_validate(kid, depth+1)
-def parse(script, jsversion,
- error_callback, startpos):
+def parse(script, jsversion, error_callback, start_offset):
# TODO: respect version
assert is_valid_version(jsversion)
try:
- root = parsestring(script, startpos)
+ root = parsestring(script, start_offset)
except JSSyntaxError as error:
- error_callback(error.pos.line, error.pos.col, error.msg, error.msg_args)
+ error_callback(error.offset, error.msg, error.msg_args)
return None
_validate(root)
return root
@@ -868,8 +868,8 @@
self.assertEquals(right.kind, kind.RC)
node = right.end_comma
self.assertEquals(node.kind, tok.COMMA)
- self.assertEquals(node.startpos, NodePos(0, 6))
- self.assertEquals(node.endpos, NodePos(0, 6))
+ self.assertEquals(node.start_offset, NodePos(0, 6))
+ self.assertEquals(node.end_offset, NodePos(0, 6))
def _testArrayEndComma(self, script, col):
root = parsestring(script)
node, = root.kids
@@ -885,8 +885,8 @@
self.assert_(node is None)
else:
self.assertEquals(node.kind, tok.COMMA)
- self.assertEquals(node.startpos, NodePos(0, col))
- self.assertEquals(node.endpos, NodePos(0, col))
+ self.assertEquals(node.start_offset, NodePos(0, col))
+ self.assertEquals(node.end_offset, NodePos(0, col))
def testArrayEndComma(self):
self._testArrayEndComma('a=[,]', 3)
self._testArrayEndComma('a=[a,]', 4)
Modified: trunk/jsengine/structs.py
===================================================================
--- trunk/jsengine/structs.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/jsengine/structs.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -90,26 +90,27 @@
class ParseNode:
node_index = None
parent = None
- def __init__(self, kind_, op_, start_pos, end_pos, atom, kids,
+ def __init__(self, kind_, op_, start_offset, end_offset, atom, kids,
no_semi=False, end_comma=None, fn_args=None):
assert not kids is None
assert kind.contains(kind_)
assert op_ is None or op.contains(op_)
if kind_ == kind.RESERVED:
- assert start_pos is None
- assert end_pos is None
+ assert start_offset is None
+ assert end_offset is None
else:
- assert isinstance(start_pos, NodePos), repr(start_pos)
- assert isinstance(end_pos, NodePos), repr(end_pos)
+ assert isinstance(start_offset, int), repr(start_offset)
+ assert isinstance(end_offset, int), repr(end_offset)
assert end_comma is None or isinstance(end_comma, ParseNode)
- assert (start_pos is None and end_pos is None) or start_pos <= end_pos
+ assert (start_offset is None and end_offset is None) or start_offset <= end_offset, \
+ (start_offset, end_offset)
self.kind = kind_
self.opcode = op_
self.atom = atom
self.kids = kids
self._lefthandside = False
- self.startpos = start_pos
- self.endpos = end_pos
+ self.start_offset = start_offset
+ self.end_offset = end_offset
self.no_semi = no_semi
self.end_comma = end_comma
@@ -132,11 +133,6 @@
else:
self.dval = float(self.atom)
- def start_pos(self):
- return self.startpos
- def end_pos(self):
- return self.endpos
-
def is_equivalent(self, other, are_functions_equiv=False):
if not other:
return False
Modified: trunk/jsengine/tokenizer/__init__.py
===================================================================
--- trunk/jsengine/tokenizer/__init__.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/jsengine/tokenizer/__init__.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -1,6 +1,5 @@
# vim: sw=4 ts=4 et
from jsengine import JSSyntaxError
-from jsengine.structs import NodePositions
_WHITESPACE = u'\u0020\t\u000B\u000C\u00A0\uFFFF'
_LINETERMINATOR = u'\u000A\u000D\u2028\u2029'
@@ -141,59 +140,60 @@
def __init__(self, tok, atom=None):
self.tok = tok
self.atom = atom
- self.startpos = None
- self.endpos = None
- def setpos(self, startpos, endpos):
- self.startpos = startpos
- self.endpos = endpos
+ self.start_offset = None
+ self.end_offset = None
+ def set_offset(self, start_offset, end_offset):
+ self.start_offset = start_offset
+ self.end_offset = end_offset
def __repr__(self):
return 'Token(%r, %r)' % \
(self.tok, self.atom)
class TokenStream:
- def __init__(self, content, startpos=None):
+ def __init__(self, content, start_offset=0):
+ assert isinstance(start_offset, int)
self._content = content
- self._pos = 0
- self._watched_pos = None
- self._nodepositions = NodePositions(content, startpos)
+ self._start_offset = start_offset
+ self._offset = 0
+ self._watched_offset = None
- def getpos(self, offset=0):
- return self._nodepositions.from_offset(self._pos+offset)
+ def get_offset(self, offset=0):
+ return self._start_offset + self._offset + offset
def watch_reads(self):
- self._watched_pos = self._pos
+ self._watched_offset = self._offset
def get_watched_reads(self):
- assert not self._watched_pos == None
- s = self._content[self._watched_pos:self._pos]...
[truncated message content] |