@@ -2035,6 +2035,7 @@ def __init__(self):
2035
2035
p .non_math = Forward ()
2036
2036
p .operatorname = Forward ()
2037
2037
p .overline = Forward ()
2038
+ p .overset = Forward ()
2038
2039
p .placeable = Forward ()
2039
2040
p .rbrace = Forward ()
2040
2041
p .rbracket = Forward ()
@@ -2051,8 +2052,10 @@ def __init__(self):
2051
2052
p .subsuper = Forward ()
2052
2053
p .subsuperop = Forward ()
2053
2054
p .symbol = Forward ()
2055
+ p .symbol_group = Forward ()
2054
2056
p .symbol_name = Forward ()
2055
2057
p .token = Forward ()
2058
+ p .underset = Forward ()
2056
2059
p .unknown_symbol = Forward ()
2057
2060
2058
2061
# Set names on everything -- very useful for debugging
@@ -2109,6 +2112,7 @@ def __init__(self):
2109
2112
p .end_group <<= p .rbrace .copy ()
2110
2113
p .simple_group <<= Group (p .lbrace + ZeroOrMore (p .token ) + p .rbrace )
2111
2114
p .required_group <<= Group (p .lbrace + OneOrMore (p .token ) + p .rbrace )
2115
+ p .symbol_group <<= Group (p .lbrace + p .symbol + p .rbrace )
2112
2116
p .group <<= Group (
2113
2117
p .start_group + ZeroOrMore (p .token ) + p .end_group
2114
2118
)
@@ -2168,6 +2172,18 @@ def __init__(self):
2168
2172
- (p .required_group | Error ("Expected \\ overline{value}" ))
2169
2173
)
2170
2174
2175
+ p .overset <<= Group (
2176
+ Suppress (Literal (r"\overset" ))
2177
+ - ((p .required_group + p .symbol_group )
2178
+ | Error ("Expected \\ overset{value}{symbol}" ))
2179
+ )
2180
+
2181
+ p .underset <<= Group (
2182
+ Suppress (Literal (r"\underset" ))
2183
+ - ((p .required_group + p .symbol_group )
2184
+ | Error ("Expected \\ underset{value}{symbol}" ))
2185
+ )
2186
+
2171
2187
p .unknown_symbol <<= Combine (p .bslash + Regex ("[A-Za-z]*" ))
2172
2188
2173
2189
p .operatorname <<= Group (
@@ -2189,6 +2205,8 @@ def __init__(self):
2189
2205
| p .dfrac
2190
2206
| p .binom
2191
2207
| p .genfrac
2208
+ | p .overset
2209
+ | p .underset
2192
2210
| p .sqrt
2193
2211
| p .overline
2194
2212
| p .operatorname
@@ -2858,6 +2876,40 @@ def binom(self, s, loc, toks):
2858
2876
return self ._genfrac ('(' , ')' , 0.0 , self ._MathStyle .TEXTSTYLE ,
2859
2877
num , den )
2860
2878
2879
+ def _genset (self , state , value , symbol , shift ):
2880
+ thickness = state .font_output .get_underline_thickness (
2881
+ state .font , state .fontsize , state .dpi )
2882
+
2883
+ value .shrink ()
2884
+
2885
+ cvalue = HCentered ([value ])
2886
+ csymbol = HCentered ([symbol ])
2887
+ width = max (cvalue .width , csymbol .width )
2888
+ cvalue .hpack (width , 'exactly' )
2889
+ csymbol .hpack (width , 'exactly' )
2890
+
2891
+ metrics = state .font_output .get_metrics (
2892
+ state .font , mpl .rcParams ['mathtext.default' ],
2893
+ r'\leftrightarrow' , state .fontsize , state .dpi )
2894
+
2895
+ # Shift so the symbol sits in the same vertical position
2896
+ shift_amount = csymbol .height / 2 - (metrics .ymax + metrics .ymin )/ 2
2897
+ if shift :
2898
+ vlist = Vlist ([csymbol , # value
2899
+ cvalue # symbol
2900
+ ])
2901
+ vlist .shift_amount = shift_amount + cvalue .height
2902
+ else :
2903
+ vlist = Vlist ([cvalue , # value
2904
+ Vbox (0 , thickness * 1.5 ), # space
2905
+ csymbol # symbol
2906
+ ])
2907
+ vlist .shift_amount = shift_amount
2908
+
2909
+ hlist = [Hlist ([vlist , Hbox (thickness * 2. )])]
2910
+
2911
+ return hlist
2912
+
2861
2913
def sqrt (self , s , loc , toks ):
2862
2914
root , body = toks [0 ]
2863
2915
state = self .get_state ()
@@ -2921,6 +2973,30 @@ def overline(self, s, loc, toks):
2921
2973
hlist = Hlist ([rightside ])
2922
2974
return [hlist ]
2923
2975
2976
+ def overset (self , s , loc , toks ):
2977
+ assert len (toks ) == 1
2978
+ assert len (toks [0 ]) == 2
2979
+ # Only one symbol
2980
+ assert len (toks [0 ][1 ]) == 1
2981
+ state = self .get_state ()
2982
+
2983
+ value , symbol = toks [0 ]
2984
+ symbol = symbol [0 ]
2985
+
2986
+ return self ._genset (state , value , symbol , shift = False )
2987
+
2988
+ def underset (self , s , loc , toks ):
2989
+ assert len (toks ) == 1
2990
+ assert len (toks [0 ]) == 2
2991
+ # Only one symbol
2992
+ assert len (toks [0 ][1 ]) == 1
2993
+ state = self .get_state ()
2994
+
2995
+ value , symbol = toks [0 ]
2996
+ symbol = symbol [0 ]
2997
+
2998
+ return self ._genset (state , value , symbol , shift = True )
2999
+
2924
3000
def _auto_sized_delimiter (self , front , middle , back ):
2925
3001
state = self .get_state ()
2926
3002
if len (middle ):
0 commit comments