1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 '''
31 Tests for the lepl.support.node module.
32 '''
33
34
35 from unittest import TestCase
36
37 from lepl import Delayed, Digit, Any, Node, make_error, node_throw, Or, Space, \
38 AnyBut, Eos
39 from lepl.support.graph import order, PREORDER, POSTORDER, LEAF
40 from lepl._test.base import assert_str
41
42
43
44
45
46
48
50
51
52 class Term(Node): pass
53 class Factor(Node): pass
54 class Expression(Node): pass
55
56 expression = Delayed()
57 number = Digit()[1:,...] > 'number'
58 term = (number | '(' / expression / ')') > Term
59 muldiv = Any('*/') > 'operator'
60 factor = (term / (muldiv / term)[0::]) > Factor
61 addsub = Any('+-') > 'operator'
62 expression += (factor / (addsub / factor)[0::]) > Expression
63
64 p = expression.get_parse_string()
65 ast = p('1 + 2 * (3 + 4 - 5)')
66 assert_str(ast[0], """Expression
67 +- Factor
68 | +- Term
69 | | `- number '1'
70 | `- ' '
71 +- operator '+'
72 +- ' '
73 `- Factor
74 +- Term
75 | `- number '2'
76 +- ' '
77 +- operator '*'
78 +- ' '
79 `- Term
80 +- '('
81 +- Expression
82 | +- Factor
83 | | +- Term
84 | | | `- number '3'
85 | | `- ' '
86 | +- operator '+'
87 | +- ' '
88 | +- Factor
89 | | +- Term
90 | | | `- number '4'
91 | | `- ' '
92 | +- operator '-'
93 | +- ' '
94 | `- Factor
95 | `- Term
96 | `- number '5'
97 `- ')'""")
98
100
102
103
104 expression = Delayed()
105 number = Digit()[1:,...] > 'number'
106 term = (number | '(' / expression / ')') > list
107 muldiv = Any('*/') > 'operator'
108 factor = (term / (muldiv / term)[0:]) > list
109 addsub = Any('+-') > 'operator'
110 expression += (factor / (addsub / factor)[0:]) > list
111
112 ast = expression.parse_string('1 + 2 * (3 + 4 - 5)')
113 assert ast == [[[[('number', '1')], ' '], ('operator', '+'), ' ', [[('number', '2')], ' ', ('operator', '*'), ' ', ['(', [[[('number', '3')], ' '], ('operator', '+'), ' ', [[('number', '4')], ' '], ('operator', '-'), ' ', [[('number', '5')]]], ')']]]], ast
114
115
117
119
120
121 class Term(Node): pass
122 class Factor(Node): pass
123 class Expression(Node): pass
124
125 expression = Delayed()
126 number = Digit()[1:,...] > 'number'
127 term = Or(
128 AnyBut(Space() | Digit() | '(')[1:,...] ^ 'unexpected text: {results[0]}',
129 number > Term,
130 number ** make_error("no ( before {out_rest}") / ')' >> node_throw,
131 '(' / expression / ')' > Term,
132 ('(' / expression / Eos()) ** make_error("no ) for {in_rest}") >> node_throw)
133 muldiv = Any('*/') > 'operator'
134 factor = (term / (muldiv / term)[0:,r'\s*']) > Factor
135 addsub = Any('+-') > 'operator'
136 expression += (factor / (addsub / factor)[0:,r'\s*']) > Expression
137 line = expression / Eos()
138
139 parser = line.get_parse_string()
140
141 try:
142 parser('1 + 2 * 3 + 4 - 5)')[0]
143 assert False, 'expected error'
144 except SyntaxError as e:
145 assert e.msg == "no ( before ')'", e.msg
146
147 try:
148 parser('1 + 2 * (3 + 4 - 5')
149 assert False, 'expected error'
150 except SyntaxError as e:
151 assert e.msg == "no ) for '(3 + 4 - 5'", e.msg
152
153 try:
154 parser('1 + 2 * foo')
155 assert False, 'expected error'
156 except SyntaxError as e:
157 assert e.msg == "unexpected text: foo", e.msg
158
159
161
163 a = Node('a')
164 b = Node('a')
165 assert a != b
166 assert b != a
167 assert a is not b
168 assert b is not a
169 assert a == a
170 assert b == b
171 assert a is a
172 assert b is b
173
180
181
183
185 a = Node('a')
186 for c in a:
187 assert c == 'a', c
188
189
191
193 return Node('a',
194 Node('b',
195 Node('c',
196 Node('d'),
197 Node('e')),
198 Node('f')),
199 Node('g'),
200 Node('h',
201 Node('i',
202 Node('j'),
203 Node('k')),
204 Node('l')))
205
206 - def order(self, tree, flags):
208
210 tree = self.tree()
211 ordered = self.order(tree, PREORDER)
212 assert ordered == ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], ordered
213 ordered = self.order(tree, POSTORDER)
214 assert ordered == ['d', 'e', 'c', 'f', 'b', 'g', 'j', 'k', 'i', 'l', 'h', 'a'], ordered
215
217 text = str(self.tree())
218 assert text == """Node
219 +- 'a'
220 +- Node
221 | +- 'b'
222 | +- Node
223 | | +- 'c'
224 | | +- Node
225 | | | `- 'd'
226 | | `- Node
227 | | `- 'e'
228 | `- Node
229 | `- 'f'
230 +- Node
231 | `- 'g'
232 `- Node
233 +- 'h'
234 +- Node
235 | +- 'i'
236 | +- Node
237 | | `- 'j'
238 | `- Node
239 | `- 'k'
240 `- Node
241 `- 'l'""", text
242
243
245
248
250 text = str(self.tree())
251 assert text == """Node
252 +- a
253 | `- 'A'
254 `- b
255 `- 'B'""", text
256
257
270