[jsinterp] Adding ast to for empty and for in parser test
This commit is contained in:
parent
b397ea2bdd
commit
cd0bb42f4e
@ -835,24 +835,47 @@ class TestJSInterpreterParser(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(list(traverse(list(jsi.statements()))), list(traverse(ast)))
|
self.assertEqual(list(traverse(list(jsi.statements()))), list(traverse(ast)))
|
||||||
|
|
||||||
@unittest.skip('Test not yet implemented: missing ast')
|
|
||||||
def test_for_empty(self):
|
def test_for_empty(self):
|
||||||
# ASAP for empty statement test
|
|
||||||
jsi = JSInterpreter('''
|
jsi = JSInterpreter('''
|
||||||
function f(x){
|
function f(x){
|
||||||
var h = 0
|
var h = 0;
|
||||||
for (; h <= x; ++h) {
|
for (; h <= x; ++h) {
|
||||||
a = h;
|
a = h;
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
''')
|
''')
|
||||||
ast = []
|
ast = [
|
||||||
|
(Token.FUNC, 'f', ['x'],
|
||||||
|
(Token.BLOCK, [
|
||||||
|
(Token.VAR, zip(['h'], [
|
||||||
|
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.INT, 0), None, None)]), None)
|
||||||
|
])),
|
||||||
|
(Token.FOR,
|
||||||
|
None,
|
||||||
|
(Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
|
||||||
|
(Token.MEMBER, (Token.ID, 'h'), None, None),
|
||||||
|
(Token.MEMBER, (Token.ID, 'x'), None, None),
|
||||||
|
(Token.REL, _RELATIONS['<='][1])
|
||||||
|
]), None)]),
|
||||||
|
(Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
|
||||||
|
(Token.MEMBER, (Token.ID, 'h'), None, None),
|
||||||
|
(Token.UOP, _UNARY_OPERATORS['++'][1])
|
||||||
|
]), None)]),
|
||||||
|
(Token.BLOCK, [
|
||||||
|
(Token.EXPR, [
|
||||||
|
(Token.ASSIGN, _ASSIGN_OPERATORS['='][1],
|
||||||
|
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'a'), None, None)]),
|
||||||
|
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'h'), None, None)]), None))
|
||||||
|
])
|
||||||
|
])),
|
||||||
|
(Token.RETURN, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
|
||||||
|
(Token.MEMBER, (Token.ID, 'a'), None, None)]), None)]))
|
||||||
|
]))
|
||||||
|
]
|
||||||
self.assertEqual(list(traverse(list(jsi.statements()))), list(traverse(ast)))
|
self.assertEqual(list(traverse(list(jsi.statements()))), list(traverse(ast)))
|
||||||
|
|
||||||
@unittest.skip('Test not yet implemented: missing ast')
|
|
||||||
def test_for_in(self):
|
def test_for_in(self):
|
||||||
# ASAP for in statement test
|
|
||||||
jsi = JSInterpreter('''
|
jsi = JSInterpreter('''
|
||||||
function f(z){
|
function f(z){
|
||||||
for (h in z) {
|
for (h in z) {
|
||||||
@ -861,7 +884,28 @@ class TestJSInterpreterParser(unittest.TestCase):
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
''')
|
''')
|
||||||
ast = []
|
ast = [
|
||||||
|
(Token.FUNC, 'f', ['z'],
|
||||||
|
(Token.BLOCK, [
|
||||||
|
(Token.FOR,
|
||||||
|
(Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
|
||||||
|
(Token.MEMBER, (Token.ID, 'h'), None, None)
|
||||||
|
]), None)]),
|
||||||
|
(Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
|
||||||
|
(Token.MEMBER, (Token.ID, 'z'), None, None)
|
||||||
|
]), None)]),
|
||||||
|
None,
|
||||||
|
(Token.BLOCK, [
|
||||||
|
(Token.EXPR, [
|
||||||
|
(Token.ASSIGN, _ASSIGN_OPERATORS['='][1],
|
||||||
|
(Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'a'), None, None)]),
|
||||||
|
(Token.ASSIGN, None, (Token.OPEXPR, [(Token.MEMBER, (Token.ID, 'h'), None, None)]), None))
|
||||||
|
])
|
||||||
|
])),
|
||||||
|
(Token.RETURN, (Token.EXPR, [(Token.ASSIGN, None, (Token.OPEXPR, [
|
||||||
|
(Token.MEMBER, (Token.ID, 'a'), None, None)]), None)]))
|
||||||
|
]))
|
||||||
|
]
|
||||||
self.assertEqual(list(jsi.statements()), ast)
|
self.assertEqual(list(jsi.statements()), ast)
|
||||||
|
|
||||||
def test_do(self):
|
def test_do(self):
|
||||||
|
@ -30,9 +30,10 @@ __ESC_HEX_RE = r'x[0-9a-fA-F]{2}'
|
|||||||
|
|
||||||
|
|
||||||
# NOTE order is fixed due to regex matching, does not represent any precedence
|
# NOTE order is fixed due to regex matching, does not represent any precedence
|
||||||
|
# NOTE unary operator 'delete', 'void', 'instanceof' and relation 'in' and 'instanceof' do not handled this way
|
||||||
_logical_operator = ['||', '&&']
|
_logical_operator = ['||', '&&']
|
||||||
_relation = ['===', '!==', '==', '!=', '<=', '>=', '<', '>']
|
_relation = ['===', '!==', '==', '!=', '<=', '>=', '<', '>']
|
||||||
_unary_operator = ['++', '--', '!', '~', 'delete', 'void', 'typeof']
|
_unary_operator = ['++', '--', '!', '~']
|
||||||
_operator = ['|', '^', '&', '>>>', '>>', '<<', '-', '+', '%', '/', '*']
|
_operator = ['|', '^', '&', '>>>', '>>', '<<', '-', '+', '%', '/', '*']
|
||||||
_assign_operator = [op + '=' for op in _operator]
|
_assign_operator = [op + '=' for op in _operator]
|
||||||
_assign_operator.append('=')
|
_assign_operator.append('=')
|
||||||
|
@ -102,7 +102,6 @@ class JSInterpreter(object):
|
|||||||
|
|
||||||
elif token_id is Token.ID:
|
elif token_id is Token.ID:
|
||||||
if token_value == 'var':
|
if token_value == 'var':
|
||||||
# XXX refactor (create dedicated method for handling variable declaration list)
|
|
||||||
token_stream.pop()
|
token_stream.pop()
|
||||||
variables = []
|
variables = []
|
||||||
init = []
|
init = []
|
||||||
@ -252,17 +251,18 @@ class JSInterpreter(object):
|
|||||||
if token_id is Token.END:
|
if token_id is Token.END:
|
||||||
init = None
|
init = None
|
||||||
elif token_id is Token.ID and token_value == 'var':
|
elif token_id is Token.ID and token_value == 'var':
|
||||||
|
# XXX change it on refactoring variable declaration list
|
||||||
init = self._statement(token_stream, stack_top - 1)
|
init = self._statement(token_stream, stack_top - 1)
|
||||||
else:
|
else:
|
||||||
init = self._expression(token_stream, stack_top - 1)
|
init = self._expression(token_stream, stack_top - 1)
|
||||||
self._context.no_in = True
|
self._context.no_in = True
|
||||||
|
|
||||||
token_id, token_value, token_pos = token_stream.pop()
|
token_id, token_value, token_pos = token_stream.pop()
|
||||||
if token_id is Token.IN:
|
if token_id is Token.ID and token_value == 'in':
|
||||||
cond = self._expression(token_stream, stack_top - 1)
|
cond = self._expression(token_stream, stack_top - 1)
|
||||||
# FIXME further processing might be needed for interpretation
|
# FIXME further processing of operator 'in' needed for interpretation
|
||||||
incr = None
|
incr = None
|
||||||
# NOTE ES6 has of operator
|
# NOTE ES6 has 'of' operator
|
||||||
elif token_id is Token.END:
|
elif token_id is Token.END:
|
||||||
token_id, token_value, token_pos = token_stream.peek()
|
token_id, token_value, token_pos = token_stream.peek()
|
||||||
cond = None if token_id is Token.END else self._expression(token_stream, stack_top - 1)
|
cond = None if token_id is Token.END else self._expression(token_stream, stack_top - 1)
|
||||||
@ -881,6 +881,8 @@ class JSInterpreter(object):
|
|||||||
rpn = expr[1][:]
|
rpn = expr[1][:]
|
||||||
while rpn:
|
while rpn:
|
||||||
token = rpn.pop(0)
|
token = rpn.pop(0)
|
||||||
|
# XXX add unary operator 'delete', 'void', 'instanceof'
|
||||||
|
# XXX relation 'in' 'instanceof'
|
||||||
if token[0] in (Token.OP, Token.AOP, Token.UOP, Token.LOP, Token.REL):
|
if token[0] in (Token.OP, Token.AOP, Token.UOP, Token.LOP, Token.REL):
|
||||||
right = stack.pop()
|
right = stack.pop()
|
||||||
left = stack.pop()
|
left = stack.pop()
|
||||||
|
@ -48,12 +48,14 @@ _RELATIONS = {
|
|||||||
'>': (Token.GT, operator.gt),
|
'>': (Token.GT, operator.gt),
|
||||||
'<=': (Token.LE, operator.le),
|
'<=': (Token.LE, operator.le),
|
||||||
'>=': (Token.GE, operator.ge),
|
'>=': (Token.GE, operator.ge),
|
||||||
# XXX add instanceof and in operators
|
|
||||||
# XXX check python and JavaScript equality difference
|
# XXX check python and JavaScript equality difference
|
||||||
'==': (Token.EQ, operator.eq),
|
'==': (Token.EQ, operator.eq),
|
||||||
'!=': (Token.NE, operator.ne),
|
'!=': (Token.NE, operator.ne),
|
||||||
'===': (Token.SEQ, lambda cur, right: cur == right and type(cur) == type(right)),
|
'===': (Token.SEQ, lambda cur, right: cur == right and type(cur) == type(right)),
|
||||||
'!==': (Token.SNE, lambda cur, right: not cur == right or not type(cur) == type(right))
|
'!==': (Token.SNE, lambda cur, right: not cur == right or not type(cur) == type(right)),
|
||||||
|
# XXX define instanceof and in operators
|
||||||
|
'in': (Token.IN, None),
|
||||||
|
'instanceof': (Token.INSTANCEOF, None)
|
||||||
}
|
}
|
||||||
_OPERATORS = {
|
_OPERATORS = {
|
||||||
'|': (Token.BOR, operator.or_),
|
'|': (Token.BOR, operator.or_),
|
||||||
@ -132,7 +134,9 @@ class TokenStream(object):
|
|||||||
elif token_id is Token.ID:
|
elif token_id is Token.ID:
|
||||||
yield (token_id, token_value, pos)
|
yield (token_id, token_value, pos)
|
||||||
elif token_id in _operator_lookup:
|
elif token_id in _operator_lookup:
|
||||||
yield (token_id, _operator_lookup[token_id][token_value], pos)
|
yield (token_id if token_value != 'in' else Token.IN,
|
||||||
|
_operator_lookup[token_id][token_value],
|
||||||
|
pos)
|
||||||
elif token_id is Token.PUNCT:
|
elif token_id is Token.PUNCT:
|
||||||
yield (_PUNCTUATIONS[token_value], token_value, pos)
|
yield (_PUNCTUATIONS[token_value], token_value, pos)
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user