A rule can be expressed as a string of the form * ` -> ; ` * where ` `, ` ` and ` ` are LaTeX expressions.
(
ce: ComputeEngine,
rule: string,
options?: { canonical?: boolean; purpose?: RulePurpose }
)
| 495 | } |
| 496 | return expr; |
| 497 | } |
| 498 | const canonical = |
| 499 | options?.canonical ?? |
| 500 | (rule instanceof _BoxedExpression ? rule.isCanonical : false); |
| 501 | return ce.expr(rule, { form: canonical ? 'canonical' : 'raw' }); |
| 502 | } |
| 503 | |
| 504 | /** A rule can be expressed as a string of the form |
| 505 | * `<match> -> <replace>; <condition>` |
| 506 | * where `<match>`, `<replace>` and `<condition>` are LaTeX expressions. |
| 507 | */ |
| 508 | function parseRule( |
| 509 | ce: ComputeEngine, |
| 510 | rule: string, |
| 511 | options?: { canonical?: boolean; purpose?: RulePurpose } |
| 512 | ): BoxedRule { |
| 513 | const makeWildcardEntry = (x: string) => { |
| 514 | return { |
| 515 | kind: 'symbol', |
| 516 | latexTrigger: x, |
| 517 | // domain: { kind: 'Any' }, |
| 518 | parse: (parser: Parser, _until?: Readonly<Terminator>) => { |
| 519 | if (!wildcards[x]) wildcards[x] = `_${x}`; |
| 520 | // conditions are `:condition` or `:condition1,condition2,...` |
| 521 | // or `:\mathrm{condition}` |
| 522 | const conditions = parseModifierExpression(parser); |
| 523 | if (conditions !== null) { |
| 524 | if (!wildcardConditions[x]) wildcardConditions[x] = conditions; |
| 525 | else wildcardConditions[x] += ',' + conditions; |
| 526 | } |
| 527 | return wildcards[x]; |
| 528 | }, |
| 529 | }; |
| 530 | }; |
| 531 | |
| 532 | // Setup custom dictionary entries for ...x, ...x? |
| 533 | // mapping to wildcard sequence, wildcard optional sequence |
| 534 | |
| 535 | // A mapping from a symbol to a wildcard |
| 536 | const wildcards: Record<string, string> = {}; |
| 537 | |
| 538 | // A mapping from a symbol to a condition |
| 539 | const wildcardConditions: Record<string, string> = {}; |
| 540 | |
| 541 | // Add wildcard entries for all lowercase letters, except |
| 542 | // for e (natural number), d (differential) and i (imaginary unit) |
| 543 | const ruleDict = [ |
| 544 | ...LATEX_DICTIONARY, |
| 545 | { |
| 546 | kind: 'prefix', |
| 547 | precedence: 100, |
| 548 | latexTrigger: '...', |
| 549 | parse: (parser: Parser, _until?: Readonly<Terminator>) => { |
| 550 | const id = parser.nextToken(); |
| 551 | if (!'abcfghjklmnopqrstuvwxyz'.includes(id)) return null; |
| 552 | let prefix = '__'; |
| 553 | // Optional wildcard sequence? |
| 554 | if (parser.match('?')) prefix = '___'; |
no test coverage detected