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 An example that avoids using tokens with the line aware parsing (you'd have
32 to be crazy to want to do this, but it's possible).
33 '''
34
35
36 from unittest import TestCase
37
38
39 from lepl import *
40
41
42 -class TextTest(TestCase):
43
44 - def parser(self, regexp):
45 '''
46 Construct a parser that uses "offside rule" parsing, but which
47 avoids using tokens in the grammar.
48 '''
49
50
51 Text = Token(regexp)
52
53 def TLine(contents):
54 '''
55 A version of Line() that takes text-based matchers.
56 '''
57 return Line(Text(contents))
58
59
60
61
62
63 with Separator(~Space()[:]):
64 name = Word()
65 args = name[:, ',']
66 fundef = 'def' & name & '(' & args & ')' & ':'
67
68 expression = Literal('pass')
69
70
71 statement = Delayed()
72 simple = TLine(expression)
73 empty = TLine(Empty())
74 block = TLine(fundef) & Block(statement[:])
75 statement += (simple | empty | block) > list
76 program = statement[:]
77
78 program.config.lines(block_policy=2)
79 return program.get_parse_string()
80
81 - def do_parse(self, parser):
82 return parser('''pass
83 def foo():
84 pass
85 def bar():
86 pass
87 ''')
88
89 - def test_plus(self):
90 parser = self.parser('[^\n]+')
91 result = self.do_parse(parser)
92 assert result == [['pass'],
93 ['def', 'foo', '(', ')', ':',
94 ['pass'],
95 ['def', 'bar', '(', ')', ':',
96 ['pass']]]], result
97
98 - def test_star(self):
99 '''
100 I have no idea why this fails, but this test was here before I forgot
101 so I assume it is correct behaviour!
102
103 (I think matching the empty string for a token is probably not a good
104 idea)
105 '''
106
107 parser = self.parser('[^\n]*')
108 try:
109 self.do_parse(parser)
110 assert False, 'Expected error'
111
112
113 except FullFirstMatchException:
114 pass
115