Skip to content

Commit 161f3b8

Browse files
committed
Read operator data from operator JSON tables
1 parent e715104 commit 161f3b8

File tree

2 files changed

+36
-170
lines changed

2 files changed

+36
-170
lines changed

mathics/core/parser/operators.py

Lines changed: 19 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
2+
"""Mathics3 Operator tables.
3+
4+
This information is controlled by data from the MathicsScanner Project,
5+
from YAML tables which are converted to JSON.
6+
7+
The dictionary from these which are read in here, are used by the
8+
Mathics3 parser.
9+
"""
310

411

512
import os.path as osp
@@ -12,169 +19,23 @@
1219
except ImportError:
1320
import json as ujson # type: ignore[no-redef]
1421

15-
# Load the conversion tables from disk
22+
# Load Mathics3 operator information from JSON. This file is derived from a
23+
# Mathics3 Operator Data YAML file in MathicsScanner.
1624
operator_tables_path = osp.join(ROOT_DIR, "data", "operator-tables.json")
1725
assert osp.exists(
1826
operator_tables_path
19-
), f"Internal error: Operator precedence tables are missing; expected to be in {operator_tables_path}"
27+
), f"Internal error: Mathics3 Operator information are missing; expected to be in {operator_tables_path}"
2028
with open(operator_tables_path, "r") as f:
2129
OPERATOR_DATA = ujson.load(f)
2230

