oakproof 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/eprover/eprover-2.3-linux +0 -0
- data/eprover/eprover-2.3-mac +0 -0
- data/eprover/eprover-2.3-windows.exe +0 -0
- data/eprover/eprover.txt +5 -0
- data/oak +3 -0
- data/src/bindings.rb +464 -0
- data/src/commands.rb +349 -0
- data/src/external prover.rb +189 -0
- data/src/grammar rules.rb +439 -0
- data/src/grammar.rb +218 -0
- data/src/oak.rb +56 -0
- data/src/parser.rb +1089 -0
- data/src/proof.rb +471 -0
- data/src/schema.rb +170 -0
- data/src/utilities.rb +361 -0
- metadata +58 -0
@@ -0,0 +1,439 @@
|
|
1
|
+
def grammar_rules
|
2
|
+
[
|
3
|
+
[:start, :ending, :end], # needed to preserve line numbers
|
4
|
+
[:start, :begin_assume, :start5],
|
5
|
+
[:start, :end_assume, :start5],
|
6
|
+
[:start, :marker, :start5],
|
7
|
+
[:start, :include, :start5],
|
8
|
+
[:start, :now, :start5],
|
9
|
+
[:start, :end, :start5],
|
10
|
+
[:start, :exit, :start5],
|
11
|
+
[:start, :tie_in, :start3],
|
12
|
+
[:start, :label, :start2],
|
13
|
+
[:start, :else, :start2],
|
14
|
+
|
15
|
+
# things that can have labels
|
16
|
+
[:start2, :assume, :start4],
|
17
|
+
[:start2, :axiom, :start5],
|
18
|
+
[:start2, :suppose, :start5],
|
19
|
+
[:start2, :take, :start5],
|
20
|
+
[:start2, :so, :start3],
|
21
|
+
[:start2, :derive, :start3],
|
22
|
+
|
23
|
+
[:start3, :by, :start5],
|
24
|
+
[:start3, :proof, :start5],
|
25
|
+
[:start3, :else, :start5],
|
26
|
+
[:start4, :by, :start5],
|
27
|
+
[:start4, :else, :start5],
|
28
|
+
[:start5, :ending, :end],
|
29
|
+
|
30
|
+
[:label, [:label_name, /\s*:/], :end, :catch],
|
31
|
+
|
32
|
+
[:label_same_line, [:label_name_same_line, /\s*:/], :end, :catch],
|
33
|
+
|
34
|
+
[:include, /\s*include\b/i, :filename],
|
35
|
+
|
36
|
+
[:begin_assume, /\s*begin assume\b/i, :end],
|
37
|
+
|
38
|
+
[:end_assume, /\s*end assume\b/i, :end],
|
39
|
+
|
40
|
+
[:marker, /\s*marker\b/i, :end],
|
41
|
+
|
42
|
+
[:filename, [/\s*"/, /[^"\n]+/, /"/], :end],
|
43
|
+
|
44
|
+
[:tie_in, /\s*tie-in\b/i, :tie_in2],
|
45
|
+
[:tie_in2, [:quote, :with, :quote], :tie_in3],
|
46
|
+
[:tie_in3, /\s*for (all|any|each|every)\b/i, :tie_in4],
|
47
|
+
[:tie_in3, :else, :end],
|
48
|
+
[:tie_in4, :atom_list_adjacent, :end],
|
49
|
+
|
50
|
+
[:assume, /\s*assume\b/i, :assume2],
|
51
|
+
[:assume2, :tie_in, :end],
|
52
|
+
[:assume2, :else, :label_schema],
|
53
|
+
|
54
|
+
[:axiom, /\s*axiom\b/i, :label_schema],
|
55
|
+
|
56
|
+
[:label_schema, :label_same_line, :label_schema2],
|
57
|
+
[:label_schema, :else, :label_schema2],
|
58
|
+
[:label_schema2, :schema, :end],
|
59
|
+
[:label_schema2, :define, :end],
|
60
|
+
[:label_schema2, :exp, :end],
|
61
|
+
|
62
|
+
[:schema, [/\s*schema\b/i, :universal_meta], :end],
|
63
|
+
|
64
|
+
[:suppose, /\s*suppose\b/i, :suppose2],
|
65
|
+
[:suppose2, :label_same_line, :suppose3],
|
66
|
+
[:suppose2, :else, :suppose3],
|
67
|
+
[:suppose3, :exp, :end],
|
68
|
+
|
69
|
+
[:take, :take_label, :post_quantifier],
|
70
|
+
[:take_label, /\s*take any\b/i, :end],
|
71
|
+
[:take_label, [/\s*take\b/i, :label_same_line, /\s*any\b/i], :end],
|
72
|
+
|
73
|
+
[:so, /\s*so\b/i, :so2],
|
74
|
+
[:so2, :assume, :end],
|
75
|
+
[:so2, :label_same_line, :so3],
|
76
|
+
[:so2, :else, :so3],
|
77
|
+
[:so3, :define, :end],
|
78
|
+
[:so3, :exp, :end],
|
79
|
+
|
80
|
+
[:now, /\s*now\b/i, :end],
|
81
|
+
|
82
|
+
[:end, /\s*end\b/i, :end],
|
83
|
+
|
84
|
+
[:derive, :exp, :end],
|
85
|
+
[:derive, :let, :end],
|
86
|
+
[:derive, :define, :end],
|
87
|
+
|
88
|
+
[:exit, /\s*exit\b/i, :end],
|
89
|
+
|
90
|
+
[:by, /\s*(by|from)\b/i, :by2],
|
91
|
+
[:by2, :question_mark, :by3],
|
92
|
+
[:by2, :label_name, :by3],
|
93
|
+
[:by3, /\s*,/, :by2],
|
94
|
+
[:by3, /\s*and\b/i, :by2],
|
95
|
+
[:by3, :else, :end],
|
96
|
+
|
97
|
+
[:question_mark, /\s*\?/, :end],
|
98
|
+
|
99
|
+
[:proof, /\s*proof\b/i, :end],
|
100
|
+
|
101
|
+
[:ending, /\s*\.\s|\s*\.\z/, :end],
|
102
|
+
[:ending, /\s*;/, :end],
|
103
|
+
[:ending, /\s*\n/, :end],
|
104
|
+
[:ending, /\s*\z/, :end],
|
105
|
+
|
106
|
+
# prefix can have any prefix under it
|
107
|
+
# prefix can have any infix of higher level under it
|
108
|
+
|
109
|
+
# infix can have any prefix of higher level to left of it
|
110
|
+
# infix can have any infix of higher level to left of it
|
111
|
+
|
112
|
+
# infix can have any prefix to right of it
|
113
|
+
# infix can have any infix of higher level to right of it
|
114
|
+
|
115
|
+
[:exp, :exp_, :end],
|
116
|
+
|
117
|
+
[:prefix_, :universal, :end],
|
118
|
+
[:prefix_, :for_at_most_one, :end],
|
119
|
+
[:prefix_, :no_existential, :end],
|
120
|
+
[:prefix_, :existential, :end],
|
121
|
+
|
122
|
+
# no infix at this level
|
123
|
+
[:exp_, :prefix_, :end],
|
124
|
+
[:exp_, :exp0, :end],
|
125
|
+
|
126
|
+
[:prefix0, :if, :end],
|
127
|
+
|
128
|
+
[:exp0, :prefix0, :end],
|
129
|
+
[:exp0, :exp1, :exp0a],
|
130
|
+
[:exp0a, /\s*(iff|if and only if)\b/i, :exp0b],
|
131
|
+
[:exp0a, /\s*implies( that)?\b/i, :exp0b],
|
132
|
+
[:exp0a, :else, :end],
|
133
|
+
[:exp0b, :exp1, :end],
|
134
|
+
[:exp0b, :prefix0, :end],
|
135
|
+
[:exp0b, :prefix_, :end],
|
136
|
+
|
137
|
+
[:prefix1, :not, :end],
|
138
|
+
|
139
|
+
[:exp1, :prefix1, :end],
|
140
|
+
[:exp1, :exp2, :exp1a],
|
141
|
+
[:exp1a, :and, :and1],
|
142
|
+
[:and, /\s*and\b/i, :end],
|
143
|
+
[:and1, :exp2, :and2],
|
144
|
+
[:and1, :else, :exp1c],
|
145
|
+
[:and2, :and, :and1],
|
146
|
+
[:and2, :else, :end],
|
147
|
+
[:exp1a, :or, :or1],
|
148
|
+
[:or, /\s*or\b/i, :end],
|
149
|
+
[:or1, :exp2, :or2],
|
150
|
+
[:or1, :else, :exp1c],
|
151
|
+
[:or2, :or, :or1],
|
152
|
+
[:or2, :else, :end],
|
153
|
+
[:exp1a, :else, :end],
|
154
|
+
[:exp1b, :exp2, :end],
|
155
|
+
[:exp1b, :else, :exp1c],
|
156
|
+
[:exp1c, :prefix1, :end],
|
157
|
+
[:exp1c, :prefix0, :end],
|
158
|
+
[:exp1c, :prefix_, :end],
|
159
|
+
|
160
|
+
[:prefix2, :every, :end],
|
161
|
+
[:prefix2, :no, :end],
|
162
|
+
[:prefix2, :some, :end],
|
163
|
+
[:prefix2, :at_most_one, :end],
|
164
|
+
|
165
|
+
[:exp2, :prefix2, :end],
|
166
|
+
[:exp2, :exp3, :exp2a],
|
167
|
+
[:exp2a, /\s*=/i, :exp2b],
|
168
|
+
[:exp2a, :not_equal, :exp2b],
|
169
|
+
[:exp2a, :inequality, :exp2b],
|
170
|
+
[:exp2a, :is_in, :exp2b],
|
171
|
+
[:exp2a, :is_not_in, :exp2b],
|
172
|
+
[:exp2a, :is_not, :is_predicate],
|
173
|
+
[:exp2a, :is, :is_predicate],
|
174
|
+
[:exp2a, :set_relation, :exp2b],
|
175
|
+
[:exp2a, :custom, :exp2b], # not sure about this, move or remove?
|
176
|
+
[:exp2a, :else, :end],
|
177
|
+
[:exp2b, :exp3, :end],
|
178
|
+
|
179
|
+
# addition, subtraction, union, and intersection
|
180
|
+
[:exp3, :exp4, :exp3a],
|
181
|
+
[:exp3a, :plus, :plus1],
|
182
|
+
[:plus, /\s*\+/i, :end],
|
183
|
+
[:plus1, :exp4, :plus2],
|
184
|
+
[:plus2, :plus, :plus1],
|
185
|
+
[:plus2, :else, :end],
|
186
|
+
[:exp3a, /\s*\-/i, :exp3b],
|
187
|
+
[:exp3a, :union, :union1],
|
188
|
+
[:union, /\s*\∪/i, :end],
|
189
|
+
[:union1, :exp4, :union2],
|
190
|
+
[:union2, :union, :union1],
|
191
|
+
[:union2, :else, :end],
|
192
|
+
[:exp3a, :intersection, :intersection1],
|
193
|
+
[:intersection, /\s*\∩/i, :end],
|
194
|
+
[:intersection1, :exp4, :intersection2],
|
195
|
+
[:intersection2, :intersection, :intersection1],
|
196
|
+
[:intersection2, :else, :end],
|
197
|
+
[:exp3a, :else, :end],
|
198
|
+
[:exp3b, :exp4, :end],
|
199
|
+
|
200
|
+
# multiplication and division
|
201
|
+
[:exp4, :exp5, :exp4a],
|
202
|
+
[:exp4a, :times, :times1],
|
203
|
+
[:times, /\s*\*/i, :end],
|
204
|
+
[:times1, :exp5, :times2],
|
205
|
+
[:times2, :times, :times1],
|
206
|
+
[:times2, :else, :end],
|
207
|
+
[:exp4a, /\s*\//i, :exp4b],
|
208
|
+
[:exp4a, /\s*÷/i, :exp4b],
|
209
|
+
[:exp4a, :else, :end],
|
210
|
+
[:exp4b, :exp5, :end],
|
211
|
+
|
212
|
+
# exponentiation
|
213
|
+
[:exp5, :exp6, :exp5a],
|
214
|
+
[:exp5a, /\s*\^/i, :exp5b],
|
215
|
+
[:exp5a, /\s*\*\*/i, :exp5b],
|
216
|
+
[:exp5a, :else, :end],
|
217
|
+
[:exp5b, :exp6, :end],
|
218
|
+
|
219
|
+
[:exp6, :operand, :end],
|
220
|
+
|
221
|
+
[:if, [/\s*if\b/i, :exp, /\s*,?\s*then\b/i], :exp0b],
|
222
|
+
|
223
|
+
[:not, /\s*not\b/i, :exp1b],
|
224
|
+
|
225
|
+
[:atom_list, :atom_block, :atom_list2],
|
226
|
+
[:atom_list2, [/\s*and\b/i, :atom_block], :atom_list2],
|
227
|
+
[:atom_list2, :else, :end],
|
228
|
+
|
229
|
+
[:atom_block, :word, :atom_block2],
|
230
|
+
[:atom_block, :else, :atom_list_adjacent],
|
231
|
+
[:atom_block2, :word_same_line, :atom_block2],
|
232
|
+
[:atom_block2, :condition, :end, :catch],
|
233
|
+
[:atom_block2, :definable_same_line, :atom_list_adjacent2],
|
234
|
+
[:atom_block2, :else, :atom_list_adjacent2],
|
235
|
+
|
236
|
+
[:atom_list_adjacent, :definable, :atom_list_adjacent2],
|
237
|
+
[:atom_list_adjacent2, [/,/, :definable_raw,], :atom_list_adjacent2, :catch],
|
238
|
+
[:atom_list_adjacent2, :condition, :end],
|
239
|
+
[:atom_list_adjacent2, :else, :end],
|
240
|
+
|
241
|
+
[:universal, /\s*for (all|any|each|every) meta\b/i, :null],
|
242
|
+
[:universal, /\s*for (all|any|each|every)\b/i, :post_quantifier_exp],
|
243
|
+
|
244
|
+
[:universal_meta, /\s*for (all|any|each|every) meta\b/i, :universal_meta2],
|
245
|
+
[:universal_meta2, [:list_with_such, /,\s/, :quote], :end],
|
246
|
+
|
247
|
+
[:existential, /\s*for (at least one|some)\b/i, :post_quantifier_exp],
|
248
|
+
[:existential, /\s*there (exist|exists|is|are)( (a|an|at least one|some))?\b/i, :post_quantifier],
|
249
|
+
[:for_at_most_one, /\s*for at most one\b/i, :post_quantifier_exp],
|
250
|
+
[:for_at_most_one, /\s*there (exist|exists|is|are) at most one\b/i, :post_quantifier],
|
251
|
+
[:no_existential, /\s*for no\b/i, :post_quantifier_exp],
|
252
|
+
[:no_existential, /\s*there (exist|exists|is|are) no\b/i, :post_quantifier],
|
253
|
+
|
254
|
+
[:post_quantifier_exp, :list_with_such, :post_quantifier_exp2],
|
255
|
+
[:post_quantifier_exp2, [/,\s/, :exp], :end],
|
256
|
+
|
257
|
+
[:post_quantifier, :list_with_such, :end],
|
258
|
+
|
259
|
+
[:list_with_such, :atom_list, :list_with_such2],
|
260
|
+
[:list_with_such2, [:with, :exp], :list_with_such3],
|
261
|
+
[:list_with_such2, :else, :list_with_such3],
|
262
|
+
[:list_with_such3, [:such_that, :exp], :end],
|
263
|
+
[:list_with_such3, :else, :end],
|
264
|
+
|
265
|
+
[:with, /\s*with\b/i, :end],
|
266
|
+
|
267
|
+
[:such_that, /\s*(such that|where)\b/i, :end],
|
268
|
+
|
269
|
+
[:let, /\s*let\b/i, :let2],
|
270
|
+
[:let2, :definable, :let3],
|
271
|
+
[:let3, /\s*=/i, :let4],
|
272
|
+
[:let4, :exp, :end],
|
273
|
+
|
274
|
+
[:define, /\s*define\b/i, :post_quantifier],
|
275
|
+
|
276
|
+
[:condition, [/\s*in\b/i, :exp3], :end],
|
277
|
+
[:condition, [/\s*not in\b/i, :exp3], :end],
|
278
|
+
[:condition, [:inequality, :exp3], :end],
|
279
|
+
[:condition, [:set_relation, :exp3], :end],
|
280
|
+
[:condition, [:not_equal, :exp3], :end],
|
281
|
+
|
282
|
+
[:inequality, /\s*<=/i, :end],
|
283
|
+
[:inequality, /\s*≤/i, :end],
|
284
|
+
[:inequality, /\s*</i, :end],
|
285
|
+
[:inequality, /\s*>=/i, :end],
|
286
|
+
[:inequality, /\s*≥/i, :end],
|
287
|
+
[:inequality, /\s*>/i, :end],
|
288
|
+
|
289
|
+
[:set_relation, /\s*\⊆/i, :end],
|
290
|
+
[:set_relation, /\s*\⊊/i, :end],
|
291
|
+
[:set_relation, /\s*\⊇/i, :end],
|
292
|
+
[:set_relation, /\s*\⊋/i, :end],
|
293
|
+
[:set_relation, /\s*\⊂/i, :end],
|
294
|
+
[:set_relation, /\s*\⊃/i, :end],
|
295
|
+
|
296
|
+
[:not_equal, /\s*!=/i, :end],
|
297
|
+
[:not_equal, /\s*≠/i, :end],
|
298
|
+
|
299
|
+
[:custom, [:word_same_line, /[ \t]/], :end],
|
300
|
+
|
301
|
+
[:is, /\s*is\b/i, :end],
|
302
|
+
[:is_not, /\s*is not\b/i, :end],
|
303
|
+
|
304
|
+
[:is_in, /\s*is in\b/i, :end],
|
305
|
+
[:is_not_in, /\s*is not in\b/i, :end],
|
306
|
+
|
307
|
+
[:preposition, /\s*(of|on)\b/i, :end],
|
308
|
+
|
309
|
+
[:category, :word, :category2],
|
310
|
+
[:category2, [:preposition, :exp3], :end],
|
311
|
+
[:category2, :word_same_line, :category2],
|
312
|
+
[:category2, :else, :end],
|
313
|
+
|
314
|
+
[:article, /\s*(a|an)\b/i, :end],
|
315
|
+
|
316
|
+
[:quantified, [:article, :category], :end],
|
317
|
+
|
318
|
+
[:is_predicate, :quantified, :end],
|
319
|
+
[:is_predicate, :word, :end],
|
320
|
+
|
321
|
+
[:every, /\s*every\b/i, :category_is],
|
322
|
+
|
323
|
+
[:no, /\s*no\b/i, :category_is],
|
324
|
+
|
325
|
+
[:some, /\s*(some|at least one)\b/i, :category_is_with_not],
|
326
|
+
|
327
|
+
[:at_most_one, /\s*at most one\b/i, :category_is_with_not],
|
328
|
+
|
329
|
+
[:category_is, :category, :category_is2],
|
330
|
+
[:category_is2, :is_in, :exp2b],
|
331
|
+
[:category_is2, :is, :is_predicate],
|
332
|
+
|
333
|
+
[:category_is_with_not, :category, :category_is_with_not2],
|
334
|
+
[:category_is_with_not2, :is_in, :exp2b],
|
335
|
+
[:category_is_with_not2, :is_not_in, :exp2b],
|
336
|
+
[:category_is_with_not2, :is_not, :is_predicate],
|
337
|
+
[:category_is_with_not2, :is, :is_predicate],
|
338
|
+
|
339
|
+
[:boolean, /\s*(true|false|contradiction)\b/i, :end],
|
340
|
+
|
341
|
+
[:thesis, /\s*thesis\b/i, :end],
|
342
|
+
|
343
|
+
# [:meta, [/\$/, :operand_base], :end],
|
344
|
+
|
345
|
+
[:quote, [/\s*`/, :exp, /\s*`/], :end],
|
346
|
+
|
347
|
+
[:string, /\s*"/, :string2],
|
348
|
+
[:string2, /"/, :end],
|
349
|
+
# [:string2, :meta, :string2],
|
350
|
+
# [:string2, /[^"$]*/, :string2],
|
351
|
+
[:string2, /[^"]*/, :string2],
|
352
|
+
|
353
|
+
[:negative, /\s*-/, :negative2],
|
354
|
+
[:negative2, :atom, :end],
|
355
|
+
[:negative2, [/\[/, :exp, /\s*\]/], :end],
|
356
|
+
|
357
|
+
[:square_root, /\s*√/, :square_root2],
|
358
|
+
[:square_root2, :atom, :end],
|
359
|
+
# [:square_root2, [/\[/, :exp, /\s*\]/], :end],
|
360
|
+
|
361
|
+
[:operand, :boolean, :end],
|
362
|
+
[:operand, :thesis, :end],
|
363
|
+
[:operand, :string, :end],
|
364
|
+
[:operand, :negative, :end],
|
365
|
+
[:operand, :square_root, :end, :catch],
|
366
|
+
[:operand, :operand_base, :operand2],
|
367
|
+
[:operand2, :subst, :operand3],
|
368
|
+
[:operand2, :else, :operand3],
|
369
|
+
[:operand3, :params, :operand3],
|
370
|
+
[:operand3, :else, :end],
|
371
|
+
|
372
|
+
[:operand_base, [/\s*\(/, :exp, /\s*\)/], :end],
|
373
|
+
[:operand_base, [/\s*\|/, :exp, /\s*\|/], :end],
|
374
|
+
[:operand_base, :list, :end],
|
375
|
+
[:operand_base, :set, :end],
|
376
|
+
[:operand_base, :word, :end],
|
377
|
+
|
378
|
+
[:list, /\s*\[/, :list1a],
|
379
|
+
[:list1a, /\s*\]/, :end],
|
380
|
+
[:list1a, :else, :list2],
|
381
|
+
[:list2, :exp, :list3],
|
382
|
+
[:list3, /,/, :list2],
|
383
|
+
[:list3, :else, :list4],
|
384
|
+
[:list4, /\s*\]/, :end],
|
385
|
+
|
386
|
+
[:params, /\[/, :list2],
|
387
|
+
[:params, /\(/, :params2],
|
388
|
+
[:params2, :exp, :params3],
|
389
|
+
[:params3, /,/, :params2],
|
390
|
+
[:params3, :else, :params4],
|
391
|
+
[:params4, /\s*\)/, :end],
|
392
|
+
|
393
|
+
[:set, /\s*{/, :set1a],
|
394
|
+
[:set1a, /\s*}/, :end],
|
395
|
+
[:set1a, :else, :set2],
|
396
|
+
[:set2, :exp, :set3],
|
397
|
+
[:set3, /,/, :set2],
|
398
|
+
[:set3, :else, :set4],
|
399
|
+
[:set4, /\s*}/, :end],
|
400
|
+
|
401
|
+
[:map, /\s*{/, :map2],
|
402
|
+
[:map2, [:word, /\s*:/, :exp], :map3],
|
403
|
+
[:map3, /\s*,/, :map2],
|
404
|
+
[:map3, /\s*}/, :end],
|
405
|
+
|
406
|
+
[:subst, /{/, :map2],
|
407
|
+
|
408
|
+
[:word, [/\s*/, :atom], :end, :catch],
|
409
|
+
|
410
|
+
[:word_same_line, [/[ \t]*/, :atom], :end, :catch],
|
411
|
+
|
412
|
+
[:label_name, [/\s*/, :atom], :label_name2],
|
413
|
+
[:label_name2, [/ ?/, :atom], :label_name2, :catch],
|
414
|
+
[:label_name2, :else, :end],
|
415
|
+
|
416
|
+
[:label_name_same_line, [/[ \t]*/, :atom], :label_name2, :catch],
|
417
|
+
|
418
|
+
[:definable, [/\s*/, :definable_raw], :end, :catch],
|
419
|
+
|
420
|
+
[:definable_same_line, [/[ \t]*/, :definable_raw], :end, :catch],
|
421
|
+
|
422
|
+
[:definable_raw, /\+|\-|\*|\÷|\/|\^|⊆|⊊|⊂|\|\||{}|\[\]|∪|∩|</, :end],
|
423
|
+
[:definable_raw, :atom, :end],
|
424
|
+
|
425
|
+
[:atom, /for (all|any|at least one|at most one)\b/i, :null],
|
426
|
+
[:atom, /for (each|every|no|some)\b/i, :null],
|
427
|
+
[:atom, /there (are|exist|exists|is)\b/i, :null],
|
428
|
+
[:atom, /(at least one|at most one|every|some|no)\b/i, :null],
|
429
|
+
[:atom, /(and|any|define|if|iff|implies|in|is|let|not|of|on|or)\b/i, :null],
|
430
|
+
[:atom, /(such that|then|where|with)\b/i, :null],
|
431
|
+
[:atom, /(assume|axiom|begin assume|by|end|exit|from|include)\b/i, :null],
|
432
|
+
[:atom, /(marker|now|proof|schema|so|suppose|take)\b/i, :null],
|
433
|
+
[:atom, /(contradiction|false|thesis|true)\b/i, :null],
|
434
|
+
[:atom, /((?!
|
435
|
+
\(|\)|\[|\]|,|;|\.\s|\.\z|=|!=|≠|\+|\-|\*|÷|\^
|
436
|
+
|<=|≤|<|>=|≥|>|:|"|`|{|}|\$|\||⊆|⊇|⊊|⊋|⊂|⊃|\/
|
437
|
+
)\S)+/x, :end],
|
438
|
+
]
|
439
|
+
end
|
data/src/grammar.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
class Grammar
|
5
|
+
attr_reader :non_terminals, :start_symbol
|
6
|
+
|
7
|
+
class Rule
|
8
|
+
attr_reader :state, :input, :next_state, :catch, :multiple
|
9
|
+
|
10
|
+
def initialize state, input, next_state, catch, multiple = nil
|
11
|
+
@state, @input, @next_state, @catch, @multiple =
|
12
|
+
state, input, next_state, catch, multiple
|
13
|
+
@input = Regexp.new Regexp.escape(@input) if @input.is_a? String
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize rules
|
18
|
+
@rules = []
|
19
|
+
rules.each {|rule|
|
20
|
+
state, inputs, next_state, catch = rule
|
21
|
+
raise "bad rule format: #{rule}" if not state or (catch and catch != :catch)
|
22
|
+
if not inputs.is_a? Array
|
23
|
+
@rules << Rule.new(state, inputs, next_state, catch)
|
24
|
+
else
|
25
|
+
# make a dummy state which can be used to catch errors from the real inputs
|
26
|
+
dummy = @rules.size.to_s.to_sym
|
27
|
+
@rules << Rule.new(state, dummy, next_state, catch, :multiple)
|
28
|
+
inputs.each_with_index {|input, index|
|
29
|
+
# here we generate symbols for implicit states in input arrays
|
30
|
+
this_state = (index == 0) ? dummy : @rules.size.to_s.to_sym
|
31
|
+
if index == inputs.size - 1
|
32
|
+
this_next_state = :end
|
33
|
+
else
|
34
|
+
this_next_state = (@rules.size + 1).to_s.to_sym
|
35
|
+
end
|
36
|
+
@rules << Rule.new(this_state, input, this_next_state, catch)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
}
|
40
|
+
@non_terminals = @rules.collect {|rule| rule.state}.to_set
|
41
|
+
inputs = @rules.collect {|rule| rule.input}
|
42
|
+
symbol_inputs = inputs.select {|input| input.is_a? Symbol}
|
43
|
+
unrecognized = symbol_inputs - @non_terminals.to_a - [:else, :eof]
|
44
|
+
raise "unrecognized inputs: #{unrecognized}" unless unrecognized.empty?
|
45
|
+
@start_symbol = @rules[0].state
|
46
|
+
@rules = @rules.group_by {|rule| rule.state}
|
47
|
+
end
|
48
|
+
|
49
|
+
def [] non_terminal
|
50
|
+
@rules[non_terminal] or []
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class GrammarParser
|
55
|
+
def initialize grammar
|
56
|
+
@grammar = grammar
|
57
|
+
end
|
58
|
+
|
59
|
+
def match input
|
60
|
+
if input == :else
|
61
|
+
true
|
62
|
+
elsif input == :eof
|
63
|
+
@scanner.eos?
|
64
|
+
elsif @grammar.non_terminals.include? input
|
65
|
+
parse_from input
|
66
|
+
elsif match_string = @scanner.scan(input)
|
67
|
+
@tree.bloom match_string
|
68
|
+
true
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse program
|
75
|
+
@scanner = StringScanner.new program
|
76
|
+
@tree = GrammarTree.new
|
77
|
+
parse_from @grammar.start_symbol, true
|
78
|
+
@tree
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_each program
|
82
|
+
@scanner = StringScanner.new program
|
83
|
+
last_pos = @scanner.charpos
|
84
|
+
until @scanner.eos?
|
85
|
+
@tree = GrammarTree.new
|
86
|
+
parse_from @grammar.start_symbol, true
|
87
|
+
yield @tree, program[last_pos...@scanner.charpos], last_pos
|
88
|
+
last_pos = @scanner.charpos
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_from state, top = false
|
93
|
+
top ? @tree.root(state) : @tree.branch(state)
|
94
|
+
parsed = while true
|
95
|
+
last_pos = @scanner.pos
|
96
|
+
last_active = @tree.active
|
97
|
+
found = @grammar[state].find {|rule|
|
98
|
+
begin
|
99
|
+
match rule.input
|
100
|
+
rescue GrammarParseException => exception
|
101
|
+
unless rule.catch
|
102
|
+
if rule.multiple
|
103
|
+
# remove dummy branch which was just added, replacing it with its children
|
104
|
+
last_active.branches[-1..-1] = last_active.branches[-1].branches
|
105
|
+
# take responsibility for exception if exception state is a dummy value
|
106
|
+
if exception.state.to_s.to_i.to_s == exception.state.to_s
|
107
|
+
exception.state = state
|
108
|
+
end
|
109
|
+
end
|
110
|
+
raise
|
111
|
+
end
|
112
|
+
@scanner.pos = last_pos
|
113
|
+
@tree.prune until @tree.active == last_active
|
114
|
+
false
|
115
|
+
end
|
116
|
+
}
|
117
|
+
break false if not found
|
118
|
+
if found.multiple
|
119
|
+
# remove dummy branch which was just added, replacing it with its children
|
120
|
+
last_active.branches[-1..-1] = last_active.branches[-1].branches
|
121
|
+
end
|
122
|
+
break true if found.next_state == :end
|
123
|
+
state = found.next_state
|
124
|
+
end
|
125
|
+
committed = (not @tree.active.branches.empty?)
|
126
|
+
@tree.retract if parsed
|
127
|
+
@tree.prune if not parsed and not committed
|
128
|
+
return parsed if parsed or (not top and not committed)
|
129
|
+
raise GrammarParseException.new @tree, state, @scanner
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class GrammarParseException < StandardError
|
134
|
+
attr_reader :scanner, :tree
|
135
|
+
attr_accessor :state
|
136
|
+
|
137
|
+
def initialize tree, state, scanner
|
138
|
+
@tree = tree
|
139
|
+
@state = state
|
140
|
+
@scanner = scanner
|
141
|
+
end
|
142
|
+
|
143
|
+
def position
|
144
|
+
@scanner.charpos
|
145
|
+
end
|
146
|
+
|
147
|
+
def to_s
|
148
|
+
rest_to_show = @scanner.rest.inspect[0..80]
|
149
|
+
"\n#{@tree}parse failed in #{@state.inspect} at #{rest_to_show}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class GrammarTree
|
154
|
+
attr_reader :active
|
155
|
+
|
156
|
+
class Node
|
157
|
+
attr_accessor :branches, :parent, :value
|
158
|
+
|
159
|
+
def initialize value, parent, leaf = nil
|
160
|
+
@value, @parent = value, parent
|
161
|
+
@branches = [] unless leaf
|
162
|
+
end
|
163
|
+
|
164
|
+
def text
|
165
|
+
return @value if not @branches
|
166
|
+
@branches.collect {|branch| branch.text}.join
|
167
|
+
end
|
168
|
+
|
169
|
+
def to_s prefix = '1'
|
170
|
+
result = prefix + ' ' + @value.inspect + "\n"
|
171
|
+
if @branches
|
172
|
+
@branches.each_with_index {|branch, index|
|
173
|
+
new_prefix = prefix + '.' + (index + 1).to_s
|
174
|
+
result << branch.to_s(new_prefix)
|
175
|
+
}
|
176
|
+
end
|
177
|
+
result
|
178
|
+
end
|
179
|
+
|
180
|
+
# def to_s indent = 0
|
181
|
+
# result = ' ' * indent + @value.inspect + "\n"
|
182
|
+
# @branches.each {|branch| result << branch.to_s(indent + 1)} if @branches
|
183
|
+
# result
|
184
|
+
# end
|
185
|
+
end
|
186
|
+
|
187
|
+
def bloom string
|
188
|
+
@active.branches << Node.new(string, @active, :leaf)
|
189
|
+
end
|
190
|
+
|
191
|
+
def branch symbol
|
192
|
+
@active.branches << Node.new(symbol, @active)
|
193
|
+
@active = @active.branches[-1]
|
194
|
+
end
|
195
|
+
|
196
|
+
def prune
|
197
|
+
if @active == @root
|
198
|
+
@active, @root = nil, nil
|
199
|
+
else
|
200
|
+
@active.parent.branches.delete @active
|
201
|
+
@active = @active.parent
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def retract
|
206
|
+
@active = @active.parent
|
207
|
+
end
|
208
|
+
|
209
|
+
def root value = nil
|
210
|
+
return @root if not value
|
211
|
+
@root = Node.new value, nil
|
212
|
+
@active = @root
|
213
|
+
end
|
214
|
+
|
215
|
+
def to_s
|
216
|
+
@root.to_s
|
217
|
+
end
|
218
|
+
end
|
data/src/oak.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'proof.rb'
|
2
|
+
|
3
|
+
name_version = 'Oak version 0.7.1'
|
4
|
+
issues_url = 'https://github.com/timlabs/oak/issues'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
if ARGV.delete '-v'
|
9
|
+
puts name_version
|
10
|
+
exit if ARGV.size == 0
|
11
|
+
end
|
12
|
+
|
13
|
+
if ARGV.delete '-c'
|
14
|
+
options[:reduce] = true
|
15
|
+
end
|
16
|
+
|
17
|
+
if ARGV.delete '-f'
|
18
|
+
options[:fix] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
if ARGV.delete '-m'
|
22
|
+
options[:marker] = true
|
23
|
+
end
|
24
|
+
|
25
|
+
if ARGV.delete '-w'
|
26
|
+
options[:wait] = true
|
27
|
+
end
|
28
|
+
|
29
|
+
if options[:fix] and options[:wait]
|
30
|
+
puts 'error: options -f and -w cannot be used together'
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
|
34
|
+
if ARGV.size != 1 or ARGV[0].start_with? '-'
|
35
|
+
puts 'usage: oak [-v] [-c] [-f] [-m] [-w] <filename>'
|
36
|
+
puts ' -v print the version number of Oak'
|
37
|
+
puts ' -c check for unneeded citations'
|
38
|
+
puts ' -f look for a fix'
|
39
|
+
puts ' -m assume until marker'
|
40
|
+
puts ' -w wait for validity (does not change proof outcome)'
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
44
|
+
begin
|
45
|
+
Proof.process_file ARGV[0], options
|
46
|
+
rescue ProofException
|
47
|
+
# already printed
|
48
|
+
rescue Interrupt
|
49
|
+
puts "\naborted due to ctrl-c"
|
50
|
+
rescue => e
|
51
|
+
puts "\n\n#{e.message} (#{e.class}) [#{name_version}]"
|
52
|
+
puts "\tfrom #{e.backtrace.join "\n\tfrom "}"
|
53
|
+
puts "\nBUG: You have found a bug in the proof checker! It would be " \
|
54
|
+
"greatly appreciated if you could report it at #{issues_url} so that " \
|
55
|
+
"it can be fixed."
|
56
|
+
end
|