treetop 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README +1 -1
  2. data/Rakefile +3 -2
  3. data/doc/contributing_and_planned_features.markdown +1 -1
  4. data/doc/using_in_ruby.markdown +2 -2
  5. data/examples/lambda_calculus/arithmetic.rb +551 -0
  6. data/examples/lambda_calculus/arithmetic_test.rb +1 -1
  7. data/examples/lambda_calculus/lambda_calculus.rb +39 -72
  8. data/examples/lambda_calculus/lambda_calculus_test.rb +2 -2
  9. data/examples/lambda_calculus/test_helper.rb +3 -3
  10. data/lib/treetop.rb +3 -0
  11. data/lib/treetop/bootstrap_gen_1_metagrammar.rb +22 -14
  12. data/lib/treetop/compiler.rb +1 -2
  13. data/lib/treetop/compiler/grammar_compiler.rb +12 -5
  14. data/lib/treetop/compiler/metagrammar.rb +931 -558
  15. data/lib/treetop/compiler/metagrammar.treetop +26 -6
  16. data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -2
  17. data/lib/treetop/compiler/node_classes/atomic_expression.rb +4 -0
  18. data/lib/treetop/compiler/node_classes/character_class.rb +10 -1
  19. data/lib/treetop/compiler/node_classes/choice.rb +2 -4
  20. data/lib/treetop/compiler/node_classes/parsing_expression.rb +8 -17
  21. data/lib/treetop/compiler/node_classes/parsing_rule.rb +3 -3
  22. data/lib/treetop/compiler/node_classes/predicate.rb +1 -1
  23. data/lib/treetop/compiler/node_classes/repetition.rb +3 -4
  24. data/lib/treetop/compiler/node_classes/sequence.rb +4 -4
  25. data/lib/treetop/compiler/node_classes/terminal.rb +11 -1
  26. data/lib/treetop/compiler/ruby_builder.rb +2 -2
  27. data/lib/treetop/ruby_extensions.rb +1 -1
  28. data/lib/treetop/runtime.rb +0 -3
  29. data/lib/treetop/runtime/compiled_parser.rb +42 -34
  30. data/lib/treetop/runtime/node_cache.rb +1 -1
  31. data/lib/treetop/runtime/syntax_node.rb +51 -32
  32. data/lib/treetop/runtime/terminal_parse_failure.rb +7 -24
  33. data/lib/treetop/runtime/terminal_syntax_node.rb +7 -2
  34. metadata +12 -7
  35. data/examples/TALK +0 -33
  36. data/lib/treetop/compiler/load_grammar.rb +0 -7
  37. data/lib/treetop/compiler/metagrammar. +0 -0
  38. data/lib/treetop/runtime/parse_failure.rb +0 -32
  39. data/lib/treetop/runtime/parse_result.rb +0 -30
data/README CHANGED
@@ -26,7 +26,7 @@ The first rule becomes the *root* of the grammar, causing its expression to be m
26
26
  # use_grammar.rb
27
27
  require 'rubygems'
28
28
  require 'treetop'
29
- load_grammar 'my_grammar'
29
+ Treetop.load 'my_grammar'
30
30
 
31
31
  parser = MyGrammarParser.new
32
32
  puts parser.parse('hello chomsky').success? # => true
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ end
15
15
 
16
16
  gemspec = Gem::Specification.new do |s|
17
17
  s.name = "treetop"
18
- s.version = "1.1.4"
18
+ s.version = "1.2.0"
19
19
  s.author = "Nathan Sobo"
20
20
  s.email = "nathansobo@gmail.com"
21
21
  s.homepage = "http://functionalform.blogspot.com"
@@ -28,8 +28,9 @@ gemspec = Gem::Specification.new do |s|
28
28
  s.autorequire = "treetop"
29
29
  s.has_rdoc = false
30
30
  s.add_dependency "facets", ">=2.0.2"
31
+ s.add_dependency "polyglot"
31
32
  end
32
33
 
33
34
  Rake::GemPackageTask.new(gemspec) do |pkg|
34
35
  pkg.need_tar = true
