1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 '''
20 An example that avoids using tokens (in a sense) with the line aware
21 parsing.
22 '''
23
24
25 from unittest import TestCase
26
27 from lepl import *
28
29
30 -class TextTest(TestCase):
31
32 - def parser(self, regexp):
33 '''
34 Construct a parser that uses "offside rule" parsing, but which
35 avoids using tokens in the grammar.
36 '''
37
38
39 Text = Token(regexp)
40
41 def TLine(contents):
42 '''
43 A version of BLine() that takes text-based matchers.
44 '''
45 return BLine(Text(contents))
46
47
48
49
50
51 with Separator(~Space()[:]):
52 name = Word()
53 args = name[:, ',']
54 fundef = 'def' & name & '(' & args & ')' & ':'
55
56 expression = Literal('pass')
57
58
59 statement = Delayed()
60 simple = TLine(expression)
61 empty = TLine(Empty())
62 block = TLine(fundef) & Block(statement[:])
63 statement += (simple | empty | block) > list
64
65 return statement[:].string_parser(
66 LineAwareConfiguration(block_policy=2))
67
68 - def do_parse(self, parser):
69 return parser('''pass
70 def foo():
71 pass
72 def bar():
73 pass
74 ''')
75
76 - def test_plus(self):
77 parser = self.parser('[^\n]+')
78 result = self.do_parse(parser)
79 assert result == [['pass'],
80 ['def', 'foo', '(', ')', ':',
81 ['pass'],
82 ['def', 'bar', '(', ')', ':',
83 ['pass']]]], result
84
85 - def test_star(self):
86
87 parser = self.parser('[^\n]*')
88 try:
89 self.do_parse(parser)
90 assert False, 'Expected error'
91 except RuntimeLexerError:
92 pass
93