unicode-logic-kit 0.31.0__py3-none-any.whl

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 (237) hide show
  1. unicode_logic_kit/__init__.py +385 -0
  2. unicode_logic_kit/__main__.py +520 -0
  3. unicode_logic_kit/_deadline.py +219 -0
  4. unicode_logic_kit/ace/__init__.py +126 -0
  5. unicode_logic_kit/ace/_align.py +135 -0
  6. unicode_logic_kit/ace/chem_lexicon.py +128 -0
  7. unicode_logic_kit/ace/drs_reader.py +570 -0
  8. unicode_logic_kit/ace/mapping.py +666 -0
  9. unicode_logic_kit/ace/reverse_modal.py +138 -0
  10. unicode_logic_kit/ace/runner.py +551 -0
  11. unicode_logic_kit/ace/translate.py +452 -0
  12. unicode_logic_kit/ace/verbalize.py +1070 -0
  13. unicode_logic_kit/api.py +1284 -0
  14. unicode_logic_kit/atp/__init__.py +177 -0
  15. unicode_logic_kit/atp/_ascii_names.py +113 -0
  16. unicode_logic_kit/atp/_html.py +72 -0
  17. unicode_logic_kit/atp/_substructural_input.py +228 -0
  18. unicode_logic_kit/atp/_tff_problem.py +715 -0
  19. unicode_logic_kit/atp/_tptp_problem.py +1111 -0
  20. unicode_logic_kit/atp/_writer_support.py +289 -0
  21. unicode_logic_kit/atp/clingo_backend.py +1180 -0
  22. unicode_logic_kit/atp/cvc5_backend.py +1385 -0
  23. unicode_logic_kit/atp/eprover_backend.py +732 -0
  24. unicode_logic_kit/atp/finite_domain.py +1055 -0
  25. unicode_logic_kit/atp/fitch.py +1547 -0
  26. unicode_logic_kit/atp/fitch_search.py +551 -0
  27. unicode_logic_kit/atp/hets_backend.py +339 -0
  28. unicode_logic_kit/atp/hybrid_down.py +120 -0
  29. unicode_logic_kit/atp/incremental.py +250 -0
  30. unicode_logic_kit/atp/kripke_enum.py +741 -0
  31. unicode_logic_kit/atp/lambek.py +436 -0
  32. unicode_logic_kit/atp/leo3_backend.py +332 -0
  33. unicode_logic_kit/atp/linear.py +738 -0
  34. unicode_logic_kit/atp/lj.py +705 -0
  35. unicode_logic_kit/atp/logic_backends.py +566 -0
  36. unicode_logic_kit/atp/ltl_tableau.py +1084 -0
  37. unicode_logic_kit/atp/minizinc_backend.py +1402 -0
  38. unicode_logic_kit/atp/modal_tableau.py +1382 -0
  39. unicode_logic_kit/atp/nanocop_backend.py +410 -0
  40. unicode_logic_kit/atp/portfolio.py +489 -0
  41. unicode_logic_kit/atp/protocol.py +1803 -0
  42. unicode_logic_kit/atp/prover9_entailment.py +1153 -0
  43. unicode_logic_kit/atp/resolution.py +1376 -0
  44. unicode_logic_kit/atp/resolution_check.py +1114 -0
  45. unicode_logic_kit/atp/sequent.py +1050 -0
  46. unicode_logic_kit/atp/tableau.py +921 -0
  47. unicode_logic_kit/atp/tableau_check.py +543 -0
  48. unicode_logic_kit/atp/tptp_ncl.py +811 -0
  49. unicode_logic_kit/atp/tptp_tff.py +1546 -0
  50. unicode_logic_kit/atp/tstp.py +1333 -0
  51. unicode_logic_kit/atp/tstp_check.py +1096 -0
  52. unicode_logic_kit/atp/twee_backend.py +236 -0
  53. unicode_logic_kit/atp/twee_check.py +711 -0
  54. unicode_logic_kit/atp/twee_entailment.py +953 -0
  55. unicode_logic_kit/atp/vampire_entailment.py +540 -0
  56. unicode_logic_kit/atp/z3_arith.py +470 -0
  57. unicode_logic_kit/atp/z3_equivalence.py +36 -0
  58. unicode_logic_kit/atp/z3_fuzzy.py +362 -0
  59. unicode_logic_kit/atp/z3_input.py +500 -0
  60. unicode_logic_kit/atp/z3_models.py +208 -0
  61. unicode_logic_kit/chem/__init__.py +88 -0
  62. unicode_logic_kit/chem/_naming.py +284 -0
  63. unicode_logic_kit/chem/cache.py +185 -0
  64. unicode_logic_kit/chem/interop.py +244 -0
  65. unicode_logic_kit/chem/mol.py +525 -0
  66. unicode_logic_kit/chem/signature.py +112 -0
  67. unicode_logic_kit/comorphism.py +497 -0
  68. unicode_logic_kit/dl/__init__.py +384 -0
  69. unicode_logic_kit/dl/classification.py +227 -0
  70. unicode_logic_kit/dl/concepts.py +632 -0
  71. unicode_logic_kit/dl/datatypes.py +818 -0
  72. unicode_logic_kit/dl/owl_functional.py +2433 -0
  73. unicode_logic_kit/dl/owl_manchester.py +1637 -0
  74. unicode_logic_kit/dl/owl_reasoner.py +790 -0
  75. unicode_logic_kit/dl/parser.py +391 -0
  76. unicode_logic_kit/dl/tableau.py +4048 -0
  77. unicode_logic_kit/dl/translate.py +2704 -0
  78. unicode_logic_kit/drt/__init__.py +94 -0
  79. unicode_logic_kit/drt/export.py +179 -0
  80. unicode_logic_kit/drt/nodes.py +506 -0
  81. unicode_logic_kit/drt/parser.py +965 -0
  82. unicode_logic_kit/drt/resolve.py +195 -0
  83. unicode_logic_kit/drt/reverse.py +175 -0
  84. unicode_logic_kit/eval/__init__.py +106 -0
  85. unicode_logic_kit/eval/batch.py +382 -0
  86. unicode_logic_kit/eval/canonical.py +663 -0
  87. unicode_logic_kit/eval/chem_batch.py +606 -0
  88. unicode_logic_kit/eval/converses.py +200 -0
  89. unicode_logic_kit/eval/datasets/__init__.py +136 -0
  90. unicode_logic_kit/eval/datasets/_base.py +263 -0
  91. unicode_logic_kit/eval/datasets/_proofwriter_proof.py +422 -0
  92. unicode_logic_kit/eval/datasets/c3po.py +678 -0
  93. unicode_logic_kit/eval/datasets/folio.py +158 -0
  94. unicode_logic_kit/eval/datasets/fracas.py +418 -0
  95. unicode_logic_kit/eval/datasets/groves.py +191 -0
  96. unicode_logic_kit/eval/datasets/logicbench.py +467 -0
  97. unicode_logic_kit/eval/datasets/logicnli.py +303 -0
  98. unicode_logic_kit/eval/datasets/malls.py +133 -0
  99. unicode_logic_kit/eval/datasets/pfolio.py +594 -0
  100. unicode_logic_kit/eval/datasets/pmb.py +242 -0
  101. unicode_logic_kit/eval/datasets/prontoqa.py +611 -0
  102. unicode_logic_kit/eval/datasets/proofwriter.py +1431 -0
  103. unicode_logic_kit/eval/datasets/proverqa.py +674 -0
  104. unicode_logic_kit/eval/datasets/willow.py +478 -0
  105. unicode_logic_kit/eval/equivalence.py +466 -0
  106. unicode_logic_kit/eval/exercise_gen.py +533 -0
  107. unicode_logic_kit/eval/explain.py +791 -0
  108. unicode_logic_kit/eval/generality.py +750 -0
  109. unicode_logic_kit/eval/metric_hf.py +458 -0
  110. unicode_logic_kit/eval/predicate_match.py +343 -0
  111. unicode_logic_kit/eval/theory_check.py +1170 -0
  112. unicode_logic_kit/eval/validate.py +306 -0
  113. unicode_logic_kit/fol/__init__.py +177 -0
  114. unicode_logic_kit/fol/_atom_keys.py +510 -0
  115. unicode_logic_kit/fol/_fol_nodes.py +3586 -0
  116. unicode_logic_kit/fol/_free_parameters.py +105 -0
  117. unicode_logic_kit/fol/_ho_nodes.py +448 -0
  118. unicode_logic_kit/fol/_hybrid_nodes.py +308 -0
  119. unicode_logic_kit/fol/_identifiers.py +1091 -0
  120. unicode_logic_kit/fol/_lambek_nodes.py +112 -0
  121. unicode_logic_kit/fol/_linear_nodes.py +352 -0
  122. unicode_logic_kit/fol/_modal_nodes.py +1467 -0
  123. unicode_logic_kit/fol/_msfl_nodes.py +2196 -0
  124. unicode_logic_kit/fol/_numeral_symbols.py +231 -0
  125. unicode_logic_kit/fol/_so_nodes.py +200 -0
  126. unicode_logic_kit/fol/_symbol_names.py +81 -0
  127. unicode_logic_kit/fol/_team_nodes.py +181 -0
  128. unicode_logic_kit/fol/_tptp_symbols.py +551 -0
  129. unicode_logic_kit/fol/_truth_constants.py +117 -0
  130. unicode_logic_kit/fol/casl_export.py +1135 -0
  131. unicode_logic_kit/fol/casl_import.py +929 -0
  132. unicode_logic_kit/fol/derivation.py +367 -0
  133. unicode_logic_kit/fol/dialect_detect.py +70 -0
  134. unicode_logic_kit/fol/dialect_repair.py +537 -0
  135. unicode_logic_kit/fol/frames.py +637 -0
  136. unicode_logic_kit/fol/grammars/terminals.lark +31 -0
  137. unicode_logic_kit/fol/lambda_tools.py +297 -0
  138. unicode_logic_kit/fol/latex_input.py +429 -0
  139. unicode_logic_kit/fol/modal_translation.py +944 -0
  140. unicode_logic_kit/fol/msflparser.py +1033 -0
  141. unicode_logic_kit/fol/naming.py +422 -0
  142. unicode_logic_kit/fol/nodes.py +241 -0
  143. unicode_logic_kit/fol/normalforms.py +492 -0
  144. unicode_logic_kit/fol/pal.py +287 -0
  145. unicode_logic_kit/fol/prolog_export.py +566 -0
  146. unicode_logic_kit/fol/prolog_input.py +505 -0
  147. unicode_logic_kit/fol/prover9_input.py +1325 -0
  148. unicode_logic_kit/fol/qml.py +1760 -0
  149. unicode_logic_kit/fol/qmltp_input.py +525 -0
  150. unicode_logic_kit/fol/sanitize.py +221 -0
  151. unicode_logic_kit/fol/serialize.py +79 -0
  152. unicode_logic_kit/fol/signature.py +1290 -0
  153. unicode_logic_kit/fol/simplify_check.py +544 -0
  154. unicode_logic_kit/fol/spans.py +594 -0
  155. unicode_logic_kit/fol/tptp_input.py +1503 -0
  156. unicode_logic_kit/fol/tptp_repair.py +941 -0
  157. unicode_logic_kit/fol/unification.py +157 -0
  158. unicode_logic_kit/fol/verbalize.py +263 -0
  159. unicode_logic_kit/hets/__init__.py +163 -0
  160. unicode_logic_kit/hets/bridge.py +142 -0
  161. unicode_logic_kit/hets/client.py +748 -0
  162. unicode_logic_kit/hets/docker.py +420 -0
  163. unicode_logic_kit/hets/dol.py +712 -0
  164. unicode_logic_kit/hets/haskell_json.py +355 -0
  165. unicode_logic_kit/hets/owl_backend.py +794 -0
  166. unicode_logic_kit/hets/owl_cli.py +598 -0
  167. unicode_logic_kit/hets/symbols.py +512 -0
  168. unicode_logic_kit/hol/__init__.py +140 -0
  169. unicode_logic_kit/hol/_ho_common.py +323 -0
  170. unicode_logic_kit/hol/_isabelle_binders.py +125 -0
  171. unicode_logic_kit/hol/classical.py +812 -0
  172. unicode_logic_kit/hol/deepshallow/__init__.py +45 -0
  173. unicode_logic_kit/hol/deepshallow/_common.py +177 -0
  174. unicode_logic_kit/hol/deepshallow/conditional.py +225 -0
  175. unicode_logic_kit/hol/deepshallow/intuitionistic.py +181 -0
  176. unicode_logic_kit/hol/deepshallow/modal.py +217 -0
  177. unicode_logic_kit/hol/deepshallow/qml.py +406 -0
  178. unicode_logic_kit/hol/deepshallow/relevant.py +206 -0
  179. unicode_logic_kit/hol/free.py +753 -0
  180. unicode_logic_kit/hol/goedel.py +336 -0
  181. unicode_logic_kit/hol/ho_modal.py +1743 -0
  182. unicode_logic_kit/hol/intuitionistic.py +403 -0
  183. unicode_logic_kit/hol/isabelle_conditional.py +593 -0
  184. unicode_logic_kit/hol/isabelle_modal.py +1908 -0
  185. unicode_logic_kit/hol/isabelle_relevant.py +412 -0
  186. unicode_logic_kit/hol/isabelle_runner.py +1147 -0
  187. unicode_logic_kit/hol/isabelle_substructural.py +884 -0
  188. unicode_logic_kit/hol/lean.py +1018 -0
  189. unicode_logic_kit/hol/manyvalued.py +921 -0
  190. unicode_logic_kit/hol/secondorder.py +687 -0
  191. unicode_logic_kit/hol/thf_modal.py +941 -0
  192. unicode_logic_kit/hol/thirdorder.py +397 -0
  193. unicode_logic_kit/ilp/__init__.py +89 -0
  194. unicode_logic_kit/ilp/readback.py +389 -0
  195. unicode_logic_kit/ilp/separation.py +153 -0
  196. unicode_logic_kit/ilp/task.py +730 -0
  197. unicode_logic_kit/logic.py +163 -0
  198. unicode_logic_kit/mcp/__init__.py +28 -0
  199. unicode_logic_kit/mcp/__main__.py +5 -0
  200. unicode_logic_kit/mcp/chem_tools.py +1031 -0
  201. unicode_logic_kit/mcp/server.py +2453 -0
  202. unicode_logic_kit/mcp/syntax_spec.py +681 -0
  203. unicode_logic_kit/prob/__init__.py +53 -0
  204. unicode_logic_kit/prob/_bdd.py +225 -0
  205. unicode_logic_kit/prob/_column_gen.py +668 -0
  206. unicode_logic_kit/prob/distribution.py +686 -0
  207. unicode_logic_kit/prob/nilsson.py +470 -0
  208. unicode_logic_kit/py.typed +0 -0
  209. unicode_logic_kit/semantics/__init__.py +137 -0
  210. unicode_logic_kit/semantics/_modal_reject.py +156 -0
  211. unicode_logic_kit/semantics/action_models.py +466 -0
  212. unicode_logic_kit/semantics/asp_models.py +1200 -0
  213. unicode_logic_kit/semantics/conditional.py +580 -0
  214. unicode_logic_kit/semantics/dynamic_epistemic.py +95 -0
  215. unicode_logic_kit/semantics/free_logic.py +913 -0
  216. unicode_logic_kit/semantics/fuzzy.py +384 -0
  217. unicode_logic_kit/semantics/fuzzy_kripke.py +442 -0
  218. unicode_logic_kit/semantics/intuitionistic.py +581 -0
  219. unicode_logic_kit/semantics/kripke.py +1139 -0
  220. unicode_logic_kit/semantics/manyvalued.py +580 -0
  221. unicode_logic_kit/semantics/matrix.py +342 -0
  222. unicode_logic_kit/semantics/model_eval.py +1135 -0
  223. unicode_logic_kit/semantics/modelfinder.py +1036 -0
  224. unicode_logic_kit/semantics/nonmonotonic.py +372 -0
  225. unicode_logic_kit/semantics/relevant.py +331 -0
  226. unicode_logic_kit/semantics/secondorder.py +657 -0
  227. unicode_logic_kit/semantics/structures.py +352 -0
  228. unicode_logic_kit/semantics/tarski.py +975 -0
  229. unicode_logic_kit/semantics/team.py +315 -0
  230. unicode_logic_kit/semantics/team_translation.py +416 -0
  231. unicode_logic_kit/semantics/thirdorder.py +358 -0
  232. unicode_logic_kit/semantics/tnorm.py +85 -0
  233. unicode_logic_kit/semantics/truthtable.py +201 -0
  234. unicode_logic_kit-0.31.0.dist-info/METADATA +333 -0
  235. unicode_logic_kit-0.31.0.dist-info/RECORD +237 -0
  236. unicode_logic_kit-0.31.0.dist-info/WHEEL +4 -0
  237. unicode_logic_kit-0.31.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,181 @@