35
- end
36
+ end
@@ -15,7 +15,7 @@ Due to shortcomings in Ruby's semantics that scope constant definitions in a blo
15
15
  ##Small Stuff
16
16
  * Migrate the tests back to RSpec.
17
17
  * Improve the `tt` command line tool to allow `.treetop` extensions to be elided in its arguments.
18
- * Generate and load temp files with `load_grammar` rather than evaluating strings to improve stack trace readability.
18
+ * Generate and load temp files with `Treetop.load` rather than evaluating strings to improve stack trace readability.
19
19
  * Allow `do/end` style blocks as well as curly brace blocks. This was originally omitted because I thought it would be confusing. It probably isn't.
20
20
  * Allow the root of a grammar to be dynamically set for testing purposes.
21
21
 
@@ -6,12 +6,12 @@ You can `.treetop` files into Ruby source code with the `tt` command line script
6
6
  tt foo.treetop -o foogrammar.rb
7
7
 
8
8
  ##Loading A Grammar Directly
9
- The `load_grammar` method takes the path to a `.treetop` file (where the extension is optional), and automatically compiles and evaluates the Ruby source. If you are getting errors in methods you define on the syntax tree, try using the command line compiler for better stack trace feedback. The need to do this is being addressed.
9
+ The `Treetop.load` method takes the path to a `.treetop` file (where the extension is optional), and automatically compiles and evaluates the Ruby source. If you are getting errors in methods you define on the syntax tree, try using the command line compiler for better stack trace feedback. The need to do this is being addressed.
10
10
 
11
11
  ##Instantiating and Using Parsers
12
12
  If a grammar by the name of `Foo` is defined, the compiled Ruby source will define a `FooParser` class. To parse input, create an instance and call its `parse` method with a string.
13
13
 
14
- load_grammar "arithmetic"
14
+ Treetop.load "arithmetic"
15
15
 
16
16
  parser = ArithmeticParser.new
17
17
  puts parser.parse('1+1').success?
