@@ -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
@@ -2841,6 +2859,40 @@ def binom(self, s, loc, toks):
2841
2859
return self ._genfrac ('(' , ')' , 0.0 , self ._MathStyle .TEXTSTYLE ,
2842
2860
num , den )
2843
2861
2862
+ def _genset (self , state , value , symbol , shift ):
2863
+ thickness = state .font_output .get_underline_thickness (
2864
+ state .font , state .fontsize , state .dpi )
2865
+
2866
+ value .shrink ()
2867
+
2868
+ cvalue = HCentered ([value ])
2869
+ csymbol = HCentered ([symbol ])
2870
+ width = max (cvalue .width , csymbol .width )
2871
+ cvalue .hpack (width , 'exactly' )
2872
+ csymbol .hpack (width , 'exactly' )
2873
+
2874
+ metrics = state .font_output .get_metrics (
2875
+ state .font , mpl .rcParams ['mathtext.default' ],
2876
+ r'\leftrightarrow' , state .fontsize , state .dpi )
2877
+
2878
+ # Shift so the symbol sits in the same vertical position
2879
+ shift_amount = csymbol .height / 2 - (metrics .ymax + metrics .ymin )/ 2
2880
+ if shift :
2881
+ vlist = Vlist ([csymbol , # value
2882
+ cvalue # symbol
2883
+ ])
2884
+ vlist .shift_amount = shift_amount + cvalue .height
2885
+ else :
2886
+ vlist = Vlist ([cvalue , # value
2887
+ Vbox (0 , thickness * 1.5 ), # space
2888
+ csymbol # symbol
2889
+ ])
2890
+ vlist .shift_amount = shift_amount
2891
+
2892
+ hlist = [Hlist ([vlist , Hbox (thickness * 2. )])]
2893
+
2894
+ return hlist
2895
+
2844
2896
def sqrt (self , s , loc , toks ):
2845
2897
(root , body ), = toks
2846
2898
state = self .get_state ()
@@ -2901,6 +2953,30 @@ def overline(self, s, loc, toks):
2901
2953
hlist = Hlist ([rightside ])
2902
2954
return [hlist ]
2903
2955
2956
+ def overset (self , s , loc , toks ):
2957
+ assert len (toks ) == 1
2958
+ assert len (toks [0 ]) == 2
2959
+ # Only one symbol
2960
+ assert len (toks [0 ][1 ]) == 1
2961
+ state = self .get_state ()
2962
+
2963
+ value , symbol = toks [0 ]
2964
+ symbol = symbol [0 ]
2965
+
2966
+ return self ._genset (state , value , symbol , shift = False )
2967
+
2968
+ def underset (self , s , loc , toks ):
2969
+ assert len (toks ) == 1
2970
+ assert len (toks [0 ]) == 2
2971
+ # Only one symbol
2972
+ assert len (toks [0 ][1 ]) == 1
2973
+ state = self .get_state ()
2974
+
2975
+ value , symbol = toks [0 ]
2976
+ symbol = symbol [0 ]
2977
+
2978
+ return self ._genset (state , value , symbol , shift = True )
2979
+
2904
2980
def _auto_sized_delimiter (self , front , middle , back ):
2905
2981
state = self .get_state ()
2906
2982
if len (middle ):
0 commit comments