23-
24-
prefix_ops = {
25-
"Get": 720,
26-
"PreIncrement": 660,
27-
"PreDecrement": 660,
28-
"Del": 550,
29-
"Minus": 480,
30-
"Square": 540,
31-
"ForAll": 240,
32-
"Exists": 240,
33-
"NotExists": 240,
34-
"Not": 230,
35-
"Information": 5001,
36-
"Definition": 5000,
37-
"InterpretedBox": 670,
38-
}
39-
40-
postfix_ops = {
41-
"Unset": 670,
42-
"Conjugate": 670,
43-
"Transpose": 670,
44-
"ConjugateTranspose": 670,
45-
"Derivative": 670,
46-
"Increment": 660,
47-
"Decrement": 660,
48-
"Factorial": 610,
49-
"Factorial2": 610,
50-
"Repeated": 170,
51-
"RepeatedNull": 170,
52-
"Function": 90,
53-
}
54-
55-
left_binary_ops = {
56-
"Divide": 470,
57-
"PlusMinus": 310,
58-
"MinusPlus": 310,
59-
"Subtract": 310,
60-
"LeftTee": 190,
61-
"DoubleLeftTee": 190,
62-
"Condition": 130,
63-
"ReplaceAll": 110,
64-
"ReplaceRepeated": 110,
65-
"Because": 50,
66-
"PutAppend": 30,
67-
"Put": 30,
68-
"Postfix": 70,
69-
}
70-
71-
right_binary_ops = {
72-
"Apply": 620,
73-
"Map": 620,
74-
"MapAll": 620,
75-
"Power": 590,
76-
"Implies": 200,
77-
"RightTee": 190,
78-
"DoubleRightTee": 190,
79-
"SuchThat": 180,
80-
"Rule": 120,
81-
"RuleDelayed": 120,
82-
"AddTo": 100,
83-
"SubtractFrom": 100,
84-
"TimesBy": 100,
85-
"DivideBy": 100,
86-
"Therefore": 50,
87-
"UpSet": 40,
88-
"Set": 40,
89-
"SetDelayed": 40,
90-
"UpSetDelayed": 40,
91-
}
92-
93-
flat_binary_ops = {
94-
"MessageName": 750,
95-
"Composition": 625,
96-
"StringJoin": 600,
97-
"SmallCircle": 530,
98-
"CircleDot": 520,
99-
"NonCommutativeMultiply": 510,
100-
"Cross": 500,
101-
"Union": 300,
102-
"Dot": 490,
103-
"Backslash": 460,
104-
"Diamond": 450,
105-
"Wedge": 440,
106-
"Vee": 430,
107-
"CircleTimes": 420,
108-
"CenterDot": 410,
109-
"Times": 400,
110-
"VerticalTilde": 370,
111-
"Coproduct": 360,
112-
"Cap": 350,
113-
"Cup": 340,
114-
"Star": 390,
115-
"CirclePlus": 330,
116-
"CircleMinus": 330,
117-
"Plus": 310,
118-
"Intersection": 305,
119-
"VerticalBar": 280,
120-
"NotVerticalBar": 280,
121-
"DoubleVerticalBar": 280,
122-
"NotDoubleVerticalBar": 280,
123-
"SameQ": 290,
124-
"UnsameQ": 290,
125-
"Equal": 290,
126-
"Unequal": 290,
127-
"Greater": 290,
128-
"Less": 290,
129-
"GreaterEqual": 290,
130-
"LessEqual": 290,
131-
"Element": 250,
132-
"NotElement": 250,
133-
"Subset": 250,
134-
"Superset": 250,
135-
# HACK: although the should be 215 for all boolean_ops we adjust slightly
136-
# to get the subprecedences correct
137-
"And": 225,
138-
"Nand": 225,
139-
"Xor": 220,
140-
"Xnor": 220,
141-
"Or": 215,
142-
"Nor": 215,
143-
"Equivalent": 205,
144-
"Alternatives": 160,
145-
"StringExpression": 135,
146-
"Colon": 80,
147-
"VerticalSeparator": 60,
148-
"CompoundExpression": 10,
149-
}
150-
151-
nonassoc_binary_ops = {
152-
"UndirectedEdge": 120,
153-
"DirectedEdge": 128,
154-
"PatternTest": 680,
155-
}
156-
157-
ternary_ops = {
158-
"Span": 305,
159-
"Infix": 630,
160-
}
161-
162-
misc_ops = {
163-
"DifferentialD": 550,
164-
"Sum": 320,
165-
"Pattern": 150,
166-
"Optional": 140,
167-
"SqrtBox": 670,
168-
"RadicalBox": 670,
169-
"FractionBox": 670,
170-
"OverscriptBox": 710,
171-
"UnderscriptBox": 710,
172-
"SubscriptBox": 695,
173-
"FormBox": 670,
174-
"SuperscriptBox": 590,
175-
"UnderoverscriptBox": 700,
176-
"SubsuperscriptBox": 690,
177-
}
31+
flat_binary_ops = OPERATOR_DATA["flat-binary-operators"]
32+
left_binary_ops = OPERATOR_DATA["left-binary-operators"]
33+
misc_ops = OPERATOR_DATA["miscellaneous-operators"]
34+
nonassoc_binary_ops = OPERATOR_DATA["non-associative-binary-operators"]
35+
postfix_ops = OPERATOR_DATA["postfix-operators"]
36+
prefix_ops = OPERATOR_DATA["prefix-operators"]
37+
right_binary_ops = OPERATOR_DATA["right-binary-operators"]
38+
ternary_ops = OPERATOR_DATA["ternary-operators"]
17839

17940
inequality_ops = ["Less", "LessEqual", "Greater", "GreaterEqual", "Equal", "Unequal"]
18041

mathics/core/parser/parser.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
flat_binary_ops,
3636
inequality_ops,
3737
left_binary_ops,
38-
misc_ops,
3938
nonassoc_binary_ops,
4039
postfix_ops,
4140
prefix_ops,
@@ -761,6 +760,12 @@ def e_Divide(self, expr1, token: Token, p: int):
761760

762761
def e_Alternatives(self, expr1, token: Token, p: int) -> Optional[Node]:
763762
q = flat_binary_ops["Alternatives"]
763+
try:
764+
q < p
765+
except:
766+
from trepan.api import debug
767+
768+
debug()
764769
if q < p:
765770
return None
766771
self.consume()
@@ -795,7 +800,7 @@ def b_SqrtBox(self, box0, token: Token, p: int) -> Optional[Node]:
795800
if box0 is not None:
796801
return None
797802
self.consume()
798-
q = misc_ops["SqrtBox"]
803+
q = all_ops["SqrtBox"]
799804
box1 = self.parse_box(q)
800805
if self.next().tag == "OtherscriptBox":
801806
self.consume()
@@ -805,7 +810,7 @@ def b_SqrtBox(self, box0, token: Token, p: int) -> Optional[Node]:
805810
return Node("SqrtBox", box1)
806811

