Skip to content

Commit d7b33cb

Browse files
committed
Start adding operator precedence
1 parent f617fe8 commit d7b33cb

File tree

2 files changed

+67
-35
lines changed

2 files changed

+67
-35
lines changed

mathics_scanner/data/named-characters.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
# operator-name: If present, this symbol is a Mathics operator with
2222
# whose class name is the given name. For example Divide.
2323
#
24+
# precedence: If present, this symbol is a Mathics operator with the
25+
# specific numeric precidence value.
26+
#
2427
# unicode-equivalent: A unicode equivalent for the named-character, if it
2528
# exists.
2629
#
@@ -1243,6 +1246,7 @@ CompoundExpression:
12431246
has-unicode-inverse: false
12441247
is-letter-like: false
12451248
operator-name: CompoundExpression
1249+
precedence: 10
12461250
Condition:
12471251
ascii: "/;"
12481252
has-unicode-inverse: false
@@ -1453,12 +1457,14 @@ Decrement:
14531457
has-unicode-inverse: false
14541458
is-letter-like: false
14551459
operator-name: Decrement
1460+
precedence: 660
14561461
# See also RawQuestion
14571462
Definition:
14581463
ascii: "?"
14591464
has-unicode-inverse: false
14601465
is-letter-like: false
14611466
operator-name: Definition
1467+
precedence: 670
14621468

14631469
# \[Degree] is letter-like, not an operator, which is
14641470
# mutually exclusive.
@@ -1631,6 +1637,7 @@ Divide:
16311637
has-unicode-inverse: true
16321638
is-letter-like: false
16331639
operator-name: Divide
1640+
precedence: 470
16341641
unicode-equivalent: "\xF7"
16351642
unicode-equivalent-name: DIVISION SIGN
16361643
wl-unicode: "\xF7"
@@ -2694,6 +2701,7 @@ Factorial:
26942701
has-unicode-inverse: false
26952702
is-letter-like: false
26962703
operator-name: Factorial
2704+
precedence: 610
26972705
unicode-equivalent: "!"
26982706
unicode-equivalent-name: EXCLAMATION MARK
26992707
wl-unicode: "!"
@@ -3711,6 +3719,7 @@ Get:
37113719
has-unicode-inverse: false
37123720
is-letter-like: false
37133721
operator-name: Get
3722+
precedence: 720
37143723
Gimel:
37153724
amslatex: "\\gimel"
37163725
esc-alias: gi
@@ -4366,6 +4375,7 @@ Increment:
43664375
has-unicode-inverse: false
43674376
is-letter-like: false
43684377
operator-name: Increment
4378+
precedence: 660
43694379
IndentingNewLine:
43704380
esc-alias: nl
43714381
has-unicode-inverse: false
@@ -4392,6 +4402,7 @@ Information:
43924402
has-unicode-inverse: false
43934403
is-letter-like: false
43944404
operator-name: Information
4405+
precedence: 0
43954406
Integral:
43964407
amslatex: "\\int"
43974408
esc-alias: int
@@ -4978,6 +4989,7 @@ Minus:
49784989
has-unicode-inverse: false
49794990
is-letter-like: false
49804991
operator-name: Minus
4992+
precedence: 480
49814993
unicode-equivalent: "-"
49824994
unicode-equivalent-name: HYPHEN-MINUS
49834995
wl-unicode: "-"
@@ -5751,6 +5763,7 @@ Plus:
57515763
has-unicode-inverse: true
57525764
is-letter-like: false
57535765
operator-name: Plus
5766+
precedence: 310
57545767
unicode-equivalent: "+"
57555768
unicode-equivalent-name: PLUS SIGN
57565769
wl-unicode: "+"
@@ -5780,6 +5793,7 @@ Power:
57805793
has-unicode-inverse: true
57815794
is-letter-like: false
57825795
operator-name: Power
5796+
precedence: 590
57835797
unicode-equivalent: "^"
57845798
unicode-equivalent-name: CIRCUMFLEX ACCENT
57855799
wl-unicode: "^"
@@ -5873,11 +5887,13 @@ Put:
58735887
has-unicode-inverse: false
58745888
is-letter-like: false
58755889
operator-name: Put
5890+
precedence: 30
58765891
PutAppend:
58775892
ascii: ">>>"
58785893
has-unicode-inverse: false
58795894
is-letter-like: false
58805895
operator-name: PutAppend
5896+
precedence: 30
58815897
QuarterNote:
58825898
has-unicode-inverse: false
58835899
is-letter-like: false
@@ -6501,6 +6517,7 @@ SameQ:
65016517
has-unicode-inverse: false
65026518
is-letter-like: false
65036519
operator-name: SameQ
6520+
precedence: 290
65046521
Sampi:
65056522
esc-alias: sa
65066523
has-unicode-inverse: true
@@ -6984,6 +7001,7 @@ Set:
69847001
has-unicode-inverse: true
69857002
is-letter-like: false
69867003
operator-name: Set
7004+
precedence: 40
69877005
unicode-equivalent: "="
69887006
unicode-equivalent-name: EQUALS SIGN
69897007
wl-unicode: "="
@@ -7434,6 +7452,7 @@ Times:
74347452
has-unicode-inverse: false
74357453
is-letter-like: false
74367454
operator-name: Times
7455+
precedence: 400
74377456
unicode-equivalent: "\xD7"
74387457
unicode-equivalent-name: MULTIPLICATION SIGN
74397458
wl-unicode: "\xD7"
@@ -7574,6 +7593,7 @@ Unset:
75747593
has-unicode-inverse: false
75757594
is-letter-like: false
75767595
operator-name: Unset
7596+
precedence: 670
75777597
UpArrow:
75787598
amslatex: "\\uparrow"
75797599
has-unicode-inverse: false
@@ -7675,6 +7695,7 @@ UpSet:
76757695
has-unicode-inverse: false
76767696
is-letter-like: false
76777697
operator-name: UpSet
7698+
precedence: 40
76787699
UpSetDelayed:
76797700
ascii: "^:="
76807701
has-unicode-inverse: false

