personify 1.0.0

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.
Files changed (130) hide show
  1. data/.gitignore +1 -0
  2. data/LICENSE +20 -0
  3. data/README.md +172 -0
  4. data/Rakefile +53 -0
  5. data/VERSION +1 -0
  6. data/doc/syntax_ideas.md +141 -0
  7. data/lib/personify/context.rb +55 -0
  8. data/lib/personify/parser/personify.rb +1071 -0
  9. data/lib/personify/parser/personify.treetop +107 -0
  10. data/lib/personify/parser/personify_node_classes.rb +121 -0
  11. data/lib/personify/template.rb +17 -0
  12. data/lib/personify.rb +8 -0
  13. data/script/generate_parser.rb +6 -0
  14. data/test/context_test.rb +122 -0
  15. data/test/fixtures/multiple_tags.txt +8 -0
  16. data/test/parse_runner.rb +60 -0
  17. data/test/parser_test.rb +291 -0
  18. data/test/test_helper.rb +16 -0
  19. data/vendor/treetop/.gitignore +5 -0
  20. data/vendor/treetop/History.txt +9 -0
  21. data/vendor/treetop/README +164 -0
  22. data/vendor/treetop/Rakefile +20 -0
  23. data/vendor/treetop/Treetop.tmbundle/Snippets/grammar ___ end.tmSnippet +20 -0
  24. data/vendor/treetop/Treetop.tmbundle/Snippets/rule ___ end.tmSnippet +18 -0
  25. data/vendor/treetop/Treetop.tmbundle/Syntaxes/Treetop Grammar.tmLanguage +251 -0
  26. data/vendor/treetop/Treetop.tmbundle/info.plist +10 -0
  27. data/vendor/treetop/bin/tt +28 -0
  28. data/vendor/treetop/doc/contributing_and_planned_features.markdown +103 -0
  29. data/vendor/treetop/doc/grammar_composition.markdown +65 -0
  30. data/vendor/treetop/doc/index.markdown +90 -0
  31. data/vendor/treetop/doc/pitfalls_and_advanced_techniques.markdown +51 -0
  32. data/vendor/treetop/doc/semantic_interpretation.markdown +189 -0
  33. data/vendor/treetop/doc/site.rb +110 -0
  34. data/vendor/treetop/doc/sitegen.rb +60 -0
  35. data/vendor/treetop/doc/syntactic_recognition.markdown +100 -0
  36. data/vendor/treetop/doc/using_in_ruby.markdown +21 -0
  37. data/vendor/treetop/examples/lambda_calculus/arithmetic.rb +551 -0
  38. data/vendor/treetop/examples/lambda_calculus/arithmetic.treetop +97 -0
  39. data/vendor/treetop/examples/lambda_calculus/arithmetic_node_classes.rb +7 -0
  40. data/vendor/treetop/examples/lambda_calculus/arithmetic_test.rb +54 -0
  41. data/vendor/treetop/examples/lambda_calculus/lambda_calculus +0 -0
  42. data/vendor/treetop/examples/lambda_calculus/lambda_calculus.rb +718 -0
  43. data/vendor/treetop/examples/lambda_calculus/lambda_calculus.treetop +132 -0
  44. data/vendor/treetop/examples/lambda_calculus/lambda_calculus_node_classes.rb +5 -0
  45. data/vendor/treetop/examples/lambda_calculus/lambda_calculus_test.rb +89 -0
  46. data/vendor/treetop/examples/lambda_calculus/test_helper.rb +18 -0
  47. data/vendor/treetop/lib/treetop/bootstrap_gen_1_metagrammar.rb +45 -0
  48. data/vendor/treetop/lib/treetop/compiler/grammar_compiler.rb +40 -0
  49. data/vendor/treetop/lib/treetop/compiler/lexical_address_space.rb +17 -0
  50. data/vendor/treetop/lib/treetop/compiler/metagrammar.rb +2955 -0
  51. data/vendor/treetop/lib/treetop/compiler/metagrammar.treetop +404 -0
  52. data/vendor/treetop/lib/treetop/compiler/node_classes/anything_symbol.rb +20 -0
  53. data/vendor/treetop/lib/treetop/compiler/node_classes/atomic_expression.rb +14 -0
  54. data/vendor/treetop/lib/treetop/compiler/node_classes/character_class.rb +22 -0
  55. data/vendor/treetop/lib/treetop/compiler/node_classes/choice.rb +31 -0
  56. data/vendor/treetop/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
  57. data/vendor/treetop/lib/treetop/compiler/node_classes/grammar.rb +28 -0
  58. data/vendor/treetop/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
  59. data/vendor/treetop/lib/treetop/compiler/node_classes/nonterminal.rb +13 -0
  60. data/vendor/treetop/lib/treetop/compiler/node_classes/optional.rb +19 -0
  61. data/vendor/treetop/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
  62. data/vendor/treetop/lib/treetop/compiler/node_classes/parsing_expression.rb +138 -0
  63. data/vendor/treetop/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
  64. data/vendor/treetop/lib/treetop/compiler/node_classes/predicate.rb +45 -0
  65. data/vendor/treetop/lib/treetop/compiler/node_classes/repetition.rb +55 -0
  66. data/vendor/treetop/lib/treetop/compiler/node_classes/sequence.rb +68 -0
  67. data/vendor/treetop/lib/treetop/compiler/node_classes/terminal.rb +20 -0
  68. data/vendor/treetop/lib/treetop/compiler/node_classes/transient_prefix.rb +9 -0
  69. data/vendor/treetop/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
  70. data/vendor/treetop/lib/treetop/compiler/node_classes.rb +19 -0
  71. data/vendor/treetop/lib/treetop/compiler/ruby_builder.rb +113 -0
  72. data/vendor/treetop/lib/treetop/compiler.rb +6 -0
  73. data/vendor/treetop/lib/treetop/ruby_extensions/string.rb +42 -0
  74. data/vendor/treetop/lib/treetop/ruby_extensions.rb +2 -0
  75. data/vendor/treetop/lib/treetop/runtime/compiled_parser.rb +95 -0
  76. data/vendor/treetop/lib/treetop/runtime/interval_skip_list/head_node.rb +15 -0
  77. data/vendor/treetop/lib/treetop/runtime/interval_skip_list/interval_skip_list.rb +200 -0
  78. data/vendor/treetop/lib/treetop/runtime/interval_skip_list/node.rb +164 -0
  79. data/vendor/treetop/lib/treetop/runtime/interval_skip_list.rb +4 -0
  80. data/vendor/treetop/lib/treetop/runtime/syntax_node.rb +72 -0
  81. data/vendor/treetop/lib/treetop/runtime/terminal_parse_failure.rb +16 -0
  82. data/vendor/treetop/lib/treetop/runtime/terminal_syntax_node.rb +17 -0
  83. data/vendor/treetop/lib/treetop/runtime.rb +5 -0
  84. data/vendor/treetop/lib/treetop/version.rb +9 -0
  85. data/vendor/treetop/lib/treetop.rb +11 -0
  86. data/vendor/treetop/script/generate_metagrammar.rb +14 -0
  87. data/vendor/treetop/script/svnadd +11 -0
  88. data/vendor/treetop/script/svnrm +11 -0
  89. data/vendor/treetop/spec/compiler/and_predicate_spec.rb +36 -0
  90. data/vendor/treetop/spec/compiler/anything_symbol_spec.rb +52 -0
  91. data/vendor/treetop/spec/compiler/character_class_spec.rb +188 -0
  92. data/vendor/treetop/spec/compiler/choice_spec.rb +80 -0
  93. data/vendor/treetop/spec/compiler/circular_compilation_spec.rb +28 -0
  94. data/vendor/treetop/spec/compiler/failure_propagation_functional_spec.rb +21 -0
  95. data/vendor/treetop/spec/compiler/grammar_compiler_spec.rb +84 -0
  96. data/vendor/treetop/spec/compiler/grammar_spec.rb +41 -0
  97. data/vendor/treetop/spec/compiler/nonterminal_symbol_spec.rb +40 -0
  98. data/vendor/treetop/spec/compiler/not_predicate_spec.rb +38 -0
  99. data/vendor/treetop/spec/compiler/one_or_more_spec.rb +35 -0
  100. data/vendor/treetop/spec/compiler/optional_spec.rb +37 -0
  101. data/vendor/treetop/spec/compiler/parenthesized_expression_spec.rb +19 -0
  102. data/vendor/treetop/spec/compiler/parsing_rule_spec.rb +32 -0
  103. data/vendor/treetop/spec/compiler/sequence_spec.rb +115 -0
  104. data/vendor/treetop/spec/compiler/terminal_spec.rb +81 -0
  105. data/vendor/treetop/spec/compiler/terminal_symbol_spec.rb +37 -0
  106. data/vendor/treetop/spec/compiler/test_grammar.treetop +7 -0
  107. data/vendor/treetop/spec/compiler/test_grammar.tt +7 -0
  108. data/vendor/treetop/spec/compiler/test_grammar_do.treetop +7 -0
  109. data/vendor/treetop/spec/compiler/zero_or_more_spec.rb +56 -0
  110. data/vendor/treetop/spec/composition/a.treetop +11 -0
  111. data/vendor/treetop/spec/composition/b.treetop +11 -0
  112. data/vendor/treetop/spec/composition/c.treetop +10 -0
  113. data/vendor/treetop/spec/composition/d.treetop +10 -0
  114. data/vendor/treetop/spec/composition/grammar_composition_spec.rb +26 -0
  115. data/vendor/treetop/spec/ruby_extensions/string_spec.rb +32 -0
  116. data/vendor/treetop/spec/runtime/compiled_parser_spec.rb +101 -0
  117. data/vendor/treetop/spec/runtime/interval_skip_list/delete_spec.rb +147 -0
  118. data/vendor/treetop/spec/runtime/interval_skip_list/expire_range_spec.rb +349 -0
  119. data/vendor/treetop/spec/runtime/interval_skip_list/insert_and_delete_node.rb +385 -0
  120. data/vendor/treetop/spec/runtime/interval_skip_list/insert_spec.rb +660 -0
  121. data/vendor/treetop/spec/runtime/interval_skip_list/interval_skip_list_spec.graffle +6175 -0
  122. data/vendor/treetop/spec/runtime/interval_skip_list/interval_skip_list_spec.rb +58 -0
  123. data/vendor/treetop/spec/runtime/interval_skip_list/palindromic_fixture.rb +23 -0
  124. data/vendor/treetop/spec/runtime/interval_skip_list/palindromic_fixture_spec.rb +164 -0
  125. data/vendor/treetop/spec/runtime/interval_skip_list/spec_helper.rb +84 -0
  126. data/vendor/treetop/spec/runtime/syntax_node_spec.rb +53 -0
  127. data/vendor/treetop/spec/spec_helper.rb +106 -0
  128. data/vendor/treetop/spec/spec_suite.rb +4 -0
  129. data/vendor/treetop/treetop.gemspec +18 -0
  130. metadata +196 -0
@@ -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
@@ -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,7 @@
1
+ module Arithmetic
2
+ class BinaryOperation < Treetop::Runtime::SyntaxNode
3
+ def eval(env={})
4
+ operator.apply(operand_1.eval(env), operand_2.eval(env))
5
+ end
6
+ end
7
+ 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