807812
def b_SuperscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
808-
q = misc_ops["SuperscriptBox"]
813+
q = all_ops["SuperscriptBox"]
809814
if q < p:
810815
return None
811816
if box1 is None:
@@ -814,13 +819,13 @@ def b_SuperscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
814819
box2 = self.parse_box(q)
815820
if self.next().tag == "OtherscriptBox":
816821
self.consume()
817-
box3 = self.parse_box(misc_ops["SubsuperscriptBox"])
822+
box3 = self.parse_box(all_ops["SubsuperscriptBox"])
818823
return Node("SubsuperscriptBox", box1, box3, box2)
819824
else:
820825
return Node("SuperscriptBox", box1, box2)
821826

822827
def b_SubscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
823-
q = misc_ops["SubscriptBox"]
828+
q = all_ops["SubscriptBox"]
824829
if q < p:
825830
return None
826831
if box1 is None:
@@ -829,13 +834,13 @@ def b_SubscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
829834
box2 = self.parse_box(q)
830835
if self.next().tag == "OtherscriptBox":
831836
self.consume()
832-
box3 = self.parse_box(misc_ops["SubsuperscriptBox"])
837+
box3 = self.parse_box(all_ops["SubsuperscriptBox"])
833838
return Node("SubsuperscriptBox", box1, box2, box3)
834839
else:
835840
return Node("SubscriptBox", box1, box2)
836841

837842
def b_UnderscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
838-
q = misc_ops["UnderscriptBox"]
843+
q = all_ops["UnderscriptBox"]
839844
if q < p:
840845
return None
841846
if box1 is None:
@@ -844,13 +849,13 @@ def b_UnderscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
844849
box2 = self.parse_box(q)
845850
if self.next().tag == "OtherscriptBox":
846851
self.consume()
847-
box3 = self.parse_box(misc_ops["UnderoverscriptBox"])
852+
box3 = self.parse_box(all_ops["UnderoverscriptBox"])
848853
return Node("UnderoverscriptBox", box1, box2, box3)
849854
else:
850855
return Node("UnderscriptBox", box1, box2)
851856

852857
def b_FractionBox(self, box1, token: Token, p: int) -> Optional[Node]:
853-
q = misc_ops["FractionBox"]
858+
q = all_ops["FractionBox"]
854859
if q < p:
855860
return None
856861
if box1 is None:
@@ -860,7 +865,7 @@ def b_FractionBox(self, box1, token: Token, p: int) -> Optional[Node]:
860865
return Node("FractionBox", box1, box2)
861866

862867
def b_FormBox(self, box1, token: Token, p: int) -> Optional[Node]:
863-
q = misc_ops["FormBox"]
868+
q = all_ops["FormBox"]
864869
if q < p:
865870
return None
866871
if box1 is None:
@@ -874,7 +879,7 @@ def b_FormBox(self, box1, token: Token, p: int) -> Optional[Node]:
874879
return Node("FormBox", box2, box1)
875880

876881
def b_OverscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
877-
q = misc_ops["OverscriptBox"]
882+
q = all_ops["OverscriptBox"]
878883
if q < p:
879884
return None
880885
if box1 is None:
@@ -883,7 +888,7 @@ def b_OverscriptBox(self, box1, token: Token, p: int) -> Optional[Node]:
883888
box2 = self.parse_box(q)
884889
if self.next().tag == "OtherscriptBox":
885890
self.consume()
886-
box3 = self.parse_box(misc_ops["UnderoverscriptBox"])
891+
box3 = self.parse_box(all_ops["UnderoverscriptBox"])
887892
return Node("UnderoverscriptBox", box1, box3, box2)
888893
else:
889894
return Node("OverscriptBox", box1, box2)

0 commit comments

Comments
 (0)