oakproof 0.7.1
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.
- 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
|