* Parses the arguments of a function or environment
(
func: string, // Should look like "\name" or "\begin{name}".
funcData: FunctionSpec<NodeType> | EnvSpec<NodeType>,
)
| 516 | * Parses the arguments of a function or environment |
| 517 | */ |
| 518 | parseArguments( |
| 519 | func: string, // Should look like "\name" or "\begin{name}". |
| 520 | funcData: FunctionSpec<NodeType> | EnvSpec<NodeType>, |
| 521 | ): { |
| 522 | args: AnyParseNode[]; |
| 523 | optArgs: (AnyParseNode | null)[]; |
| 524 | } { |
| 525 | const numOptionalArgs = funcData.numOptionalArgs ?? 0; |
| 526 | const totalArgs = funcData.numArgs + numOptionalArgs; |
| 527 | if (totalArgs === 0) { |
| 528 | return {args: [], optArgs: []}; |
| 529 | } |
| 530 | |
| 531 | const args: AnyParseNode[] = []; |
| 532 | const optArgs: (AnyParseNode | null)[] = []; |
| 533 | |
| 534 | for (let i = 0; i < totalArgs; i++) { |
| 535 | let argType = funcData.argTypes?.[i]; |
| 536 | const isOptional = i < numOptionalArgs; |
| 537 | |
| 538 | if (("primitive" in funcData && funcData.primitive && argType == null) || |
| 539 | // \sqrt expands into primitive if optional argument doesn't exist |
| 540 | (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) |
| 541 | ) { |
| 542 | argType = "primitive"; |
| 543 | } |
| 544 | |
| 545 | const arg = this.parseGroupOfType(`argument to '${func}'`, |
| 546 | argType, isOptional); |
| 547 | if (isOptional) { |
| 548 | optArgs.push(arg); |
| 549 | } else if (arg != null) { |
| 550 | args.push(arg); |
| 551 | } else { // should be unreachable |
| 552 | throw new ParseError("Null argument, please report this as a bug"); |
| 553 | } |
| 554 | } |
| 555 | |
| 556 | return {args, optArgs}; |
| 557 | } |
| 558 | |
| 559 | /** |
| 560 | * Parses a group when the mode is changing. |
no test coverage detected