[jsinterp] Adding with and switch parser and fixes (tests needed)

- parsing empty block
- more specific check at else block
This commit is contained in:
sulyi 2016-12-11 11:48:31 +01:00
parent 57c8ccb7c5
commit ad49621758

View File

@ -108,16 +108,17 @@ class JSInterpreter(object):
elif token_id is Token.COPEN: elif token_id is Token.COPEN:
open_pos = token_pos open_pos = token_pos
token_stream.pop() token_stream.pop()
statement_list = [] block = []
while True: while True:
statement_list.append(self._next_statement(token_stream, stack_top - 1))
token_stream.pop()
token_id, token_value, token_pos = token_stream.peek() token_id, token_value, token_pos = token_stream.peek()
if token_id is Token.CCLOSE: if token_id is Token.CCLOSE:
break break
elif token_id is Token.END and token_stream.ended: elif token_id is Token.END and token_stream.ended:
raise ExtractorError('Unbalanced parentheses at %d' % open_pos) raise ExtractorError('Unbalanced parentheses at %d' % open_pos)
statement = (Token.BLOCK, statement_list) block.append(self._next_statement(token_stream, stack_top - 1))
token_stream.pop()
statement = (Token.BLOCK, block)
elif token_id is Token.ID: elif token_id is Token.ID:
# TODO parse label # TODO parse label
@ -158,7 +159,7 @@ class JSInterpreter(object):
token_id, token_value, token_pos = token_stream.pop() token_id, token_value, token_pos = token_stream.pop()
if token_id is not Token.POPEN: if token_id is not Token.POPEN:
raise ExtractorError('Missing condition at %d' % token_pos) raise ExtractorError('Missing condition at %d' % token_pos)
cond_expr = self._next_statement(token_stream, stack_top - 1) cond_expr = self._expression(token_stream, stack_top - 1)
token_stream.pop() # Token.PCLOSE token_stream.pop() # Token.PCLOSE
true_expr = self._next_statement(token_stream, stack_top - 1) true_expr = self._next_statement(token_stream, stack_top - 1)
token_id, token_value, token_pos = token_stream.peek() token_id, token_value, token_pos = token_stream.peek()
@ -166,7 +167,7 @@ class JSInterpreter(object):
token_stream.pop() token_stream.pop()
token_id, token_value, token_pos = token_stream.peek() token_id, token_value, token_pos = token_stream.peek()
false_expr = None false_expr = None
if token_value == 'else': if token_id is Token.ID and token_value == 'else':
token_stream.pop() token_stream.pop()
false_expr = self._next_statement(token_stream, stack_top - 1) false_expr = self._next_statement(token_stream, stack_top - 1)
statement = (Token.IF, cond_expr, true_expr, false_expr) statement = (Token.IF, cond_expr, true_expr, false_expr)
@ -180,12 +181,11 @@ class JSInterpreter(object):
token = {'break': Token.BREAK, 'continue': Token.CONTINUE}[token_value] token = {'break': Token.BREAK, 'continue': Token.CONTINUE}[token_value]
peek_id, peek_value, peek_pos = token_stream.peek() peek_id, peek_value, peek_pos = token_stream.peek()
# XXX no line break here # XXX no line break here
label = None
if peek_id is not Token.END: if peek_id is not Token.END:
token_stream.chk_id() token_stream.chk_id()
label = peek_value label = peek_value
token_stream.pop() token_stream.pop()
else:
label = None
statement = (token, label) statement = (token, label)
peek_id, peek_value, peek_pos = token_stream.peek() peek_id, peek_value, peek_pos = token_stream.peek()
if peek_id is not Token.END: if peek_id is not Token.END:
@ -204,12 +204,66 @@ class JSInterpreter(object):
raise ExtractorError('Unexpected sequence %s at %d' % (peek_value, peek_pos)) raise ExtractorError('Unexpected sequence %s at %d' % (peek_value, peek_pos))
elif token_value == 'with': elif token_value == 'with':
# TODO parse withstatement token_stream.pop()
raise ExtractorError('With statement is not yet supported at %d' % token_pos) token_id, token_value, token_pos = token_stream.pop()
if token_id is not Token.POPEN:
raise ExtractorError('Missing expression at %d' % token_pos)
expr = self._expression(token_stream, stack_top - 1)
token_stream.pop() # Token.PCLOSE
statement = (Token.WITH, expr, self._next_statement(token_stream, stack_top - 1))
elif token_value == 'switch': elif token_value == 'switch':
# TODO parse switchstatement token_stream.pop()
raise ExtractorError('Switch statement is not yet supported at %d' % token_pos) token_id, token_value, token_pos = token_stream.pop()
if token_id is not Token.POPEN:
raise ExtractorError('Missing expression at %d' % token_pos)
discriminant = self._expression(token_stream, stack_top - 1)
token_stream.pop() # Token.PCLOSE
token_id, token_value, token_pos = token_stream.pop()
if token_id is not Token.COPEN:
raise ExtractorError('Missing case block at %d' % token_pos)
open_pos = token_pos
has_default = False
block = []
while True:
token_id, token_value, token_pos = token_stream.peek()
if token_id is Token.CCLOSE:
break
elif token_id is Token.ID and token_value == 'case':
token_stream.pop()
expr = self._expression(token_stream, stack_top - 1)
elif token_id is Token.ID and token_value == 'default':
if has_default:
raise ExtractorError('Multiple default clause')
token_stream.pop()
has_default = True
expr = None
elif token_id is Token.END and token_stream.ended:
raise ExtractorError('Unbalanced parentheses at %d' % open_pos)
else:
raise ExtractorError('Unexpected sequence at %d, default or case clause is expected' %
token_pos)
token_id, token_value, token_pos = token_stream.pop()
if token_id is not Token.COLON:
raise ExtractorError('''Unexpected sequence at %d, ':' is expected''' % token_pos)
statement_list = []
while True:
token_id, token_value, token_pos = token_stream.peek()
if token_id == Token.CCLOSE or (token_id is Token.ID and (token_value in ('default', 'case'))):
break
elif token_id is Token.END and token_stream.ended:
raise ExtractorError('Unbalanced parentheses at %d' % open_pos)
statement_list.append(self._next_statement(token_id, stack_top - 1))
token_stream.pop()
block.append((expr, statement_list))
statement = (Token.BLOCK, discriminant, block)
elif token_value == 'throw': elif token_value == 'throw':
# TODO parse throwstatement # TODO parse throwstatement