r""" Helper to define TeX commands. ``cmd("\cmd", args)`` is equivalent to ``"\cmd" - (args | Error("Expected \cmd{arg}{...}"))`` where the names in the error message are taken from element names in *args*. If *expr* already includes arguments (e.g. "\cmd{arg}{...}"), then they
(expr: str, args: ParserElement)
| 1912 | |
| 1913 | |
| 1914 | def cmd(expr: str, args: ParserElement) -> ParserElement: |
| 1915 | r""" |
| 1916 | Helper to define TeX commands. |
| 1917 | |
| 1918 | ``cmd("\cmd", args)`` is equivalent to |
| 1919 | ``"\cmd" - (args | Error("Expected \cmd{arg}{...}"))`` where the names in |
| 1920 | the error message are taken from element names in *args*. If *expr* |
| 1921 | already includes arguments (e.g. "\cmd{arg}{...}"), then they are stripped |
| 1922 | when constructing the parse element, but kept (and *expr* is used as is) in |
| 1923 | the error message. |
| 1924 | """ |
| 1925 | |
| 1926 | def names(elt: ParserElement) -> T.Generator[str, None, None]: |
| 1927 | if isinstance(elt, ParseExpression): |
| 1928 | for expr in elt.exprs: |
| 1929 | yield from names(expr) |
| 1930 | elif elt.resultsName: |
| 1931 | yield elt.resultsName |
| 1932 | |
| 1933 | csname = expr.split("{", 1)[0] |
| 1934 | err = (csname + "".join("{%s}" % name for name in names(args)) |
| 1935 | if expr == csname else expr) |
| 1936 | return csname - (args | Error(f"Expected {err}")) |
| 1937 | |
| 1938 | |
| 1939 | class Parser: |