@@ -0,0 +1,551 @@
1
+ module Arithmetic
2
+ include Treetop::Runtime
3
+
4
+ def root
5
+ @root || :expression
6
+ end
7
+
8
+ def _nt_expression
9
+ start_index = index
10
+ cached = node_cache[:expression][index]
11
+ if cached
12
+ @index = cached.interval.end
13
+ return cached
14
+ end
15
+
16
+ i0 = index
17
+ r1 = _nt_comparative
18
+ if r1.success?
19
+ r0 = r1
20
+ else
21
+ r2 = _nt_additive
22
+ if r2.success?
23
+ r0 = r2
24
+ else
25
+ self.index = i0
26
+ r0 = ParseFailure.new(input, i0)
27
+ end
28
+ end
29
+
30
+ node_cache[:expression][start_index] = r0
31
+
32
+ return r0
33
+ end
34
+
35
+ module Comparative0
36
+ def operand_1
37
+ elements[0]
38
+ end
39
+
40
+ def space
41
+ elements[1]
42
+ end
43
+
44
+ def operator
45
+ elements[2]
46
+ end
47
+
48
+ def space
49
+ elements[3]
50
+ end
51
+
52
+ def operand_2
53
+ elements[4]
54
+ end
55
+ end
56
+
57
+ def _nt_comparative
58
+ start_index = index
59
+ cached = node_cache[:comparative][index]
60
+ if cached
61
+ @index = cached.interval.end
62
+ return cached
63
+ end
64
+
65
+ i0, s0 = index, []
66
+ r1 = _nt_additive
67
+ s0 << r1
68
+ if r1.success?
69
+ r2 = _nt_space
70
+ s0 << r2
71
+ if r2.success?
72
+ r3 = _nt_equality_op
73
+ s0 << r3
74
+ if r3.success?
75
+ r4 = _nt_space
76
+ s0 << r4
77
+ if r4.success?
78
+ r5 = _nt_additive
79
+ s0 << r5
80
+ end
81
+ end
82
+ end
83
+ end
84
+ if s0.last.success?
85
+ r0 = (BinaryOperation).new(input, i0...index, s0)
86
+ r0.extend(Comparative0)
87
+ else
88
+ self.index = i0
89
+ r0 = ParseFailure.new(input, i0)
90
+ end
91
+
92
+ node_cache[:comparative][start_index] = r0
93
+
94
+ return r0
95
+ end
96
+
97
+ module EqualityOp0
98
+ def apply(a, b)
99
+ a == b
100
+ end
101
+ end
102
+
103
+ def _nt_equality_op
104
+ start_index = index
105
+ cached = node_cache[:equality_op][index]
106
+ if cached
107
+ @index = cached.interval.end
108
+ return cached
109
+ end
110
+
111
+ r0 = parse_terminal('==', SyntaxNode, EqualityOp0)
112
+
113
+ node_cache[:equality_op][start_index] = r0
114
+
115
+ return r0
116
+ end
117
+
118
+ module Additive0
119
+ def operand_1
120
+ elements[0]
121
+ end
122
+
123
+ def space
124
+ elements[1]
125
+ end
126
+
127
+ def operator
128
+ elements[2]
129
+ end
130
+
131
+ def space
132
+ elements[3]
133
+ end
134
+
135
+ def operand_2
136
+ elements[4]
137
+ end
138
+ end
139
+
140
+ def _nt_additive
141
+ start_index = index
142
+ cached = node_cache[:additive][index]
143
+ if cached
144
+ @index = cached.interval.end
145
+ return cached
146
+ end
147
+
148
+ i0 = index
149
+ i1, s1 = index, []
150
+ r2 = _nt_multitive
151
+ s1 << r2
152
+ if r2.success?
153
+ r3 = _nt_space
154
+ s1 << r3
155
+ if r3.success?
156
+ r4 = _nt_additive_op
157
+ s1 << r4
158
+ if r4.success?
159
+ r5 = _nt_space
160
+ s1 << r5
161
+ if r5.success?
162
+ r6 = _nt_additive
163
+ s1 << r6
164
+ end
165
+ end
166
+ end
167
+ end
168
+ if s1.last.success?
169
+ r1 = (BinaryOperation).new(input, i1...index, s1)
170
+ r1.extend(Additive0)
171
+ else
172
+ self.index = i1
173
+ r1 = ParseFailure.new(input, i1)
174
+ end
175
+ if r1.success?
176
+ r0 = r1
177
+ else
178
+ r7 = _nt_multitive
179
+ if r7.success?
180
+ r0 = r7
181
+ else
182
+ self.index = i0
183
+ r0 = ParseFailure.new(input, i0)
184
+ end
185
+ end
186
+
187
+ node_cache[:additive][start_index] = r0
188
+
189
+ return r0
190
+ end
191
+
192
+ module AdditiveOp0
193
+ def apply(a, b)
194
+ a + b
195
+ end
196
+ end
197
+
198
+ module AdditiveOp1
199
+ def apply(a, b)
200
+ a - b
201
+ end
202
+ end
203
+
204
+ def _nt_additive_op
205
+ start_index = index
206
+ cached = node_cache[:additive_op][index]
207
+ if cached
208
+ @index = cached.interval.end
209
+ return cached
210
+ end
211
+
212
+ i0 = index
213
+ r1 = parse_terminal('+', SyntaxNode, AdditiveOp0)
214
+ if r1.success?
215
+ r0 = r1
216
+ else
217
+ r2 = parse_terminal('-', SyntaxNode, AdditiveOp1)
218
+ if r2.success?
219
+ r0 = r2
220
+ else
221
+ self.index = i0
222
+ r0 = ParseFailure.new(input, i0)
223
+ end
224
+ end
225
+
226
+ node_cache[:additive_op][start_index] = r0
227
+
228
+ return r0
229
+ end
230
+
231
+ module Multitive0
232
+ def operand_1
233
+ elements[0]
234
+ end
235
+
236
+ def space
237
+ elements[1]
238
+ end
239
+
240
+ def operator
241
+ elements[2]
242
+ end
243
+
244
+ def space
245
+ elements[3]
246
+ end
247
+
248
+ def operand_2
249
+ elements[4]
250
+ end
251
+ end
252
+
253
+ def _nt_multitive
254
+ start_index = index
255
+ cached = node_cache[:multitive][index]
256
+ if cached
257
+ @index = cached.interval.end
258
+ return cached
259
+ end
260
+
261
+ i0 = index
262
+ i1, s1 = index, []
263
+ r2 = _nt_primary
264
+ s1 << r2
265
+ if r2.success?
266
+ r3 = _nt_space
267
+ s1 << r3
268
+ if r3.success?
269
+ r4 = _nt_multitive_op
270
+ s1 << r4
271
+ if r4.success?
272
+ r5 = _nt_space
273
+ s1 << r5
274
+ if r5.success?
275
+ r6 = _nt_multitive
276
+ s1 << r6
277
+ end
278
+ end
279
+ end
280
+ end
281
+ if s1.last.success?
282
+ r1 = (BinaryOperation).new(input, i1...index, s1)
283
+ r1.extend(Multitive0)
284
+ else
285
+ self.index = i1
286
+ r1 = ParseFailure.new(input, i1)
287
+ end
288
+ if r1.success?
289
+ r0 = r1
290
+ else
291
+ r7 = _nt_primary
292
+ if r7.success?
293
+ r0 = r7
294
+ else
295
+ self.index = i0
296
+ r0 = ParseFailure.new(input, i0)
297
+ end
298
+ end
299
+
300
+ node_cache[:multitive][start_index] = r0
301
+
302
+ return r0
303
+ end
304
+
305
+ module MultitiveOp0
306
+ def apply(a, b)
307
+ a * b
308
+ end
309
+ end
310
+
311
+ module MultitiveOp1
312
+ def apply(a, b)
313
+ a / b
314
+ end
315
+ end
316
+
317
+ def _nt_multitive_op
318
+ start_index = index
319
+ cached = node_cache[:multitive_op][index]
320
+ if cached
321
+ @index = cached.interval.end
322
+ return cached
323
+ end
324
+
325
+ i0 = index
326
+ r1 = parse_terminal('*', SyntaxNode, MultitiveOp0)
327
+ if r1.success?
328
+ r0 = r1
329
+ else
330
+ r2 = parse_terminal('/', SyntaxNode, MultitiveOp1)
331
+ if r2.success?
332
+ r0 = r2
333
+ else
334
+ self.index = i0
335
+ r0 = ParseFailure.new(input, i0)
336
+ end
337
+ end
338
+
339
+ node_cache[:multitive_op][start_index] = r0
340
+
341
+ return r0
342
+ end
343
+
344
+ module Primary0
345
+ def space
346
+ elements[1]
347
+ end
348
+
349
+ def expression
350
+ elements[2]
351
+ end
352
+
353
+ def space
354
+ elements[3]
355
+ end
356
+
357
+ end
358
+
359
+ module Primary1
360
+ def eval(env={})
361
+ expression.eval(env)
362
+ end
363
+ end
364
+
365
+ def _nt_primary
366
+ start_index = index
367
+ cached = node_cache[:primary][index]
368
+ if cached
369
+ @index = cached.interval.end
370
+ return cached
371
+ end
372
+
373
+ i0 = index
374
+ r1 = _nt_variable
375
+ if r1.success?
376
+ r0 = r1
377
+ else
378
+ r2 = _nt_number
379
+ if r2.success?
380
+ r0 = r2
381
+ else
382
+ i3, s3 = index, []
383
+ r4 = parse_terminal('(', SyntaxNode)
384
+ s3 << r4
385
+ if r4.success?
386
+ r5 = _nt_space
387
+ s3 << r5
388
+ if r5.success?
389
+ r6 = _nt_expression
390
+ s3 << r6
391
+ if r6.success?
392
+ r7 = _nt_space
393
+ s3 << r7
394
+ if r7.success?
395
+ r8 = parse_terminal(')', SyntaxNode)
396
+ s3 << r8
397
+ end
398
+ end
399
+ end
400
+ end
401
+ if s3.last.success?
402
+ r3 = (SyntaxNode).new(input, i3...index, s3)
403
+ r3.extend(Primary0)
404
+ r3.extend(Primary1)
405
+ else
406
+ self.index = i3
407
+ r3 = ParseFailure.new(input, i3)
408
+ end
409
+ if r3.success?
410
+ r0 = r3
411
+ else
412
+ self.index = i0
413
+ r0 = ParseFailure.new(input, i0)
414
+ end
415
+ end
416
+ end
417
+
418
+ node_cache[:primary][start_index] = r0
419
+
420
+ return r0
421
+ end
422
+
423
+ module Variable0
424
+ def eval(env={})
425
+ env[name]
426
+ end
427
+
428
+ def name
429
+ text_value
430
+ end
431
+ end
432
+
433
+ def _nt_variable
434
+ start_index = index
435
+ cached = node_cache[:variable][index]
436
+ if cached
437
+ @index = cached.interval.end
438
+ return cached
439
+ end
440
+
441
+ s0, i0 = [], index
442
+ loop do
443
+ r1 = parse_char_class(/[a-z]/, 'a-z', SyntaxNode)
444
+ if r1.success?
445
+ s0 << r1
446
+ else
447
+ break
448
+ end
449
+ end
450
+ if s0.empty?
451
+ self.index = i0
452
+ r0 = ParseFailure.new(input, i0)
453
+ else
454
+ r0 = SyntaxNode.new(input, i0...index, s0)
455
+ r0.extend(Variable0)
456
+ end
457
+
458
+ node_cache[:variable][start_index] = r0
459
+
460
+ return r0
461
+ end
462
+
463
+ module Number0
464
+ end
465
+
466
+ module Number1
467
+ def eval(env={})
468
+ text_value.to_i
469
+ end
470
+ end
471
+
472
+ def _nt_number
473
+ start_index = index
474
+ cached = node_cache[:number][index]
475
+ if cached
476
+ @index = cached.interval.end
477
+ return cached
478
+ end
479
+
480
+ i0 = index
481
+ i1, s1 = index, []
482
+ r2 = parse_char_class(/[1-9]/, '1-9', SyntaxNode)
483
+ s1 << r2
484
+ if r2.success?
485
+ s3, i3 = [], index
486
+ loop do
487
+ r4 = parse_char_class(/[0-9]/, '0-9', SyntaxNode)
488
+ if r4.success?
489
+ s3 << r4
490
+ else
491
+ break
492
+ end
493
+ end
494
+ r3 = SyntaxNode.new(input, i3...index, s3)
495
+ s1 << r3
496
+ end
497
+ if s1.last.success?
498
+ r1 = (SyntaxNode).new(input, i1...index, s1)
499
+ r1.extend(Number0)
500
+ else
501
+ self.index = i1
502
+ r1 = ParseFailure.new(input, i1)
503
+ end
504
+ if r1.success?
505
+ r0 = r1
506
+ r0.extend(Number1)
507
+ else
508
+ r5 = parse_terminal('0', SyntaxNode)
509
+ if r5.success?
510
+ r0 = r5
511
+ r0.extend(Number1)
512
+ else
513
+ self.index = i0
514
+ r0 = ParseFailure.new(input, i0)
515
+ end
516
+ end
517
+
518
+ node_cache[:number][start_index] = r0
519
+
520
+ return r0
521
+ end
522
+
523
+ def _nt_space
524
+ start_index = index
525
+ cached = node_cache[:space][index]
526
+ if cached
527
+ @index = cached.interval.end
528
+ return cached
529
+ end
530
+
531
+ s0, i0 = [], index
532
+ loop do
533
+ r1 = parse_terminal(' ', SyntaxNode)
534
+ if r1.success?
535
+ s0 << r1
536
+ else
537
+ break
538
+ end
539
+ end
540
+ r0 = SyntaxNode.new(input, i0...index, s0)
541
+
542
+ node_cache[:space][start_index] = r0
543
+
544
+ return r0
545
+ end
546
+
547
+ end
548
+
549
+ class ArithmeticParser < Treetop::Runtime::CompiledParser
550
+ include Arithmetic
551
+ end