fitch-js 0.1.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.
- package/LICENSE +7 -0
- package/README.md +401 -0
- package/dist/cjs/index.js +131 -0
- package/dist/cjs/parser.js +211 -0
- package/dist/cjs/proof/index.js +31 -0
- package/dist/cjs/proof/textParser.js +222 -0
- package/dist/cjs/proof/types.js +117 -0
- package/dist/cjs/proofChecker.js +163 -0
- package/dist/cjs/ruleValidators.js +811 -0
- package/dist/cjs/symbols.js +85 -0
- package/dist/cjs/types.js +184 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/parser.js +204 -0
- package/dist/esm/proof/index.js +7 -0
- package/dist/esm/proof/textParser.js +217 -0
- package/dist/esm/proof/types.js +111 -0
- package/dist/esm/proofChecker.js +128 -0
- package/dist/esm/ruleValidators.js +799 -0
- package/dist/esm/symbols.js +77 -0
- package/dist/esm/types.js +178 -0
- package/package.json +45 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
4
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
5
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
6
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
7
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
8
|
+
/**
|
|
9
|
+
* ASCII to Unicode symbol conversion utilities for logical notation
|
|
10
|
+
* @module symbols
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ASCII to Unicode symbol mappings (sorted by length, longest first for correct replacement order)
|
|
14
|
+
var SYMBOL_MAPPINGS = [['<->', '↔'], ['/\\', '∧'], ['\\/', '∨'], ['_|_', '⊥'], ['->', '→'], ['~', '¬'], ['!', '¬'], ['&', '∧'], ['#', '⊥'], ['@', '∀'], ['$', '∃']];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Converts ASCII logical symbols to their Unicode equivalents
|
|
18
|
+
* @param {string} text - Text containing ASCII symbols
|
|
19
|
+
* @returns {string} Text with Unicode symbols
|
|
20
|
+
* @example
|
|
21
|
+
* convertAsciiToSymbols('P -> Q') // Returns 'P → Q'
|
|
22
|
+
* convertAsciiToSymbols('~P /\\ Q') // Returns '¬P ∧ Q'
|
|
23
|
+
* convertAsciiToSymbols('@x P(x)') // Returns '∀x P(x)'
|
|
24
|
+
*/
|
|
25
|
+
export function convertAsciiToSymbols(text) {
|
|
26
|
+
var result = text;
|
|
27
|
+
var _iterator = _createForOfIteratorHelper(SYMBOL_MAPPINGS),
|
|
28
|
+
_step;
|
|
29
|
+
try {
|
|
30
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
31
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
32
|
+
ascii = _step$value[0],
|
|
33
|
+
symbol = _step$value[1];
|
|
34
|
+
var regex = new RegExp(ascii.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
|
|
35
|
+
result = result.replace(regex, symbol);
|
|
36
|
+
}
|
|
37
|
+
} catch (err) {
|
|
38
|
+
_iterator.e(err);
|
|
39
|
+
} finally {
|
|
40
|
+
_iterator.f();
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Converts Unicode logical symbols back to ASCII equivalents
|
|
47
|
+
* @param {string} text - Text containing Unicode symbols
|
|
48
|
+
* @returns {string} Text with ASCII symbols
|
|
49
|
+
* @example
|
|
50
|
+
* convertSymbolsToAscii('P → Q') // Returns 'P -> Q'
|
|
51
|
+
* convertSymbolsToAscii('¬P ∧ Q') // Returns '~P /\\ Q'
|
|
52
|
+
*/
|
|
53
|
+
export function convertSymbolsToAscii(text) {
|
|
54
|
+
var result = text;
|
|
55
|
+
var _iterator2 = _createForOfIteratorHelper(SYMBOL_MAPPINGS),
|
|
56
|
+
_step2;
|
|
57
|
+
try {
|
|
58
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
59
|
+
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
60
|
+
ascii = _step2$value[0],
|
|
61
|
+
symbol = _step2$value[1];
|
|
62
|
+
var regex = new RegExp(symbol.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
|
|
63
|
+
result = result.replace(regex, ascii);
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
_iterator2.e(err);
|
|
67
|
+
} finally {
|
|
68
|
+
_iterator2.f();
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The symbol mappings array for external use
|
|
75
|
+
* @type {Array<[string, string]>}
|
|
76
|
+
*/
|
|
77
|
+
export var symbolMappings = SYMBOL_MAPPINGS;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
var _RULE_REQUIREMENTS;
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
7
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
8
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
9
|
+
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
10
|
+
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
11
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
12
|
+
import { OPERATORS } from './parser.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} Formula
|
|
16
|
+
* @property {string} type - The type of formula ('atomic', 'compound', 'quantified', 'identity', 'splat')
|
|
17
|
+
* @property {string} [operator] - The main logical operator (for compound/quantified formulas)
|
|
18
|
+
* @property {string} [predicate] - The predicate symbol (for atomic formulas)
|
|
19
|
+
* @property {string[]} [terms] - The terms in the formula
|
|
20
|
+
* @property {Formula} [left] - The left subformula (for binary operators)
|
|
21
|
+
* @property {Formula} [right] - The right subformula (for binary operators)
|
|
22
|
+
* @property {string} [variable] - The bound variable (for quantified formulas)
|
|
23
|
+
* @property {Formula} [scope] - The scope of the quantifier (for quantified formulas)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {Object} ProofLine
|
|
28
|
+
* @property {number} lineNum - The line number in the proof
|
|
29
|
+
* @property {Formula} formula - The formula at this line
|
|
30
|
+
* @property {string} rule - The rule applied at this line
|
|
31
|
+
* @property {number[]} citations - Line numbers cited in the justification
|
|
32
|
+
* @property {Array<{start: number, end: number}>} subproofs - Subproof ranges cited
|
|
33
|
+
* @property {string[]} issues - Any issues with this line
|
|
34
|
+
* @property {number[]} location - Array indicating the scope depth
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} Proof
|
|
39
|
+
* @property {ProofLine[]} lines - The lines in the proof
|
|
40
|
+
* @property {number} numPremises - The number of premises
|
|
41
|
+
* @property {Formula} conclusion - The desired conclusion
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {Object} ValidationResult
|
|
46
|
+
* @property {boolean} isValid - Whether the proof is valid
|
|
47
|
+
* @property {string[]} issues - Any issues with the proof
|
|
48
|
+
* @property {boolean} conclusionReached - Whether the conclusion was reached
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Extracts all terms from a formula recursively
|
|
53
|
+
* @param {Formula} formula
|
|
54
|
+
* @returns {string[]}
|
|
55
|
+
*/
|
|
56
|
+
export function getAllTerms(formula) {
|
|
57
|
+
if (!formula) return [];
|
|
58
|
+
switch (formula.type) {
|
|
59
|
+
case 'atomic':
|
|
60
|
+
return formula.terms || [];
|
|
61
|
+
case 'compound':
|
|
62
|
+
if (formula.operator === OPERATORS.NOT) {
|
|
63
|
+
return formula.right ? getAllTerms(formula.right) : [];
|
|
64
|
+
}
|
|
65
|
+
return [].concat(_toConsumableArray(formula.left ? getAllTerms(formula.left) : []), _toConsumableArray(formula.right ? getAllTerms(formula.right) : []));
|
|
66
|
+
case 'quantified':
|
|
67
|
+
if (!formula.scope) return [];
|
|
68
|
+
return getAllTerms(formula.scope).filter(function (t) {
|
|
69
|
+
return t !== formula.variable;
|
|
70
|
+
});
|
|
71
|
+
case 'identity':
|
|
72
|
+
return formula.terms || [];
|
|
73
|
+
default:
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Rule definitions
|
|
79
|
+
export var RULES = {
|
|
80
|
+
// Propositional Logic Rules
|
|
81
|
+
CONJ_INTRO: '∧I',
|
|
82
|
+
CONJ_ELIM: '∧E',
|
|
83
|
+
DISJ_INTRO: '∨I',
|
|
84
|
+
DISJ_ELIM: '∨E',
|
|
85
|
+
COND_INTRO: '→I',
|
|
86
|
+
COND_ELIM: '→E',
|
|
87
|
+
BICOND_INTRO: '↔I',
|
|
88
|
+
BICOND_ELIM: '↔E',
|
|
89
|
+
NEG_INTRO: '¬I',
|
|
90
|
+
NEG_ELIM: '¬E',
|
|
91
|
+
CONTRA_INTRO: '⊥I',
|
|
92
|
+
CONTRA_ELIM: '⊥E',
|
|
93
|
+
LEM: 'LEM',
|
|
94
|
+
// First-Order Logic Rules
|
|
95
|
+
UNIV_INTRO: '∀I',
|
|
96
|
+
UNIV_ELIM: '∀E',
|
|
97
|
+
EXIST_INTRO: '∃I',
|
|
98
|
+
EXIST_ELIM: '∃E',
|
|
99
|
+
ID_INTRO: '=I',
|
|
100
|
+
ID_ELIM: '=E',
|
|
101
|
+
CQ: 'CQ',
|
|
102
|
+
// Structural Rules
|
|
103
|
+
PREMISE: 'Pr',
|
|
104
|
+
HYPOTHESIS: 'Hyp',
|
|
105
|
+
REIT: 'R'
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Rule citation requirements
|
|
109
|
+
export var RULE_REQUIREMENTS = (_RULE_REQUIREMENTS = {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_RULE_REQUIREMENTS, RULES.CONJ_INTRO, {
|
|
110
|
+
lines: 2,
|
|
111
|
+
subproofs: 0
|
|
112
|
+
}), RULES.CONJ_ELIM, {
|
|
113
|
+
lines: 1,
|
|
114
|
+
subproofs: 0
|
|
115
|
+
}), RULES.DISJ_INTRO, {
|
|
116
|
+
lines: 1,
|
|
117
|
+
subproofs: 0
|
|
118
|
+
}), RULES.DISJ_ELIM, {
|
|
119
|
+
lines: 1,
|
|
120
|
+
subproofs: 2
|
|
121
|
+
}), RULES.COND_INTRO, {
|
|
122
|
+
lines: 0,
|
|
123
|
+
subproofs: 1
|
|
124
|
+
}), RULES.COND_ELIM, {
|
|
125
|
+
lines: 2,
|
|
126
|
+
subproofs: 0
|
|
127
|
+
}), RULES.BICOND_INTRO, {
|
|
128
|
+
lines: 0,
|
|
129
|
+
subproofs: 2
|
|
130
|
+
}), RULES.BICOND_ELIM, {
|
|
131
|
+
lines: 2,
|
|
132
|
+
subproofs: 0
|
|
133
|
+
}), RULES.NEG_INTRO, {
|
|
134
|
+
lines: 0,
|
|
135
|
+
subproofs: 1
|
|
136
|
+
}), RULES.NEG_ELIM, {
|
|
137
|
+
lines: 2,
|
|
138
|
+
subproofs: 0
|
|
139
|
+
}), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_RULE_REQUIREMENTS, RULES.CONTRA_INTRO, {
|
|
140
|
+
lines: 2,
|
|
141
|
+
subproofs: 0
|
|
142
|
+
}), RULES.CONTRA_ELIM, {
|
|
143
|
+
lines: 1,
|
|
144
|
+
subproofs: 0
|
|
145
|
+
}), RULES.LEM, {
|
|
146
|
+
lines: 0,
|
|
147
|
+
subproofs: 2
|
|
148
|
+
}), RULES.UNIV_INTRO, {
|
|
149
|
+
lines: 1,
|
|
150
|
+
subproofs: 0
|
|
151
|
+
}), RULES.UNIV_ELIM, {
|
|
152
|
+
lines: 1,
|
|
153
|
+
subproofs: 0
|
|
154
|
+
}), RULES.EXIST_INTRO, {
|
|
155
|
+
lines: 1,
|
|
156
|
+
subproofs: 0
|
|
157
|
+
}), RULES.EXIST_ELIM, {
|
|
158
|
+
lines: 1,
|
|
159
|
+
subproofs: 1
|
|
160
|
+
}), RULES.ID_INTRO, {
|
|
161
|
+
lines: 0,
|
|
162
|
+
subproofs: 0
|
|
163
|
+
}), RULES.ID_ELIM, {
|
|
164
|
+
lines: 2,
|
|
165
|
+
subproofs: 0
|
|
166
|
+
}), RULES.CQ, {
|
|
167
|
+
lines: 1,
|
|
168
|
+
subproofs: 0
|
|
169
|
+
}), _defineProperty(_defineProperty(_defineProperty(_RULE_REQUIREMENTS, RULES.PREMISE, {
|
|
170
|
+
lines: 0,
|
|
171
|
+
subproofs: 0
|
|
172
|
+
}), RULES.HYPOTHESIS, {
|
|
173
|
+
lines: 0,
|
|
174
|
+
subproofs: 0
|
|
175
|
+
}), RULES.REIT, {
|
|
176
|
+
lines: 1,
|
|
177
|
+
subproofs: 0
|
|
178
|
+
}));
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fitch-js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A JavaScript library for validating Fitch-style natural deduction proofs",
|
|
5
|
+
"main": "dist/cjs/index.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/esm/index.js",
|
|
11
|
+
"require": "./dist/cjs/index.js",
|
|
12
|
+
"types": "./dist/types/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"test:watch": "jest --watch",
|
|
22
|
+
"build": "npm run build:clean && npm run build:cjs && npm run build:esm",
|
|
23
|
+
"build:clean": "rm -rf dist",
|
|
24
|
+
"build:cjs": "BABEL_ENV=cjs babel src -d dist/cjs --extensions '.js,.ts'",
|
|
25
|
+
"build:esm": "BABEL_ENV=esm babel src -d dist/esm --extensions '.js,.ts'",
|
|
26
|
+
"prepare": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"logic",
|
|
30
|
+
"proof",
|
|
31
|
+
"fitch",
|
|
32
|
+
"natural-deduction",
|
|
33
|
+
"validation"
|
|
34
|
+
],
|
|
35
|
+
"author": "",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@babel/cli": "^7.23.9",
|
|
39
|
+
"@babel/core": "^7.23.9",
|
|
40
|
+
"@babel/preset-env": "^7.23.9",
|
|
41
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
42
|
+
"jest": "^29.7.0",
|
|
43
|
+
"typescript": "^5.3.3"
|
|
44
|
+
}
|
|
45
|
+
}
|