test/test_general_yaml_sanity.py

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# -*- coding: utf-8 -*-
22

3-
from mathics_scanner.load import load_mathics_character_yaml
43
import unicodedata
54

5+
from mathics_scanner.load import load_mathics_character_yaml
6+
67
yaml_data = load_mathics_character_yaml()
78

89

@@ -21,7 +22,6 @@ def check_attr_is_invertible(attr: str):
2122
), f"{attr_vs} all have the same {attr} field set to {attr_v}"
2223

2324

24-
2525
def check_has_attr(attr: str):
2626
for k, v in yaml_data.items():
2727
assert attr in v, f"{k} has no {attr} attribute"
@@ -37,6 +37,7 @@ def test_yaml_field_names():
3737
"has-unicode-inverse",
3838
"is-letter-like",
3939
"operator-name",
40+
"precedence",
4041
"unicode-equivalent",
4142
"unicode-equivalent-name",
4243
"wl-unicode",
@@ -56,11 +57,11 @@ def test_amslatex():
5657
if a.startswith("$"):
5758
assert a.endswith("$"), (
5859
msg_prefix + "if something starts in math mode, it must end with '$'"
59-
)
60+
)
6061
if a.endswith("$"):
6162
assert a.startswith("$"), (
6263
msg_prefix + "if something ends in math mode, it must start with '$'"
63-
)
64+
)
6465
if a in dup_amslatex:
6566
continue
6667
assert a not in amslatex_seen, msg_prefix + "value seen before"
@@ -103,38 +104,14 @@ def test_operators():
103104
operator_name_seen.add(operator_name)
104105

105106

106-
def test_wl_unicode_name():
107+
def test_precedence():
107108
for k, v in yaml_data.items():
108-
if "wl-unicode" not in v:
109-
continue
110-
wl = v["wl-unicode"]
111-
112-
try:
113-
expected_name = unicodedata.name(wl)
114-
except (ValueError, TypeError):
115-
continue
116-
117-
real_name = v.get("wl-unicode-name")
118-
119-
if real_name is None:
120-
raise ValueError("Section {k}'s wl-unicode has a name but it isn't listed")
121-
122-
assert (
123-
real_name == expected_name
124-
), f"Section {k} has wl-unicode-name set to {real_name} but it should be {expected_name}"
125-
126-
127-
def test_unicode_operators():
128-
exclude_list = frozenset("Apply3Ats FunctionAmpersand".split(" "))
129-
for k, v in yaml_data.items():
130-
if k in exclude_list:
131-
continue
132-
if "operator-name" not in v:
133-
continue
134-
operator_name = v["operator-name"]
135-
assert (
136-
k == operator_name
137-
), f"Section name {k} should match operator-name {operator_name} when a section has an operator"
109+
if "precedence" in v:
110+
p = v.get("precedence", None)
111+
msg_prefix = f"In {k} with precedence {p}, "
112+
assert isinstance(p, int), msg_prefix + "must be an integer"
113+
assert p >= 0, msg_prefix + "must be a positive integer"
114+
assert "operator-name" in v, msg_prefix + "must have an operator name"
138115

139116

140117
def test_unicode_name():
@@ -186,6 +163,40 @@ def test_wl_unicode():
186163
), f"{k} has neither wl-unicode nor unicode-equivalent attribute"
187164

188165

166+
def test_unicode_operators():
167+
exclude_list = frozenset("Apply3Ats FunctionAmpersand".split(" "))
168+
for k, v in yaml_data.items():
169+
if k in exclude_list:
170+
continue
171+
if "operator-name" not in v:
172+
continue
173+
operator_name = v["operator-name"]
174+
assert (
175+
k == operator_name
176+
), f"Section name {k} should match operator-name {operator_name} when a section has an operator"
177+
178+
179+
def test_wl_unicode_name():
180+
for k, v in yaml_data.items():
181+
if "wl-unicode" not in v:
182+
continue
183+
wl = v["wl-unicode"]
184+
185+
try:
186+
expected_name = unicodedata.name(wl)
187+
except (ValueError, TypeError):
188+
continue
189+
190+
real_name = v.get("wl-unicode-name")
191+
192+
if real_name is None:
193+
raise ValueError("Section {k}'s wl-unicode has a name but it isn't listed")
194+
195+
assert (
196+
real_name == expected_name
197+
), f"Section {k} has wl-unicode-name set to {real_name} but it should be {expected_name}"
198+
199+
189200
def test_general_yaml_sanity():
190201
# Check if required attributes are in place
191202
check_has_attr("is-letter-like")

0 commit comments

Comments
 (0)