1
+ """Dependence-logic / IF-logic node classes and the ``dependence`` parser mode.
2
+
3
+ Dependence logic (Väänänen 2007) and independence-friendly (IF) logic extend
4
+ first-order syntax with constructs whose meaning lives in TEAM SEMANTICS — a
5
+ formula is satisfied by a SET of assignments (a team), not a single one:
6
+
7
+ - the **dependence atom** ``=(t₁, …, tₙ)``: in the current team, the value of
8
+ ``tₙ`` is functionally determined by the values of ``t₁ … tₙ₋₁``
9
+ (``=(t)`` with one argument is the constancy atom: ``t`` has the same value
10
+ under every assignment of the team);
11
+ - the **slashed existential** ``∃x/{y, …} φ`` (IF logic): a witness for ``x``
12
+ is chosen UNIFORMLY IN — i.e. independently of — the listed variables.
13
+
14
+ The ``dependence`` mode (``MSFLParser(dependence=True)``) is classical unsorted
15
+ FOL syntax restricted to the team-friendly fragment: literals, ``∧``, ``∨``
16
+ (read as the SPLITTING disjunction), ``∀`` / ``∃``, plus the two constructs
17
+ above. ``→`` / ``↔`` are deliberately absent — they have no faithful team
18
+ semantics in this fragment. Evaluation lives in
19
+ ``unicode_logic_kit.semantics.team`` (``team_satisfies`` / ``team_models``);
20
+ dependence logic captures existential second-order logic, so there is no
21
+ classical export: ``to_z3`` / ``to_prover9`` / ``to_tptp`` reject.
22
+ """
23
+
24
+ from dataclasses import dataclass
25
+ from typing import Tuple
26
+
27
+ from ._fol_nodes import (
28
+ Node, Z3Env, Variable, Not, And, Or, Quantifier,
29
+ NODE_CLASSES, register_parser_op, _fold_binary,
30
+ )
31
+
32
+ # Shared rejection message: team-semantic constructs have no classical export.
33
+ _NO_TEAM_EXPORT = (
34
+ "Dependence/IF constructs (=(…) dependence atoms, slashed quantifiers) have "
35
+ "team semantics — a formula is satisfied by a SET of assignments — and are "
36
+ "expressively second-order, so they have no classical first-order export. "
37
+ "Evaluate with unicode_logic_kit.team_satisfies / team_models over a finite "
38
+ "Structure."
39
+ )
40
+
41
+
42
+ @dataclass(frozen=True)
43
+ class Dependence(Node):
44
+ """A dependence atom ``=(t₁, …, tₙ)``: ``tₙ`` is determined by ``t₁ … tₙ₋₁``.
45
+
46
+ ``args`` is a non-empty tuple of terms; the LAST is the dependent one. A
47
+ team X satisfies it iff any two assignments in X that agree on
48
+ ``t₁ … tₙ₋₁`` also agree on ``tₙ``. With a single argument, ``=(t)`` is the
49
+ CONSTANCY atom: ``t`` takes one fixed value across the whole team.
50
+ """
51
+
52
+ args: Tuple[Node, ...]
53
+
54
+ def __post_init__(self):
55
+ """Coerce the args to a tuple and require at least one term."""
56
+ object.__setattr__(self, "args", tuple(self.args))
57
+ if len(self.args) < 1:
58
+ raise ValueError("Dependence: =(…) needs at least one term.")
59
+
60
+ def _tree_parts(self):
61
+ """Return the =(…) label and the term children."""
62
+ return "=(…)", list(self.args)
63
+
64
+ def to_dict(self):
65
+ """Serialise to dict with the recursively serialised terms."""
66
+ return {"_type": "Dependence", "args": [a.to_dict() for a in self.args]}
67
+
68
+ @staticmethod
69
+ def from_dict(d):
70
+ """Deserialise a Dependence from a dict produced by to_dict."""
71
+ return Dependence(tuple(Node.from_dict(a) for a in d["args"]))
72
+
73
+ def to_z3(self, env: Z3Env = None):
74
+ """Reject Z3 export: dependence atoms are team-semantic."""
75
+ raise NotImplementedError(_NO_TEAM_EXPORT)
76
+
77
+ def to_prover9(self) -> str:
78
+ """Reject Prover9 export: dependence atoms are team-semantic."""
79
+ raise NotImplementedError(_NO_TEAM_EXPORT)
80
+
81
+ def to_tptp(self) -> str:
82
+ """Reject TPTP export: dependence atoms are team-semantic."""
83
+ raise NotImplementedError(_NO_TEAM_EXPORT)
84
+
85
+
86
+ @dataclass(frozen=True)
87
+ class SlashedExists(Node):
88
+ """An IF-logic slashed existential ``∃x/{y, …} φ``.
89
+
90
+ Binds ``variable`` over ``formula``; the witness for ``x`` must be chosen
91
+ UNIFORMLY IN the variables listed in ``slashed`` (a tuple of names bound by
92
+ ENCLOSING quantifiers): two team assignments that agree on everything
93
+ except the slashed variables receive the same witness. Only the
94
+ existential is slashed (a slashed universal adds nothing in this
95
+ fragment).
96
+ """
97
+
98
+ variable: Variable
99
+ slashed: Tuple[str, ...]
100
+ formula: Node
101
+
102
+ def __post_init__(self):
103
+ """Coerce the slashed list to a tuple of names and validate it."""
104
+ names = tuple(v.name if isinstance(v, Variable) else str(v)
105
+ for v in self.slashed)
106
+ object.__setattr__(self, "slashed", names)
107
+ if len(names) < 1:
108
+ raise ValueError("SlashedExists: the slash set must name at least "
109
+ "one variable (∃x/{y} …).")
110
+
111
+ def _tree_parts(self):
112
+ """Return the slashed-∃ label (with variable and slash set) and the matrix."""
113
+ return f"∃{self.variable.name}/{{{', '.join(self.slashed)}}}", [self.formula]
114
+
115
+ def to_dict(self):
116
+ """Serialise to dict with the bound variable, slash set, and matrix."""
117
+ return {"_type": "SlashedExists", "variable": self.variable.to_dict(),
118
+ "slashed": list(self.slashed), "formula": self.formula.to_dict()}
119
+
120
+ @staticmethod
121
+ def from_dict(d):
122
+ """Deserialise a SlashedExists from a dict produced by to_dict."""
123
+ return SlashedExists(Node.from_dict(d["variable"]), tuple(d["slashed"]),
124
+ Node.from_dict(d["formula"]))
125
+
126
+ def to_z3(self, env: Z3Env = None):
127
+ """Reject Z3 export: slashed quantifiers are team-semantic."""
128
+ raise NotImplementedError(_NO_TEAM_EXPORT)
129
+
130
+ def to_prover9(self) -> str:
131
+ """Reject Prover9 export: slashed quantifiers are team-semantic."""
132
+ raise NotImplementedError(_NO_TEAM_EXPORT)
133
+
134
+ def to_tptp(self) -> str:
135
+ """Reject TPTP export: slashed quantifiers are team-semantic."""
136
+ raise NotImplementedError(_NO_TEAM_EXPORT)
137
+
138
+
139
+ NODE_CLASSES.update({"Dependence": Dependence, "SlashedExists": SlashedExists})
140
+
141
+
142
+ # =========================
143
+ # Parser registration — the "dependence" mode
144
+ # =========================
145
+ #
146
+ # Classical unsorted FOL syntax restricted to the team-friendly fragment:
147
+ # ¬ (semantically honest on atoms only — the evaluator enforces that), the
148
+ # splitting ∨ and ∧ (same-level, no mixing), plain ∀/∃, the dependence atom
149
+ # =(…), and the slashed ∃x/{y,…}. Deliberately NO → / ↔ / ⊕.
150
+
151
+ register_parser_op(Not, "dependence", "prefix", "not_", '"¬" prefix',
152
+ lambda items: Not(items[0]))
153
+ register_parser_op(And, "dependence", "level2", "and_", '"∧"',
154
+ lambda items: _fold_binary(items, And), only_name="only_and")
155
+ register_parser_op(Or, "dependence", "level2", "or_", '"∨"',
156
+ lambda items: _fold_binary(items, Or), only_name="only_or")
157
+ register_parser_op(Quantifier, "dependence", "quantifier", "quantifier_",
158
+ "(FORALL | EXISTS) VARIABLE prefix",
159
+ lambda items: Quantifier(str(items[0]), items[1], items[2]))
160
+
161
+
162
+ def _dep_transform(items):
163
+ """Build a Dependence atom from the parenthesised termlist of =(…)."""
164
+ args = items[0] if items and isinstance(items[0], list) else list(items)
165
+ return Dependence(tuple(args))
166
+
167
+
168
+ def _slashed_transform(items):
169
+ """Build a SlashedExists from [EXISTS, Variable, slashed Variables…, body]."""
170
+ variable = items[1]
171
+ slashed = tuple(v.name for v in items[2:-1])
172
+ return SlashedExists(variable, slashed, items[-1])
173
+
174
+
175
+ # The '=(' form cannot collide with the infix 'term = term' atom: infix equality
176
+ # requires a term BEFORE the '='.
177
+ register_parser_op(Dependence, "dependence", "prefix", "dep_",
178
+ '"=" "(" termlist ")"', _dep_transform)
179
+ register_parser_op(SlashedExists, "dependence", "quantifier", "slashed_",
180
+ 'EXISTS VARIABLE "/" "{" VARIABLE ("," VARIABLE)* "}" prefix',
181
+ _slashed_transform)