regex-treetop 1.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +19 -0
- data/README.md +164 -0
- data/Rakefile +19 -0
- data/bin/tt +112 -0
- data/doc/contributing_and_planned_features.markdown +103 -0
- data/doc/grammar_composition.markdown +65 -0
- data/doc/index.markdown +90 -0
- data/doc/pitfalls_and_advanced_techniques.markdown +51 -0
- data/doc/semantic_interpretation.markdown +189 -0
- data/doc/site.rb +112 -0
- data/doc/sitegen.rb +65 -0
- data/doc/syntactic_recognition.markdown +100 -0
- data/doc/using_in_ruby.markdown +21 -0
- data/examples/lambda_calculus/arithmetic.rb +551 -0
- data/examples/lambda_calculus/arithmetic.treetop +97 -0
- data/examples/lambda_calculus/arithmetic_node_classes.rb +7 -0
- data/examples/lambda_calculus/arithmetic_test.rb +54 -0
- data/examples/lambda_calculus/lambda_calculus +0 -0
- data/examples/lambda_calculus/lambda_calculus.rb +718 -0
- data/examples/lambda_calculus/lambda_calculus.treetop +132 -0
- data/examples/lambda_calculus/lambda_calculus_node_classes.rb +5 -0
- data/examples/lambda_calculus/lambda_calculus_test.rb +89 -0
- data/examples/lambda_calculus/test_helper.rb +18 -0
- data/lib/treetop.rb +16 -0
- data/lib/treetop/bootstrap_gen_1_metagrammar.rb +45 -0
- data/lib/treetop/compiler.rb +6 -0
- data/lib/treetop/compiler/grammar_compiler.rb +44 -0
- data/lib/treetop/compiler/lexical_address_space.rb +17 -0
- data/lib/treetop/compiler/metagrammar.rb +3392 -0
- data/lib/treetop/compiler/metagrammar.treetop +454 -0
- data/lib/treetop/compiler/node_classes.rb +21 -0
- data/lib/treetop/compiler/node_classes/anything_symbol.rb +18 -0
- data/lib/treetop/compiler/node_classes/atomic_expression.rb +14 -0
- data/lib/treetop/compiler/node_classes/character_class.rb +28 -0
- data/lib/treetop/compiler/node_classes/choice.rb +31 -0
- data/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
- data/lib/treetop/compiler/node_classes/grammar.rb +28 -0
- data/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
- data/lib/treetop/compiler/node_classes/nonterminal.rb +13 -0
- data/lib/treetop/compiler/node_classes/optional.rb +19 -0
- data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/parsing_expression.rb +146 -0
- data/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
- data/lib/treetop/compiler/node_classes/predicate.rb +45 -0
- data/lib/treetop/compiler/node_classes/predicate_block.rb +16 -0
- data/lib/treetop/compiler/node_classes/regex.rb +23 -0
- data/lib/treetop/compiler/node_classes/repetition.rb +55 -0
- data/lib/treetop/compiler/node_classes/sequence.rb +71 -0
- data/lib/treetop/compiler/node_classes/terminal.rb +20 -0
- data/lib/treetop/compiler/node_classes/transient_prefix.rb +9 -0
- data/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
- data/lib/treetop/compiler/ruby_builder.rb +113 -0
- data/lib/treetop/ruby_extensions.rb +2 -0
- data/lib/treetop/ruby_extensions/string.rb +42 -0
- data/lib/treetop/runtime.rb +5 -0
- data/lib/treetop/runtime/compiled_parser.rb +118 -0
- data/lib/treetop/runtime/interval_skip_list.rb +4 -0
- data/lib/treetop/runtime/interval_skip_list/head_node.rb +15 -0
- data/lib/treetop/runtime/interval_skip_list/interval_skip_list.rb +200 -0
- data/lib/treetop/runtime/interval_skip_list/node.rb +164 -0
- data/lib/treetop/runtime/syntax_node.rb +114 -0
- data/lib/treetop/runtime/terminal_parse_failure.rb +16 -0
- data/lib/treetop/runtime/terminal_syntax_node.rb +17 -0
- data/lib/treetop/version.rb +9 -0
- metadata +138 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
grammar Arithmetic
|
2
|
+
rule expression
|
3
|
+
comparative / additive
|
4
|
+
end
|
5
|
+
|
6
|
+
rule comparative
|
7
|
+
operand_1:additive space operator:equality_op space operand_2:additive <BinaryOperation>
|
8
|
+
end
|
9
|
+
|
10
|
+
rule equality_op
|
11
|
+
'==' {
|
12
|
+
def apply(a, b)
|
13
|
+
a == b
|
14
|
+
end
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
rule additive
|
19
|
+
operand_1:multitive
|
20
|
+
space operator:additive_op space
|
21
|
+
operand_2:additive <BinaryOperation>
|
22
|
+
/
|
23
|
+
multitive
|
24
|
+
end
|
25
|
+
|
26
|
+
rule additive_op
|
27
|
+
'+' {
|
28
|
+
def apply(a, b)
|
29
|
+
a + b
|
30
|
+
end
|
31
|
+
}
|
32
|
+
/
|
33
|
+
'-' {
|
34
|
+
def apply(a, b)
|
35
|
+
a - b
|
36
|
+
end
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
rule multitive
|
41
|
+
operand_1:primary
|
42
|
+
space operator:multitive_op space
|
43
|
+
operand_2:multitive <BinaryOperation>
|
44
|
+
/
|
45
|
+
primary
|
46
|
+
end
|
47
|
+
|
48
|
+
rule multitive_op
|
49
|
+
'*' {
|
50
|
+
def apply(a, b)
|
51
|
+
a * b
|
52
|
+
end
|
53
|
+
}
|
54
|
+
/
|
55
|
+
'/' {
|
56
|
+
def apply(a, b)
|
57
|
+
a / b
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
rule primary
|
63
|
+
variable
|
64
|
+
/
|
65
|
+
number
|
66
|
+
/
|
67
|
+
'(' space expression space ')' {
|
68
|
+
def eval(env={})
|
69
|
+
expression.eval(env)
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
rule variable
|
75
|
+
[a-z]+ {
|
76
|
+
def eval(env={})
|
77
|
+
env[name]
|
78
|
+
end
|
79
|
+
|
80
|
+
def name
|
81
|
+
text_value
|
82
|
+
end
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
rule number
|
87
|
+
([1-9] [0-9]* / '0') {
|
88
|
+
def eval(env={})
|
89
|
+
text_value.to_i
|
90
|
+
end
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
rule space
|
95
|
+
' '*
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require File.expand_path("#{dir}/test_helper")
|
3
|
+
|
4
|
+
require File.expand_path("#{dir}/arithmetic_node_classes")
|
5
|
+
Treetop.load File.expand_path("#{dir}/arithmetic")
|
6
|
+
|
7
|
+
class ArithmeticParserTest < Test::Unit::TestCase
|
8
|
+
include ParserTestHelper
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@parser = ArithmeticParser.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_number
|
15
|
+
assert_equal 0, parse('0').eval
|
16
|
+
assert_equal 1, parse('1').eval
|
17
|
+
assert_equal 123, parse('123').eval
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_variable
|
21
|
+
assert_equal 0, parse('x').eval('x' => 0)
|
22
|
+
assert_equal 3, parse('x').eval('x' => 3)
|
23
|
+
assert_equal 10, parse('y').eval('y' => 10)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_addition
|
27
|
+
assert_equal 10, parse('x + 5').eval('x' => 5)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_subtraction
|
31
|
+
assert_equal 0, parse('x - 5').eval('x' => 5)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_multiplication
|
35
|
+
assert_equal 6, parse('x * 2').eval('x' => 3)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_division
|
39
|
+
assert_equal 3, parse('x / 2').eval('x' => 6)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_order_of_operations
|
43
|
+
assert_equal 11, parse('1 + 2 * 3 + 4').eval
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_parentheses
|
47
|
+
assert_equal 25, parse('(5 + x) * (10 - y)').eval('x' => 0, 'y' => 5)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_equality
|
51
|
+
assert parse('4 == 4').eval
|
52
|
+
assert !parse('4 == 3').eval
|
53
|
+
end
|
54
|
+
end
|
File without changes
|
@@ -0,0 +1,718 @@
|
|
1
|
+
module LambdaCalculus
|
2
|
+
include Treetop::Runtime
|
3
|
+
|
4
|
+
def root
|
5
|
+
@root || :program
|
6
|
+
end
|
7
|
+
|
8
|
+
include Arithmetic
|
9
|
+
|
10
|
+
module Program0
|
11
|
+
def space
|
12
|
+
elements[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
def expression
|
16
|
+
elements[2]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Program1
|
21
|
+
def expression
|
22
|
+
elements[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
def more_expressions
|
26
|
+
elements[1]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Program2
|
31
|
+
def eval(env={})
|
32
|
+
env = env.clone
|
33
|
+
last_eval = nil
|
34
|
+
expressions.each do |exp|
|
35
|
+
last_eval = exp.eval(env)
|
36
|
+
end
|
37
|
+
last_eval
|
38
|
+
end
|
39
|
+
|
40
|
+
def expressions
|
41
|
+
[expression] + more_expressions.elements.map {|elt| elt.expression}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def _nt_program
|
46
|
+
start_index = index
|
47
|
+
cached = node_cache[:program][index]
|
48
|
+
if cached
|
49
|
+
@index = cached.interval.end
|
50
|
+
return cached
|
51
|
+
end
|
52
|
+
|
53
|
+
i0, s0 = index, []
|
54
|
+
r1 = _nt_expression
|
55
|
+
s0 << r1
|
56
|
+
if r1.success?
|
57
|
+
s2, i2 = [], index
|
58
|
+
loop do
|
59
|
+
i3, s3 = index, []
|
60
|
+
r4 = parse_terminal(';', SyntaxNode)
|
61
|
+
s3 << r4
|
62
|
+
if r4.success?
|
63
|
+
r5 = _nt_space
|
64
|
+
s3 << r5
|
65
|
+
if r5.success?
|
66
|
+
r6 = _nt_expression
|
67
|
+
s3 << r6
|
68
|
+
end
|
69
|
+
end
|
70
|
+
if s3.last.success?
|
71
|
+
r3 = (SyntaxNode).new(input, i3...index, s3)
|
72
|
+
r3.extend(Program0)
|
73
|
+
else
|
74
|
+
self.index = i3
|
75
|
+
r3 = ParseFailure.new(input, i3)
|
76
|
+
end
|
77
|
+
if r3.success?
|
78
|
+
s2 << r3
|
79
|
+
else
|
80
|
+
break
|
81
|
+
end
|
82
|
+
end
|
83
|
+
r2 = SyntaxNode.new(input, i2...index, s2)
|
84
|
+
s0 << r2
|
85
|
+
end
|
86
|
+
if s0.last.success?
|
87
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
88
|
+
r0.extend(Program1)
|
89
|
+
r0.extend(Program2)
|
90
|
+
else
|
91
|
+
self.index = i0
|
92
|
+
r0 = ParseFailure.new(input, i0)
|
93
|
+
end
|
94
|
+
|
95
|
+
node_cache[:program][start_index] = r0
|
96
|
+
|
97
|
+
return r0
|
98
|
+
end
|
99
|
+
|
100
|
+
def _nt_expression
|
101
|
+
start_index = index
|
102
|
+
cached = node_cache[:expression][index]
|
103
|
+
if cached
|
104
|
+
@index = cached.interval.end
|
105
|
+
return cached
|
106
|
+
end
|
107
|
+
|
108
|
+
i0 = index
|
109
|
+
r1 = _nt_definition
|
110
|
+
if r1.success?
|
111
|
+
r0 = r1
|
112
|
+
else
|
113
|
+
r2 = _nt_conditional
|
114
|
+
if r2.success?
|
115
|
+
r0 = r2
|
116
|
+
else
|
117
|
+
r3 = _nt_application
|
118
|
+
if r3.success?
|
119
|
+
r0 = r3
|
120
|
+
else
|
121
|
+
r4 = _nt_function
|
122
|
+
if r4.success?
|
123
|
+
r0 = r4
|
124
|
+
else
|
125
|
+
r5 = super
|
126
|
+
if r5.success?
|
127
|
+
r0 = r5
|
128
|
+
else
|
129
|
+
self.index = i0
|
130
|
+
r0 = ParseFailure.new(input, i0)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
node_cache[:expression][start_index] = r0
|
138
|
+
|
139
|
+
return r0
|
140
|
+
end
|
141
|
+
|
142
|
+
module Definition0
|
143
|
+
def space
|
144
|
+
elements[1]
|
145
|
+
end
|
146
|
+
|
147
|
+
def variable
|
148
|
+
elements[2]
|
149
|
+
end
|
150
|
+
|
151
|
+
def space
|
152
|
+
elements[3]
|
153
|
+
end
|
154
|
+
|
155
|
+
def expression
|
156
|
+
elements[4]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module Definition1
|
161
|
+
def eval(env)
|
162
|
+
env[variable.name] = expression.eval(env)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def _nt_definition
|
167
|
+
start_index = index
|
168
|
+
cached = node_cache[:definition][index]
|
169
|
+
if cached
|
170
|
+
@index = cached.interval.end
|
171
|
+
return cached
|
172
|
+
end
|
173
|
+
|
174
|
+
i0, s0 = index, []
|
175
|
+
r1 = parse_terminal('def', SyntaxNode)
|
176
|
+
s0 << r1
|
177
|
+
if r1.success?
|
178
|
+
r2 = _nt_space
|
179
|
+
s0 << r2
|
180
|
+
if r2.success?
|
181
|
+
r3 = _nt_variable
|
182
|
+
s0 << r3
|
183
|
+
if r3.success?
|
184
|
+
r4 = _nt_space
|
185
|
+
s0 << r4
|
186
|
+
if r4.success?
|
187
|
+
r5 = _nt_expression
|
188
|
+
s0 << r5
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
if s0.last.success?
|
194
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
195
|
+
r0.extend(Definition0)
|
196
|
+
r0.extend(Definition1)
|
197
|
+
else
|
198
|
+
self.index = i0
|
199
|
+
r0 = ParseFailure.new(input, i0)
|
200
|
+
end
|
201
|
+
|
202
|
+
node_cache[:definition][start_index] = r0
|
203
|
+
|
204
|
+
return r0
|
205
|
+
end
|
206
|
+
|
207
|
+
module Conditional0
|
208
|
+
def space
|
209
|
+
elements[1]
|
210
|
+
end
|
211
|
+
|
212
|
+
def space
|
213
|
+
elements[3]
|
214
|
+
end
|
215
|
+
|
216
|
+
def condition
|
217
|
+
elements[4]
|
218
|
+
end
|
219
|
+
|
220
|
+
def space
|
221
|
+
elements[5]
|
222
|
+
end
|
223
|
+
|
224
|
+
def space
|
225
|
+
elements[7]
|
226
|
+
end
|
227
|
+
|
228
|
+
def true_case
|
229
|
+
elements[8]
|
230
|
+
end
|
231
|
+
|
232
|
+
def space
|
233
|
+
elements[9]
|
234
|
+
end
|
235
|
+
|
236
|
+
def space
|
237
|
+
elements[11]
|
238
|
+
end
|
239
|
+
|
240
|
+
def false_case
|
241
|
+
elements[12]
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
module Conditional1
|
246
|
+
def eval(env)
|
247
|
+
if condition.eval(env)
|
248
|
+
true_case.eval(env)
|
249
|
+
else
|
250
|
+
false_case.eval(env)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def _nt_conditional
|
256
|
+
start_index = index
|
257
|
+
cached = node_cache[:conditional][index]
|
258
|
+
if cached
|
259
|
+
@index = cached.interval.end
|
260
|
+
return cached
|
261
|
+
end
|
262
|
+
|
263
|
+
i0, s0 = index, []
|
264
|
+
r1 = parse_terminal('if', SyntaxNode)
|
265
|
+
s0 << r1
|
266
|
+
if r1.success?
|
267
|
+
r2 = _nt_space
|
268
|
+
s0 << r2
|
269
|
+
if r2.success?
|
270
|
+
r3 = parse_terminal('(', SyntaxNode)
|
271
|
+
s0 << r3
|
272
|
+
if r3.success?
|
273
|
+
r4 = _nt_space
|
274
|
+
s0 << r4
|
275
|
+
if r4.success?
|
276
|
+
r5 = _nt_expression
|
277
|
+
s0 << r5
|
278
|
+
if r5.success?
|
279
|
+
r6 = _nt_space
|
280
|
+
s0 << r6
|
281
|
+
if r6.success?
|
282
|
+
r7 = parse_terminal(')', SyntaxNode)
|
283
|
+
s0 << r7
|
284
|
+
if r7.success?
|
285
|
+
r8 = _nt_space
|
286
|
+
s0 << r8
|
287
|
+
if r8.success?
|
288
|
+
r9 = _nt_expression
|
289
|
+
s0 << r9
|
290
|
+
if r9.success?
|
291
|
+
r10 = _nt_space
|
292
|
+
s0 << r10
|
293
|
+
if r10.success?
|
294
|
+
r11 = parse_terminal('else', SyntaxNode)
|
295
|
+
s0 << r11
|
296
|
+
if r11.success?
|
297
|
+
r12 = _nt_space
|
298
|
+
s0 << r12
|
299
|
+
if r12.success?
|
300
|
+
r13 = _nt_expression
|
301
|
+
s0 << r13
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
if s0.last.success?
|
315
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
316
|
+
r0.extend(Conditional0)
|
317
|
+
r0.extend(Conditional1)
|
318
|
+
else
|
319
|
+
self.index = i0
|
320
|
+
r0 = ParseFailure.new(input, i0)
|
321
|
+
end
|
322
|
+
|
323
|
+
node_cache[:conditional][start_index] = r0
|
324
|
+
|
325
|
+
return r0
|
326
|
+
end
|
327
|
+
|
328
|
+
def _nt_primary
|
329
|
+
start_index = index
|
330
|
+
cached = node_cache[:primary][index]
|
331
|
+
if cached
|
332
|
+
@index = cached.interval.end
|
333
|
+
return cached
|
334
|
+
end
|
335
|
+
|
336
|
+
i0 = index
|
337
|
+
r1 = _nt_application
|
338
|
+
if r1.success?
|
339
|
+
r0 = r1
|
340
|
+
else
|
341
|
+
r2 = super
|
342
|
+
if r2.success?
|
343
|
+
r0 = r2
|
344
|
+
else
|
345
|
+
self.index = i0
|
346
|
+
r0 = ParseFailure.new(input, i0)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
node_cache[:primary][start_index] = r0
|
351
|
+
|
352
|
+
return r0
|
353
|
+
end
|
354
|
+
|
355
|
+
module Application0
|
356
|
+
def operator
|
357
|
+
elements[0]
|
358
|
+
end
|
359
|
+
|
360
|
+
def space
|
361
|
+
elements[1]
|
362
|
+
end
|
363
|
+
|
364
|
+
def expression
|
365
|
+
elements[2]
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
module Application1
|
370
|
+
def eval(env={})
|
371
|
+
left_associative_apply(operator.eval(env), env)
|
372
|
+
end
|
373
|
+
|
374
|
+
def left_associative_apply(operator, env)
|
375
|
+
if expression.instance_of?(Application)
|
376
|
+
expression.left_associative_apply(operator.apply(expression.operator.eval(env)), env)
|
377
|
+
else
|
378
|
+
operator.apply(expression.eval(env))
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def to_s(env={})
|
383
|
+
operator.to_s(env) + ' ' + expression.to_s(env)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def _nt_application
|
388
|
+
start_index = index
|
389
|
+
cached = node_cache[:application][index]
|
390
|
+
if cached
|
391
|
+
@index = cached.interval.end
|
392
|
+
return cached
|
393
|
+
end
|
394
|
+
|
395
|
+
i0, s0 = index, []
|
396
|
+
r1 = _nt_operator
|
397
|
+
s0 << r1
|
398
|
+
if r1.success?
|
399
|
+
r2 = _nt_space
|
400
|
+
s0 << r2
|
401
|
+
if r2.success?
|
402
|
+
r3 = _nt_expression
|
403
|
+
s0 << r3
|
404
|
+
end
|
405
|
+
end
|
406
|
+
if s0.last.success?
|
407
|
+
r0 = (Application).new(input, i0...index, s0)
|
408
|
+
r0.extend(Application0)
|
409
|
+
r0.extend(Application1)
|
410
|
+
else
|
411
|
+
self.index = i0
|
412
|
+
r0 = ParseFailure.new(input, i0)
|
413
|
+
end
|
414
|
+
|
415
|
+
node_cache[:application][start_index] = r0
|
416
|
+
|
417
|
+
return r0
|
418
|
+
end
|
419
|
+
|
420
|
+
def _nt_operator
|
421
|
+
start_index = index
|
422
|
+
cached = node_cache[:operator][index]
|
423
|
+
if cached
|
424
|
+
@index = cached.interval.end
|
425
|
+
return cached
|
426
|
+
end
|
427
|
+
|
428
|
+
i0 = index
|
429
|
+
r1 = _nt_function
|
430
|
+
if r1.success?
|
431
|
+
r0 = r1
|
432
|
+
else
|
433
|
+
r2 = _nt_variable
|
434
|
+
if r2.success?
|
435
|
+
r0 = r2
|
436
|
+
else
|
437
|
+
self.index = i0
|
438
|
+
r0 = ParseFailure.new(input, i0)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
node_cache[:operator][start_index] = r0
|
443
|
+
|
444
|
+
return r0
|
445
|
+
end
|
446
|
+
|
447
|
+
def _nt_non_application
|
448
|
+
start_index = index
|
449
|
+
cached = node_cache[:non_application][index]
|
450
|
+
if cached
|
451
|
+
@index = cached.interval.end
|
452
|
+
return cached
|
453
|
+
end
|
454
|
+
|
455
|
+
i0 = index
|
456
|
+
r1 = _nt_function
|
457
|
+
if r1.success?
|
458
|
+
r0 = r1
|
459
|
+
else
|
460
|
+
r2 = _nt_variable
|
461
|
+
if r2.success?
|
462
|
+
r0 = r2
|
463
|
+
else
|
464
|
+
self.index = i0
|
465
|
+
r0 = ParseFailure.new(input, i0)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
node_cache[:non_application][start_index] = r0
|
470
|
+
|
471
|
+
return r0
|
472
|
+
end
|
473
|
+
|
474
|
+
module Function0
|
475
|
+
def param
|
476
|
+
elements[1]
|
477
|
+
end
|
478
|
+
|
479
|
+
def body
|
480
|
+
elements[3]
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
module Function1
|
486
|
+
class Closure
|
487
|
+
attr_reader :env, :function
|
488
|
+
|
489
|
+
def initialize(function, env)
|
490
|
+
@function = function
|
491
|
+
@env = env
|
492
|
+
end
|
493
|
+
|
494
|
+
def apply(arg)
|
495
|
+
function.body.eval(function.param.bind(arg, env))
|
496
|
+
end
|
497
|
+
|
498
|
+
def to_s(other_env={})
|
499
|
+
"\\#{function.param.to_s}(#{function.body.to_s(other_env.merge(env))})"
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
def eval(env={})
|
504
|
+
Closure.new(self, env)
|
505
|
+
end
|
506
|
+
|
507
|
+
def to_s(env={})
|
508
|
+
eval(env).to_s
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
def _nt_function
|
513
|
+
start_index = index
|
514
|
+
cached = node_cache[:function][index]
|
515
|
+
if cached
|
516
|
+
@index = cached.interval.end
|
517
|
+
return cached
|
518
|
+
end
|
519
|
+
|
520
|
+
i0, s0 = index, []
|
521
|
+
r1 = parse_terminal('\\', SyntaxNode)
|
522
|
+
s0 << r1
|
523
|
+
if r1.success?
|
524
|
+
r2 = _nt_variable
|
525
|
+
s0 << r2
|
526
|
+
if r2.success?
|
527
|
+
r3 = parse_terminal('(', SyntaxNode)
|
528
|
+
s0 << r3
|
529
|
+
if r3.success?
|
530
|
+
r4 = _nt_expression
|
531
|
+
s0 << r4
|
532
|
+
if r4.success?
|
533
|
+
r5 = parse_terminal(')', SyntaxNode)
|
534
|
+
s0 << r5
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
if s0.last.success?
|
540
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
541
|
+
r0.extend(Function0)
|
542
|
+
r0.extend(Function1)
|
543
|
+
else
|
544
|
+
self.index = i0
|
545
|
+
r0 = ParseFailure.new(input, i0)
|
546
|
+
end
|
547
|
+
|
548
|
+
node_cache[:function][start_index] = r0
|
549
|
+
|
550
|
+
return r0
|
551
|
+
end
|
552
|
+
|
553
|
+
module Variable0
|
554
|
+
def bind(value, env)
|
555
|
+
env.merge(name => value)
|
556
|
+
end
|
557
|
+
|
558
|
+
def to_s(env={})
|
559
|
+
env.has_key?(name) ? env[name].to_s : name
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
module Variable1
|
564
|
+
end
|
565
|
+
|
566
|
+
def _nt_variable
|
567
|
+
start_index = index
|
568
|
+
cached = node_cache[:variable][index]
|
569
|
+
if cached
|
570
|
+
@index = cached.interval.end
|
571
|
+
return cached
|
572
|
+
end
|
573
|
+
|
574
|
+
i0, s0 = index, []
|
575
|
+
i1 = index
|
576
|
+
r2 = _nt_keyword
|
577
|
+
if r2.success?
|
578
|
+
r1 = ParseFailure.new(input, i1)
|
579
|
+
else
|
580
|
+
self.index = i1
|
581
|
+
r1 = SyntaxNode.new(input, index...index)
|
582
|
+
end
|
583
|
+
s0 << r1
|
584
|
+
if r1.success?
|
585
|
+
r3 = super
|
586
|
+
r3.extend(Variable0)
|
587
|
+
s0 << r3
|
588
|
+
end
|
589
|
+
if s0.last.success?
|
590
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
591
|
+
r0.extend(Variable1)
|
592
|
+
else
|
593
|
+
self.index = i0
|
594
|
+
r0 = ParseFailure.new(input, i0)
|
595
|
+
end
|
596
|
+
|
597
|
+
node_cache[:variable][start_index] = r0
|
598
|
+
|
599
|
+
return r0
|
600
|
+
end
|
601
|
+
|
602
|
+
module Keyword0
|
603
|
+
end
|
604
|
+
|
605
|
+
def _nt_keyword
|
606
|
+
start_index = index
|
607
|
+
cached = node_cache[:keyword][index]
|
608
|
+
if cached
|
609
|
+
@index = cached.interval.end
|
610
|
+
return cached
|
611
|
+
end
|
612
|
+
|
613
|
+
i0, s0 = index, []
|
614
|
+
i1 = index
|
615
|
+
r2 = parse_terminal('if', SyntaxNode)
|
616
|
+
if r2.success?
|
617
|
+
r1 = r2
|
618
|
+
else
|
619
|
+
r3 = parse_terminal('else', SyntaxNode)
|
620
|
+
if r3.success?
|
621
|
+
r1 = r3
|
622
|
+
else
|
623
|
+
self.index = i1
|
624
|
+
r1 = ParseFailure.new(input, i1)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
s0 << r1
|
628
|
+
if r1.success?
|
629
|
+
i4 = index
|
630
|
+
r5 = _nt_non_space_char
|
631
|
+
if r5.success?
|
632
|
+
r4 = ParseFailure.new(input, i4)
|
633
|
+
else
|
634
|
+
self.index = i4
|
635
|
+
r4 = SyntaxNode.new(input, index...index)
|
636
|
+
end
|
637
|
+
s0 << r4
|
638
|
+
end
|
639
|
+
if s0.last.success?
|
640
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
641
|
+
r0.extend(Keyword0)
|
642
|
+
else
|
643
|
+
self.index = i0
|
644
|
+
r0 = ParseFailure.new(input, i0)
|
645
|
+
end
|
646
|
+
|
647
|
+
node_cache[:keyword][start_index] = r0
|
648
|
+
|
649
|
+
return r0
|
650
|
+
end
|
651
|
+
|
652
|
+
module NonSpaceChar0
|
653
|
+
end
|
654
|
+
|
655
|
+
def _nt_non_space_char
|
656
|
+
start_index = index
|
657
|
+
cached = node_cache[:non_space_char][index]
|
658
|
+
if cached
|
659
|
+
@index = cached.interval.end
|
660
|
+
return cached
|
661
|
+
end
|
662
|
+
|
663
|
+
i0, s0 = index, []
|
664
|
+
i1 = index
|
665
|
+
r2 = parse_char_class(/[ \n]/, ' \n', SyntaxNode)
|
666
|
+
if r2.success?
|
667
|
+
r1 = ParseFailure.new(input, i1)
|
668
|
+
else
|
669
|
+
self.index = i1
|
670
|
+
r1 = SyntaxNode.new(input, index...index)
|
671
|
+
end
|
672
|
+
s0 << r1
|
673
|
+
if r1.success?
|
674
|
+
r3 = parse_anything(SyntaxNode)
|
675
|
+
s0 << r3
|
676
|
+
end
|
677
|
+
if s0.last.success?
|
678
|
+
r0 = (SyntaxNode).new(input, i0...index, s0)
|
679
|
+
r0.extend(NonSpaceChar0)
|
680
|
+
else
|
681
|
+
self.index = i0
|
682
|
+
r0 = ParseFailure.new(input, i0)
|
683
|
+
end
|
684
|
+
|
685
|
+
node_cache[:non_space_char][start_index] = r0
|
686
|
+
|
687
|
+
return r0
|
688
|
+
end
|
689
|
+
|
690
|
+
def _nt_space
|
691
|
+
start_index = index
|
692
|
+
cached = node_cache[:space][index]
|
693
|
+
if cached
|
694
|
+
@index = cached.interval.end
|
695
|
+
return cached
|
696
|
+
end
|
697
|
+
|
698
|
+
s0, i0 = [], index
|
699
|
+
loop do
|
700
|
+
r1 = parse_char_class(/[ \n]/, ' \n', SyntaxNode)
|
701
|
+
if r1.success?
|
702
|
+
s0 << r1
|
703
|
+
else
|
704
|
+
break
|
705
|
+
end
|
706
|
+
end
|
707
|
+
r0 = SyntaxNode.new(input, i0...index, s0)
|
708
|
+
|
709
|
+
node_cache[:space][start_index] = r0
|
710
|
+
|
711
|
+
return r0
|
712
|
+
end
|
713
|
+
|
714
|
+
end
|
715
|
+
|
716
|
+
class LambdaCalculusParser < Treetop::Runtime::CompiledParser
|
717
|
+
include LambdaCalculus
|
718
|
+
end
|