* Parses an ordinary group, which is either a single nucleus (like "x") * or an expression in braces (like "{x+y}") or an implicit group, a group * that starts at the current position, and ends right before a higher explicit * group ends, or at EOF.
(
name: string, // For error reporting.
breakOnTokenText?: BreakToken,
)
| 808 | * group ends, or at EOF. |
| 809 | */ |
| 810 | parseGroup( |
| 811 | name: string, // For error reporting. |
| 812 | breakOnTokenText?: BreakToken, |
| 813 | ): AnyParseNode | null { |
| 814 | const firstToken = this.fetch(); |
| 815 | const text = firstToken.text; |
| 816 | |
| 817 | let result; |
| 818 | // Try to parse an open brace or \begingroup |
| 819 | if (text === "{" || text === "\\begingroup") { |
| 820 | this.consume(); |
| 821 | const groupEnd = text === "{" ? "}" : "\\endgroup"; |
| 822 | |
| 823 | this.gullet.beginGroup(); |
| 824 | // If we get a brace, parse an expression |
| 825 | const expression = this.parseExpression(false, groupEnd); |
| 826 | const lastToken = this.fetch(); |
| 827 | this.expect(groupEnd); // Check that we got a matching closing brace |
| 828 | this.gullet.endGroup(); |
| 829 | result = { |
| 830 | type: "ordgroup", |
| 831 | mode: this.mode, |
| 832 | loc: SourceLocation.range(firstToken, lastToken), |
| 833 | body: expression, |
| 834 | // A group formed by \begingroup...\endgroup is a semi-simple group |
| 835 | // which doesn't affect spacing in math mode, i.e., is transparent. |
| 836 | // https://tex.stackexchange.com/questions/1930/when-should-one- |
| 837 | // use-begingroup-instead-of-bgroup |
| 838 | semisimple: text === "\\begingroup" || undefined, |
| 839 | } as const satisfies ParseNode<"ordgroup">; |
| 840 | } else { |
| 841 | // If there exists a function with this name, parse the function. |
| 842 | // Otherwise, just return a nucleus |
| 843 | result = this.parseFunction(breakOnTokenText, name) || |
| 844 | this.parseSymbol(); |
| 845 | if (result == null && text[0] === "\\" && |
| 846 | !Object.prototype.hasOwnProperty.call(implicitCommands, text)) { |
| 847 | if (this.settings.throwOnError) { |
| 848 | throw new ParseError( |
| 849 | "Undefined control sequence: " + text, firstToken); |
| 850 | } |
| 851 | result = this.formatUnsupportedCmd(text); |
| 852 | this.consume(); |
| 853 | } |
| 854 | } |
| 855 | return result; |
| 856 | } |
| 857 | |
| 858 | /** |
| 859 | * Form ligature-like combinations of characters for text mode. |
no test coverage detected