Skip to content

Commit a36d774

Browse files
committed
challenge 6.3 done
1 parent f94195f commit a36d774

File tree

2 files changed

+79
-5
lines changed

2 files changed

+79
-5
lines changed

pylox/parser.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# recursive descent, top-down parser
1010
class Parser:
1111
def __init__(
12-
self, tokens: List[Token], report_error: Optional[Callable] = None
12+
self, tokens: List[Token], report_error: Optional[Callable] = None
1313
) -> None:
1414
self.tokens = tokens
1515
self.current = 0
@@ -104,10 +104,10 @@ def comparison(self) -> ast.Expr:
104104
expr = self.term()
105105

106106
while self.match(
107-
TokenType.GREATER,
108-
TokenType.GREATER_EQUAL,
109-
TokenType.LESS,
110-
TokenType.LESS_EQUAL,
107+
TokenType.GREATER,
108+
TokenType.GREATER_EQUAL,
109+
TokenType.LESS,
110+
TokenType.LESS_EQUAL,
111111
):
112112
op = self.previous()
113113
right = self.term()
@@ -163,4 +163,35 @@ def primary(self) -> ast.Expr:
163163
self.consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.")
164164
return ast.Grouping(expr)
165165

166+
# Error handling
167+
if self.match(TokenType.BANG_EQUAL, TokenType.EQUAL_EQUAL):
168+
err = self.error(self.previous(), "Missing left-hand operand.")
169+
self.equality()
170+
raise err
171+
172+
if self.match(TokenType.BANG_EQUAL, TokenType.EQUAL_EQUAL):
173+
err = self.error(self.previous(), "Missing left-hand operand.")
174+
self.equality()
175+
raise err
176+
177+
if self.match(
178+
TokenType.GREATER,
179+
TokenType.GREATER_EQUAL,
180+
TokenType.LESS,
181+
TokenType.LESS_EQUAL,
182+
):
183+
err = self.error(self.previous(), "Missing left-hand operand.")
184+
self.comparison()
185+
raise err
186+
187+
if self.match(TokenType.PLUS):
188+
err = self.error(self.previous(), "Missing left-hand operand.")
189+
self.term()
190+
raise err
191+
192+
if self.match(TokenType.SLASH, TokenType.STAR):
193+
err = self.error(self.previous(), "Missing left-hand operand.")
194+
self.factor()
195+
raise err
196+
166197
raise self.error(self.peek(), "Expect expression")

tests/test_parser.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,46 @@ def test_if_parser_handles_empty_right_hand_operand_inside_binary_expression() -
3939
Parser(tokens).expression()
4040
# THEN
4141
assert "Expect expression" in err.value.message
42+
43+
44+
def test_if_parser_handles_empty_left_hand_operand_inside_binary_expression() -> (
45+
None
46+
):
47+
# GIVEN
48+
src = "* 123"
49+
# WHEN
50+
tokens = Scanner(src).scan_tokens()
51+
with pytest.raises(LoxParseError) as err:
52+
Parser(tokens).expression()
53+
# THEN
54+
assert "Missing left-hand operand." in err.value.message
55+
56+
57+
def test_if_parser_parse_and_discard_right_hand_operand_in_case_of_empty_left_hand_operant() -> (
58+
None
59+
):
60+
# GIVEN
61+
src = "* (123"
62+
63+
# MOCK
64+
cnt = 0
65+
66+
def handler(err: LoxParseError):
67+
nonlocal cnt
68+
69+
if cnt == 0:
70+
assert err.message == "Missing left-hand operand."
71+
elif cnt == 1:
72+
assert err.message == "Expect ')' after expression."
73+
else:
74+
assert False
75+
76+
cnt += 1
77+
78+
# WHEN
79+
tokens = Scanner(src).scan_tokens()
80+
ast = Parser(tokens, handler).parse()
81+
82+
# THEN
83+
assert ast is None
84+
assert cnt == 2 # both errors have been handled

0 commit comments

Comments
 (0)