Skip to content

Commit 4bee9c9

Browse files
authored
Parser improvements (#45)
2 parents 6dc3da3 + ed8e1b4 commit 4bee9c9

3 files changed

Lines changed: 273 additions & 430 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# The parser seeds a left-recursion sentinel only for the rules that can re-enter themselves
2+
# at the same position, which after the precedence-climbing and postfix-loop rewrites is just
3+
# two: dotted_name (`import a.b.c`) and t_primary (the target side of an assignment).
4+
#
5+
# Those two are the reason the sentinel and grow_lr still exist, and this file is what proves
6+
# they still work. If a rule is dropped from is_left_recursive it will recurse without
7+
# terminating, and if a newly left-recursive rule is added without an entry the same happens
8+
# there - so a hang here is as much a failure as a wrong answer.
9+
10+
# dotted_name: dotted_name '.' NAME | NAME
11+
import os.path
12+
13+
assert os.path.sep == "/"
14+
15+
import os.path as shortcut
16+
17+
assert shortcut.sep == "/"
18+
19+
from os.path import sep
20+
21+
assert sep == "/"
22+
23+
24+
# t_primary: the left-recursive part of an assignment target. The parser matches the longest
25+
# prefix that is still followed by a postfix operator, and the enclosing rule takes the last
26+
# one, so each extra link here exercises another turn of the seed-growing loop.
27+
nested = {"x": {"y": [1, 2]}}
28+
nested["x"]["y"][0] = 9
29+
assert nested["x"]["y"][0] == 9
30+
assert nested["x"]["y"][1] == 2
31+
32+
33+
class Holder:
34+
def __init__(self):
35+
self.d = {"k": [0, 0]}
36+
self.child = None
37+
38+
39+
h = Holder()
40+
h.d["k"][0] = 5
41+
assert h.d["k"][0] == 5
42+
43+
# attribute target reached through another attribute
44+
h.child = Holder()
45+
h.child.d["k"][1] = 7
46+
assert h.child.d["k"][1] == 7
47+
48+
# a longer chain: attribute, attribute, subscript, subscript
49+
h.child.child = Holder()
50+
h.child.child.d["k"][0] = 11
51+
assert h.child.child.d["k"][0] == 11
52+
53+
# plain attribute targets still work alongside the chained ones
54+
h.child.child.d = {"k": [1]}
55+
assert h.child.child.d["k"][0] == 1
56+
57+
print("left_recursive_rules: ok")

0 commit comments

Comments
 (0)