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.
@@ -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
+ }