Fixups and a bunch more tests - parsing seems to be working now.
Removed debugging printouts.
This commit is contained in:
parent
8937d8d40a
commit
19958d11c6
1 changed files with 43 additions and 6 deletions
49
chapter2.py
49
chapter2.py
|
|
@ -195,7 +195,6 @@ class Parser(object):
|
||||||
def _parse_identifier_expr(self):
|
def _parse_identifier_expr(self):
|
||||||
id_name = self.cur_tok.value
|
id_name = self.cur_tok.value
|
||||||
self._get_next_token()
|
self._get_next_token()
|
||||||
print('* _parse_identifier_expr:', self.cur_tok)
|
|
||||||
# If followed by a '(' it's a call; otherwise, a simple variable ref.
|
# If followed by a '(' it's a call; otherwise, a simple variable ref.
|
||||||
if not self._cur_tok_is_operator('('):
|
if not self._cur_tok_is_operator('('):
|
||||||
return VariableExprAST(id_name)
|
return VariableExprAST(id_name)
|
||||||
|
|
@ -252,7 +251,6 @@ class Parser(object):
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
cur_prec = self._cur_tok_precedence()
|
cur_prec = self._cur_tok_precedence()
|
||||||
print('* _parse_binop_rhs', self.cur_tok, ' --> prec=', cur_prec)
|
|
||||||
# If this is a binary operator with precedence lower than the
|
# If this is a binary operator with precedence lower than the
|
||||||
# currently parsed sub-expression, bail out. If it binds at least
|
# currently parsed sub-expression, bail out. If it binds at least
|
||||||
# as tightly, keep going.
|
# as tightly, keep going.
|
||||||
|
|
@ -262,7 +260,6 @@ class Parser(object):
|
||||||
return lhs
|
return lhs
|
||||||
op = self.cur_tok.value
|
op = self.cur_tok.value
|
||||||
self._get_next_token() # consume the operator
|
self._get_next_token() # consume the operator
|
||||||
print(' after consume op:', self.cur_tok)
|
|
||||||
rhs = self._parse_primary()
|
rhs = self._parse_primary()
|
||||||
|
|
||||||
next_prec = self._cur_tok_precedence()
|
next_prec = self._cur_tok_precedence()
|
||||||
|
|
@ -280,9 +277,7 @@ class Parser(object):
|
||||||
|
|
||||||
# expression ::= primary binoprhs
|
# expression ::= primary binoprhs
|
||||||
def _parse_expression(self):
|
def _parse_expression(self):
|
||||||
print('* _parse_expression:', self.cur_tok)
|
|
||||||
lhs = self._parse_primary()
|
lhs = self._parse_primary()
|
||||||
print(' after lhs:', self.cur_tok)
|
|
||||||
# Start with precedence 0 because we want to bind any operator to the
|
# Start with precedence 0 because we want to bind any operator to the
|
||||||
# expression at this point.
|
# expression at this point.
|
||||||
return self._parse_binop_rhs(0, lhs)
|
return self._parse_binop_rhs(0, lhs)
|
||||||
|
|
@ -383,7 +378,7 @@ class TestParser(unittest.TestCase):
|
||||||
args = [self._flatten(arg) for arg in ast.args]
|
args = [self._flatten(arg) for arg in ast.args]
|
||||||
return ['Call', ast.callee, args]
|
return ['Call', ast.callee, args]
|
||||||
elif isinstance(ast, PrototypeAST):
|
elif isinstance(ast, PrototypeAST):
|
||||||
return ['Proto', ast.name, ', '.join(ast.argnames)]
|
return ['Proto', ast.name, ' '.join(ast.argnames)]
|
||||||
elif isinstance(ast, FunctionAST):
|
elif isinstance(ast, FunctionAST):
|
||||||
return ['Function',
|
return ['Function',
|
||||||
self._flatten(ast.proto), self._flatten(ast.body)]
|
self._flatten(ast.proto), self._flatten(ast.body)]
|
||||||
|
|
@ -405,9 +400,51 @@ class TestParser(unittest.TestCase):
|
||||||
def test_basic_with_flattening(self):
|
def test_basic_with_flattening(self):
|
||||||
ast = Parser('2').parse_toplevel()
|
ast = Parser('2').parse_toplevel()
|
||||||
self._assert_body(ast, ['Number', '2'])
|
self._assert_body(ast, ['Number', '2'])
|
||||||
|
|
||||||
ast = Parser('foobar').parse_toplevel()
|
ast = Parser('foobar').parse_toplevel()
|
||||||
self._assert_body(ast, ['Variable', 'foobar'])
|
self._assert_body(ast, ['Variable', 'foobar'])
|
||||||
|
|
||||||
|
def test_expr_singleprec(self):
|
||||||
|
ast = Parser('2+ 3-4').parse_toplevel()
|
||||||
|
self._assert_body(ast,
|
||||||
|
['Binop',
|
||||||
|
'-', ['Binop', '+', ['Number', '2'], ['Number', '3']],
|
||||||
|
['Number', '4']])
|
||||||
|
|
||||||
|
def test_expr_multiprec(self):
|
||||||
|
ast = Parser('2+3*4-9').parse_toplevel()
|
||||||
|
self._assert_body(ast,
|
||||||
|
['Binop', '-',
|
||||||
|
['Binop', '+',
|
||||||
|
['Number', '2'],
|
||||||
|
['Binop', '*', ['Number', '3'], ['Number', '4']]],
|
||||||
|
['Number', '9']])
|
||||||
|
|
||||||
|
def test_expr_parens(self):
|
||||||
|
ast = Parser('2*(3-4)*7').parse_toplevel()
|
||||||
|
self._assert_body(ast,
|
||||||
|
['Binop', '*',
|
||||||
|
['Binop', '*',
|
||||||
|
['Number', '2'],
|
||||||
|
['Binop', '-', ['Number', '3'], ['Number', '4']]],
|
||||||
|
['Number', '7']])
|
||||||
|
|
||||||
|
def test_externals(self):
|
||||||
|
ast = Parser('extern sin(arg)').parse_toplevel()
|
||||||
|
self.assertEqual(self._flatten(ast), ['Proto', 'sin', 'arg'])
|
||||||
|
|
||||||
|
ast = Parser('extern Foobar(nom denom abom)').parse_toplevel()
|
||||||
|
self.assertEqual(self._flatten(ast),
|
||||||
|
['Proto', 'Foobar', 'nom denom abom'])
|
||||||
|
|
||||||
|
def test_funcdef(self):
|
||||||
|
ast = Parser('def foo(x) 1 + bar(x)').parse_toplevel()
|
||||||
|
self.assertEqual(self._flatten(ast),
|
||||||
|
['Function', ['Proto', 'foo', 'x'],
|
||||||
|
['Binop', '+',
|
||||||
|
['Number', '1'],
|
||||||
|
['Call', 'bar', [['Variable', 'x']]]]])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
buf = '''2+3*fob(12, kwa)-.12'''
|
buf = '''2+3*fob(12, kwa)-.12'''
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue