@@ -1864,6 +1864,7 @@ def csnames(group, names):
1864
1864
p .text = Forward ()
1865
1865
p .token = Forward ()
1866
1866
p .underset = Forward ()
1867
+ p .substack = Forward ()
1867
1868
1868
1869
set_names_and_parse_actions () # for mutually recursive definitions.
1869
1870
@@ -1914,6 +1915,9 @@ def csnames(group, names):
1914
1915
1915
1916
p .text <<= cmd (r"\text" , QuotedString ('{' , '\\ ' , endQuoteChar = "}" ))
1916
1917
1918
+ p .substack <<= cmd (
1919
+ r"\substack" , OneOrMore (p .required_group ("value" )))
1920
+
1917
1921
p .placeable <<= (
1918
1922
p .accent # Must be before symbol as all accents are symbols
1919
1923
| p .symbol # Must be second to catch all named symbols and single
@@ -1930,6 +1934,7 @@ def csnames(group, names):
1930
1934
| p .sqrt
1931
1935
| p .overline
1932
1936
| p .text
1937
+ | p .substack
1933
1938
)
1934
1939
1935
1940
p .simple <<= (
@@ -2599,3 +2604,23 @@ def auto_delim(self, s, loc, toks):
2599
2604
# if "mid" in toks ... can be removed when requiring pyparsing 3.
2600
2605
toks ["mid" ].asList () if "mid" in toks else [],
2601
2606
toks ["right" ])
2607
+
2608
+ def substack (self , s , loc , toks ):
2609
+ state = self .get_state ()
2610
+ thickness = state .get_current_underline_thickness ()
2611
+ vlist = []
2612
+
2613
+ max_width = sorted (toks [1 :], key = lambda c : c .width )[- 1 ].width
2614
+
2615
+ for sub in toks [1 :]:
2616
+ cp = HCentered ([sub ])
2617
+ cp .hpack (max_width , 'exactly' )
2618
+ vlist .append (cp )
2619
+
2620
+ vlist = [x for l in (vlist [i :i + 1 ] +
2621
+ [Vbox (0 , thickness * 2.0 )] *
2622
+ (i < len (vlist ) - 1 )
2623
+ for i in range (0 , len (vlist ), 1 )) for x in l ]
2624
+ vlt = Vlist (vlist )
2625
+ result = [Hlist ([vlt ])]
2626
+ return result
0 commit comments