Skip to content

Commit 3861557

Browse files
committed
Parse guards (ew)
1 parent 410cecc commit 3861557

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

scrapscript.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ def read_var(self, first_char: str) -> Token:
253253
while self.has_input() and is_identifier_char(c := self.peek_char()):
254254
self.read_char()
255255
buf += c
256+
if buf == "guard":
257+
return self.make_token(Operator, "guard")
256258
return self.make_token(Name, buf)
257259

258260
def read_bytes(self) -> Token:
@@ -303,6 +305,7 @@ def xp(n: float) -> Prec:
303305
"::": lp(2000),
304306
"@": rp(1001),
305307
"": rp(1000),
308+
"guard": rp(5.5),
306309
">>": lp(14),
307310
"<<": lp(14),
308311
"^": rp(13),
@@ -342,7 +345,7 @@ def xp(n: float) -> Prec:
342345
HIGHEST_PREC: float = max(max(p.pl, p.pr) for p in PS.values())
343346

344347

345-
OPER_CHARS = set("".join(PS.keys()))
348+
OPER_CHARS = set("".join(PS.keys())) - set("guard")
346349
assert " " not in OPER_CHARS
347350

348351

@@ -493,6 +496,8 @@ def parse(tokens: typing.List[Token], p: float = 0) -> "Object":
493496
elif op == Operator("@"):
494497
# TODO: revisit whether to use @ or . for field access
495498
l = Access(l, parse(tokens, pr))
499+
elif op == Operator("guard"):
500+
l = Guard(l, parse(tokens, pr))
496501
else:
497502
assert not isinstance(op, Juxt)
498503
assert isinstance(op, Operator)
@@ -868,6 +873,12 @@ def __str__(self) -> str:
868873
return f"EnvObject(keys={self.env.keys()})"
869874

870875

876+
@dataclass(eq=True, frozen=True, unsafe_hash=True)
877+
class Guard(Object):
878+
pattern: Object
879+
cond: Object
880+
881+
871882
@dataclass(eq=True, frozen=True, unsafe_hash=True)
872883
class MatchCase(Object):
873884
pattern: Object
@@ -2327,6 +2338,18 @@ def test_parse_record_with_trailing_comma_raises_parse_error(self) -> None:
23272338
def test_parse_symbol_returns_symbol(self) -> None:
23282339
self.assertEqual(parse([SymbolToken("abc")]), Symbol("abc"))
23292340

2341+
def test_parse_guard(self) -> None:
2342+
self.assertEqual(
2343+
parse(tokenize("| x guard y -> x")),
2344+
MatchFunction([MatchCase(Guard(Var("x"), Var("y")), Var("x"))]),
2345+
)
2346+
2347+
def test_parse_guard_exp(self) -> None:
2348+
self.assertEqual(
2349+
parse(tokenize("| x guard x==1 -> x")),
2350+
MatchFunction([MatchCase(Guard(Var("x"), Binop(BinopKind.EQUAL, Var("x"), Int(1))), Var("x"))]),
2351+
)
2352+
23302353

23312354
class MatchTests(unittest.TestCase):
23322355
def test_match_with_equal_ints_returns_empty_dict(self) -> None:

0 commit comments

Comments
 (0)