@holgerengels/compute-engine
Version:
Symbolic computing and numeric evaluations for JavaScript and Node.js
825 lines (824 loc) • 32.6 kB
TypeScript
/* 0.26.0-alpha2 */
import type { Expression, MathJsonIdentifier } from '../../math-json/types';
import type { IndexedLatexDictionary, IndexedLatexDictionaryEntry } from './dictionary/definitions';
export type SymbolType = 'symbol' | 'function' | 'unknown';
export type SymbolTable = {
parent: SymbolTable | null;
ids: {
[id: MathJsonIdentifier]: SymbolType;
};
};
/**
* A `LatexToken` is a token as returned by `Parser.peek`.
*
* It can be one of the indicated tokens, or a string that starts with a
* `\` for LaTeX commands, or a LaTeX character which includes digits,
* letters and punctuation.
*
* @category Latex Parsing and Serialization
*/
export type LatexToken = string | '<{>' | '<}>' | '<space>' | '<$>' | '<$$>';
/** A LatexString is a regular string of LaTeX, for example:
* `\frac{\pi}{2}`
*
* @category Latex Parsing and Serialization
*/
export type LatexString = string;
/**
* Open and close delimiters that can be used with {@linkcode MatchfixEntry}
* record to define new LaTeX dictionary entries.
*
* @category Latex Parsing and Serialization
*/
export type Delimiter = ')' | '(' | ']' | '[' | '{' /** \lbrace */ | '}' /** \rbrace */ | '<' /** \langle */ | '>' /** \rangle */ | '|' | '||' | '\\lceil' | '\\rceil' | '\\lfloor' | '\\rfloor' | '\\llbracket' | '\\rrbracket';
/** @category Latex Parsing and Serialization */
export type DelimiterScale = 'normal' | 'scaled' | 'big' | 'none';
/**
* @category Latex Parsing and Serialization
*/
export type LibraryCategory = 'algebra' | 'arithmetic' | 'calculus' | 'collections' | 'control-structures' | 'combinatorics' | 'complex' | 'core' | 'data-structures' | 'dimensions' | 'domains' | 'linear-algebra' | 'logic' | 'numeric' | 'other' | 'physics' | 'polynomials' | 'relop' | 'sets' | 'statistics' | 'styling' | 'symbols' | 'trigonometry' | 'units';
/**
*
* :::info[THEORY OF OPERATIONS]
*
* The precedence of an operator is a number that indicates the order in which
* operators are applied.
*
* For example, in `1 + 2 * 3`, the `*` operator has a **higher** precedence
* than the `+` operator, so it is applied first.
*
* The precedence range from 0 to 1000. The larger the number, the higher the
* precedence, the more "binding" the operator is.
*
* Here are some rough ranges for the precedence:
*
* - 800: prefix and postfix operators: `\lnot` etc...
* - `POSTFIX_PRECEDENCE` = 810: `!`, `'`
* - 700: some arithmetic operators
* - `EXPONENTIATION_PRECEDENCE` = 700: `^`
* - 600: some binary operators
* - `DIVISION_PRECEDENCE` = 600: `\div`
* - 500: not used
* - 400: not used
* - 300: some logic and arithmetic operators:
* `\land`, `\lor`, `\times`, etc...
* - `MULTIPLICATION_PRECEDENCE` = 390: `\times`
* - 200: arithmetic operators, inequalities:
* - `ADDITION_PRECEDENCE` = 275: `+` `-`
* - `ARROW_PRECEDENCE` = 270: `\to` `\rightarrow`
* - `ASSIGNMENT_PRECEDENCE` = 260: `:=`
* - `COMPARISON_PRECEDENCE` = 245: `\lt` `\gt`
* - 241: `\leq`
* - 100: not used
* - 0: `,`, `;`, etc...
*
* Some constants are defined below for common precedence values.
*
*
* **Note**: MathML defines
* [some operator precedence](https://www.w3.org/TR/2009/WD-MathML3-20090924/appendixc.html),
* but it has some issues and inconsistencies. However,
* whenever possible we adopted the MathML precedence.
*
* The JavaScript operator precedence is documented
* [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence).
*
* :::
*
* @category Latex Parsing and Serialization
*/
export type Precedence = number;
/** @hidden */
export declare const COMPARISON_PRECEDENCE: Precedence;
/** @hidden */
export declare const ASSIGNMENT_PRECEDENCE: Precedence;
/** @hidden */
export declare const ARROW_PRECEDENCE: Precedence;
/** @hidden */
export declare const ADDITION_PRECEDENCE: Precedence;
/** @hidden */
export declare const MULTIPLICATION_PRECEDENCE: Precedence;
/** @hidden */
export declare const DIVISION_PRECEDENCE: Precedence;
/** @hidden */
export declare const EXPONENTIATION_PRECEDENCE: Precedence;
/** @hidden */
export declare const POSTFIX_PRECEDENCE: Precedence;
/**
* This indicates a condition under which parsing should stop:
* - an operator of a precedence higher than specified has been encountered
* - the last token has been reached
* - or if a condition is provided, the condition returns true
*
* @category Latex Parsing and Serialization
*/
export type Terminator = {
minPrec: Precedence;
condition?: (parser: Parser) => boolean;
};
/**
* Custom parsing handler.
*
* When invoked the parser points right after the LaTeX fragment that triggered
* this parsing handler.
*
* The parser should be moved, by calling `parser.nextToken()` for
* every consumed token.
*
* If it was in an infix or postfix context, `lhs` will represent the
* left-hand side argument. In a prefix or matchfix context, `lhs` is `null`.
*
* In a superfix (^) or subfix (_) context (that is if the first token of the
* trigger is `^` or `_`), lhs is `["Superscript", lhs, rhs]`
* and `["Subscript", lhs, rhs]`, respectively.
*
* The handler should return `null` if the expression could not be parsed
* (didn't match the syntax that was expected). The matching expression
* otherwise.
*
* @category Latex Parsing and Serialization
*/
export type ExpressionParseHandler = (parser: Parser, until?: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type PrefixParseHandler = (parser: Parser, until?: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type SymbolParseHandler = (parser: Parser, until?: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type FunctionParseHandler = (parser: Parser, until?: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type EnvironmentParseHandler = (parser: Parser, until?: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type PostfixParseHandler = (parser: Parser, lhs: Expression, until?: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type InfixParseHandler = (parser: Parser, lhs: Expression, until: Readonly<Terminator>) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type MatchfixParseHandler = (parser: Parser, body: Expression) => Expression | null;
/**
* @category Latex Parsing and Serialization
*/
export type LatexArgumentType = '{expression}' /** A required math mode expression */ | '[expression]' /** An optional math mode expression */ | '{text}' /** A required expression in text mode */ | '[text]' /** An optional expression in text mode */ | '{unit}' /** A required unit expression, e.g. `3em` */ | '[unit]' /** An optional unit expression, e.g. `3em` */ | '{glue}' /** A required glue expression, e.g. `25 mu plus 3em ` */ | '[glue]' /** An optional glue expression, e.g. `25 mu plus 3em ` */ | '{string}' /** A required text string, terminated by a non-literal token */ | '[string]' /** An optional text string, terminated by a non-literal token */ | '{color}' /** A required color expression, e.g. `red` or `#00ff00` */ | '[color]'; /** An optional color expression, e.g. `red` or `#00ff00` */
/**
* A trigger is the set of tokens that will make an entry in the
* LaTeX dictionary eligible to parse the stream and generate an expression.
* If the trigger matches, the `parse` handler is called, if available.
*
* The trigger can be specified either as a LaTeX string (`latexTrigger`) or
* as an identifier (`identifierTrigger`). An identifier match several
* LaTeEx expressions that are equivalent, for example `\operatorname{gcd}` or
* `\mathbin{gcd}`, match the `"gcd"` identifier
*
* `matchfix` operators use `openTrigger` and `closeTrigger` instead.
*
* @category Latex Parsing and Serialization
*/
export type Trigger = {
latexTrigger?: LatexString | LatexToken[];
identifierTrigger?: MathJsonIdentifier;
};
/**
* Maps a string of LaTeX tokens to a function or symbol and vice-versa.
* @category Latex Parsing and Serialization
*/
export type BaseEntry = {
/**
* Map a MathJSON identifier to this entry.
*
* Each entry should have at least a `name` or a `parse` handler.
*
* An entry with no `name` cannot be serialized: the `name` is used to map
* a MathJSON function or symbol name to the appropriate entry for
* serializing.
*
* However, an entry with no `name` can be used to define a synonym (for
* example for the symbol `\varnothing` which is a synonym for `\emptyset`).
*
* If no `parse` handler is provided, only the trigger is used to select this
* entry. Otherwise, if the trigger of the entry matches the current
* token, the `parse` handler is invoked.
*/
name?: MathJsonIdentifier;
/**
* Transform an expression into a LaTeX string.
* If no `serialize` handler is provided, the trigger is used.
*/
serialize?: LatexString | SerializeHandler;
};
/**
* @category Latex Parsing and Serialization
*/
export type DefaultEntry = BaseEntry & Trigger & {
parse: Expression | ExpressionParseHandler;
};
/**
* @category Latex Parsing and Serialization
*/
export type ExpressionEntry = BaseEntry & Trigger & {
kind: 'expression';
parse: Expression | ExpressionParseHandler;
precedence?: Precedence;
};
/**
* @category Latex Parsing and Serialization
*/
export type MatchfixEntry = BaseEntry & {
kind: 'matchfix';
/**
* If `kind` is `'matchfix'`: the `openTrigger` and `closeTrigger`
* properties are required.
*/
openTrigger: Delimiter | LatexToken[];
closeTrigger: Delimiter | LatexToken[];
/** When invoked, the parser is pointing after the close delimiter.
* The argument of the handler is the body, i.e. the content between
* the open delimiter and the close delimiter.
*/
parse?: MatchfixParseHandler;
};
/**
* @category Latex Parsing and Serialization
*/
export type InfixEntry = BaseEntry & Trigger & {
/**
* Infix position, with an operand before and an operand after: `a ⊛ b`.
*
* Example: `+`, `\times`.
*/
kind: 'infix';
/**
* - **`none`**: a ? b ? c -> syntax error
* - **`any`**: a + b + c -> +(a, b, c)
* - **`left`**: a / b / c -> /(/(a, b), c)
* - **`right`**: a = b = c -> =(a, =(b, c))
*
* - `any`-associative operators have an unlimited number of arguments
* - `left`, `right` or `none` associative operators have two arguments
*
*/
associativity?: 'right' | 'left' | 'none' | 'any';
precedence?: Precedence;
parse?: string | InfixParseHandler;
};
/**
* @category Latex Parsing and Serialization
*/
export type PostfixEntry = BaseEntry & Trigger & {
/**
* Postfix position, with an operand before: `a ⊛`
*
* Example: `!`.
*/
kind: 'postfix';
precedence?: Precedence;
parse?: string | PostfixParseHandler;
};
/**
* @category Latex Parsing and Serialization
*/
export type PrefixEntry = BaseEntry & Trigger & {
/**
* Prefix position, with an operand after: `⊛ a`
*
* Example: `-`, `\not`.
*/
kind: 'prefix';
precedence: Precedence;
parse?: string | PrefixParseHandler;
};
/**
* A LaTeX dictionary entry for an environment, that is a LaTeX
* construct using `\begin{...}...\end{...}`.
* @category Latex Parsing and Serialization
*/
export type EnvironmentEntry = BaseEntry & {
kind: 'environment';
parse: EnvironmentParseHandler;
identifierTrigger: MathJsonIdentifier;
};
/**
* @category Latex Parsing and Serialization
*/
export type SymbolEntry = BaseEntry & Trigger & {
kind: 'symbol';
/** Used for appropriate wrapping (i.e. when to surround it with parens) */
precedence?: Precedence;
parse: Expression | SymbolParseHandler;
};
/**
* A function is an identifier followed by:
* - some postfix operators such as `\prime`
* - an optional list of arguments in an enclosure (parentheses)
*
* For more complex situations, for example implicit arguments or
* inverse functions postfix (i.e. ^{-1}), use a custom parse handler with a
* entry of kind `expression`.
* @category Latex Parsing and Serialization
*/
export type FunctionEntry = BaseEntry & Trigger & {
kind: 'function';
parse?: Expression | FunctionParseHandler;
};
/**
*
* A dictionary entry is a record that maps a LaTeX token or string of tokens
* ( a trigger) to a MathJSON expression or to a parsing handler.
*
* Set the {@linkcode ComputeEngine.latexDictionary} property to an array of
* dictionary entries to define custom LaTeX parsing and serialization.
*
* @category Latex Parsing and Serialization
*
*/
export type LatexDictionaryEntry = DefaultEntry | ExpressionEntry | MatchfixEntry | InfixEntry | PostfixEntry | PrefixEntry | SymbolEntry | FunctionEntry | EnvironmentEntry;
/** @internal */
export declare function isExpressionEntry(entry: LatexDictionaryEntry): entry is ExpressionEntry;
/** @internal */
export declare function isSymbolEntry(entry: LatexDictionaryEntry): entry is SymbolEntry;
/** @internal */
export declare function isFunctionEntry(entry: LatexDictionaryEntry): entry is FunctionEntry;
/** @internal */
export declare function isMatchfixEntry(entry: LatexDictionaryEntry): entry is MatchfixEntry;
/** @internal */
export declare function isInfixEntry(entry: LatexDictionaryEntry): entry is InfixEntry;
/** @internal */
export declare function isPrefixEntry(entry: LatexDictionaryEntry): entry is PrefixEntry;
/** @internal */
export declare function isPostfixEntry(entry: LatexDictionaryEntry): entry is PostfixEntry;
/** @internal */
export declare function isEnvironmentEntry(entry: LatexDictionaryEntry): entry is EnvironmentEntry;
/**
* A LaTeX dictionary is a collection of LaTeX dictionary entries.
*
* Each entry in the dictionary indicates how to parse and serialize a
* particular LaTeX token or string of tokens.
*
* @category Latex Parsing and Serialization
* @internal
*/
export type LatexDictionary = ReadonlyArray<Partial<LatexDictionaryEntry>>;
/**
* These options control how numbers are parsed and serialized.
*/
export type NumberFormat = {
positiveInfinity: LatexString;
negativeInfinity: LatexString;
notANumber: LatexString;
imaginaryUnit: LatexString;
/**
* A string representing the decimal separator, the string separating
* the whole portion of a number from the fractional portion, i.e.
* the "." in "3.1415".
*
* Some countries use a comma rather than a dot. In this case it is
* recommended to use `"{,}"` as the separator: the surrounding brackets
* ensure there is no additional gap after the comma.
*
* **Default**: `"."`
*/
decimalSeparator: LatexString;
/**
* A string representing the separator between groups of digits,
* to make numbers with many digits easier to read.
*
* If a single string is provided, it is used to group digits in the
* whole and the fractional part of the number. If two strings are provided,
* the first is used for the whole part and the second for the fractional
* part.
*
* Caution: some values may lead to unexpected results.
*
* For example, if the `digitGroupSeparator` is `,` (comma) the expression
* `\operatorname{Hypot}(1,2)` will parse as `["Hypot", 1.2]` rather than
* `["Hypot", 1, 2]`. You can however use `{,}` which will avoid this issue
* and display with correct spacing.
*
* **Default**: `"\\,"` (thin space, 3/18mu) (Resolution 7 of the 1948 CGPM)
*/
digitGroupSeparator: LatexString | [LatexString, LatexString];
/**
* Maximum length of digits between digit group separators.
*
* If a single number is provided, it is used for the whole and the fractional
* part of the number. If two numbers are provided, the first is used for the
* whole part and the second for the fractional part.
*
* If '`"lakh"`' is provided, the number is grouped in groups of 2 digits,
* except for the last group which has 3 digits. For example: `1,00,00,000`.
*
*
* **Default**: `3`
*/
digitGroup: 'lakh' | number | [number | 'lakh', number];
exponentProduct: LatexString;
beginExponentMarker: LatexString;
endExponentMarker: LatexString;
truncationMarker: LatexString;
repeatingDecimal: 'auto' | 'vinculum' | 'dots' | 'parentheses' | 'arc' | 'none';
};
export type NumberSerializationFormat = NumberFormat & {
/**
* The maximum number of significant digits in serialized numbers.
* - `"max"`: all availabe digits are serialized.
* - `"auto"`: use the same precision as the compute engine.
*
* Default: `"auto"`
*/
fractionalDigits: 'auto' | 'max' | number;
notation: 'auto' | 'engineering' | 'scientific';
avoidExponentsInRange: undefined | null | [negativeExponent: number, positiveExponent: number];
};
/**
*
* The LaTeX parsing options can be used with the `ce.parse()` method.
*
* @category Latex Parsing and Serialization
*/
export type ParseLatexOptions = NumberFormat & {
/**
* If true, ignore space characters in math mode.
*
* **Default**: `true`
*
*/
skipSpace: boolean;
/**
* When parsing a decimal number, e.g. `3.1415`:
*
* - `"auto"` or `"decimal"`: if a decimal number, parse it as an approximate
* decimal number with a whole part and a fractional part
* - `"rational"`: if a decimal number, parse it as an exact rational number
* with a numerator and a denominator. If not a decimal number, parse
* it as a regular number.
* - `"never"`: do not parse numbers, instead return each token making up
* the number (minus sign, digits, decimal marker, etc...).
*
* Note: if the number includes repeating digits (e.g. `1.33(333)`),
* it will be parsed as a decimal number even if this setting is `"rational"`.
*
* **Default**: `"auto"`
*
*/
parseNumbers: 'auto' | 'rational' | 'decimal' | 'never';
/**
* This handler is invoked when the parser encounters an identifier
* that has not yet been declared.
*
* The `identifier` argument is a (valid identifier)[/math-json/#identifiers].
*
* The handler can return:
*
* - `"variable"`: the identifier is a variable
* - `"function"`: the identifier is a function name. If an apply
* function operator (typically, parentheses) follow, they will be parsed
* as arguments to the function.
*
* - `"unknown"`: the identifier is not recognized.
*/
getIdentifierType: (identifier: MathJsonIdentifier) => SymbolType;
/** This handler is invoked when the parser encounters an unexpected token.
*
* The `lhs` argument is the left-hand side of the token, if any.
*
* The handler can access the unexpected token with `parser.peek`. If
* it is a token that should be recognized, the handler can consume it
* by calling `parser.nextToken()`.
*
* The handler should return an expression or `null` if the token is not
* recognized.
*/
parseUnexpectedToken: (lhs: Expression | null, parser: Parser) => Expression | null;
/**
* If true, the expression will be decorated with the LaTeX
* fragments corresponding to each elements of the expression.
*
* The top-level expression, that is the one returned by `parse()`, will
* include the verbatim LaTeX input that was parsed. The sub-expressions
* may contain a slightly different LaTeX, for example with consecutive spaces
* replaced by one, with comments removed and with some low-level LaTeX
* commands replaced, for example `\egroup` and `\bgroup`.
*
* **Default:** `false`
*/
preserveLatex: boolean;
};
/**
*
* The expected format of numbers in the LaTeX string can be specified with
* the `ce.parse()` method.
*
* @category Latex Parsing and Serialization
*/
/**
* An instance of `Parser` is provided to the `parse` handlers of custom
* LaTeX dictionary entries.
*
* @category Latex Parsing and Serialization
*/
export interface Parser {
readonly options: Required<ParseLatexOptions>;
getIdentifierType(id: MathJsonIdentifier): SymbolType;
pushSymbolTable(): void;
popSymbolTable(): void;
addSymbol(id: MathJsonIdentifier, type: SymbolType): void;
/** The index of the current token */
index: number;
/** True if the last token has been reached.
* Consider also `atTerminator()`.
*/
readonly atEnd: boolean;
/** Return true if the terminator condition is met or if the last token
* has been reached.
*/
atTerminator(t: Terminator | undefined): boolean;
/** Return the next token, without advancing the index */
readonly peek: LatexToken;
/** Return the next token and advance the index */
nextToken(): LatexToken;
/** Return a string representation of the expression
* between `start` and `end` (default: the whole expression)
*
*
*/
latex(start: number, end?: number): string;
/** Return an error expression with the specified code and arguments */
error(code: string | [string, ...Expression[]], fromToken: number): Expression;
/** If there are any space, advance the index until a non-space is encountered */
skipSpace(): boolean;
/** Skip over "visual space" which
includes space tokens, empty groups `{}`, and commands such as `\,` and `\!` */
skipVisualSpace(): void;
/** If the next token matches the target advance and return true. Otherwise
* return false
*/
match(token: LatexToken): boolean;
/** Return true if the next tokens match the argument, an array of tokens, or null otherwise
*/
matchAll(tokens: LatexToken[]): boolean;
/** Return the next token if it matches any of the token in the argument or null otherwise
*/
matchAny(tokens: LatexToken[]): LatexToken;
/** If the next token is a character, return it and advance the index
* This includes plain characters (e.g. 'a', '+'...), characters
* defined in hex (^^ and ^^^^), the `\char` and `\unicode` command.
*/
matchChar(): string | null;
/**
* Parse an expression in aLaTeX group enclosed in curly brackets `{}`.
* These are often used as arguments to LaTeX commands, for example
* `\frac{1}{2}`.
*
* Return `null` if none was found
* Return `Nothing` if an empty group `{}` was found
*/
parseGroup(): Expression | null;
/**
* Some LaTeX commands (but not all) can accept arguments as single
* tokens (i.e. without braces), for example `^2`, `\sqrt3` or `\frac12`
*
* This argument will usually be a single token, but can be a sequence of
* tokens (e.g. `\sqrt\frac12` or `\sqrt\operatorname{speed}`).
*
* The following tokens are excluded from consideration in order to fail
* early when encountering a likely syntax error, for example `x^(2)`
* instead of `x^{2}`. With `(` in the list of excluded tokens, the
* match will fail and the error can be recovered.
*
* The excluded tokens include `!"#$%&(),/;:?@[]`|~", `\left`, `\bigl`, etc...
*/
parseToken(): Expression | null;
/**
* Parse an expression enclosed in a LaTeX optional group enclosed in square brackets `[]`.
*
* Return `null` if none was found.
*/
parseOptionalGroup(): Expression | null;
/**
* Some LaTeX commands have arguments that are not interpreted as
* expressions, but as strings. For example, `\begin{array}{ccc}` (both
* `array` and `ccc` are strings), `\color{red}` or `\operatorname{lim sup}`.
*
* If the next token is the start of a group (`{`), return the content
* of the group as a string. This may include white space, and it may need
* to be trimmed at the start and end of the string.
*
* LaTeX commands are typically not allowed inside a string group (for example,
* `\alpha` would result in an error), but we do not enforce this.
*
* If `optional` is true, this should be an optional group in square brackets
* otherwise it is a regular group in braces.
*/
parseStringGroup(optional?: boolean): string | null;
/**
* A symbol can be:
* - a single-letter identifier: `x`
* - a single LaTeX command: `\pi`
* - a multi-letter identifier: `\operatorname{speed}`
*/
parseSymbol(until?: Partial<Terminator>): Expression | null;
/**
* Parse an expression in a tabular format, where rows are separated by `\\`
* and columns by `&`.
*
* Return rows of sparse columns: empty rows are indicated with `Nothing`,
* and empty cells are also indicated with `Nothing`.
*/
parseTabular(): null | Expression[][];
/**
* Parse an argument list, for example: `(12, x+1)` or `\left(x\right)`
*
* - 'enclosure' : will look for arguments inside an enclosure
* (an open/close fence) (**default**)
* - 'implicit': either an expression inside a pair of `()`, or just a primary
* (i.e. we interpret `\cos x + 1` as `\cos(x) + 1`)
*
* Return an array of expressions, one for each argument, or `null` if no
* argument was found.
*/
parseArguments(kind?: 'implicit' | 'enclosure', until?: Terminator): ReadonlyArray<Expression> | null;
/**
* Parse a postfix operator, such as `'` or `!`.
*
* Prefix, infix and matchfix operators are handled by `parseExpression()`
*
*/
parsePostfixOperator(lhs: Expression | null, until?: Partial<Terminator>): Expression | null;
/**
* Parse an expression:
*
* ```
* <expression> ::=
* | <primary> ( <infix-op> <expression> )?
* | <prefix-op> <expression>
*
* <primary> :=
* (<number> | <symbol> | <function-call> | <matchfix-expr>)
* (<subsup> | <postfix-operator>)*
*
* <matchfix-expr> :=
* <matchfix-op-open> <expression> <matchfix-op-close>
*
* <function-call> ::=
* | <function><matchfix-op-group-open><expression>[',' <expression>]<matchfix-op-group-close>
* ```
*
* This is the top-level parsing entry point.
*
* Stop when an operator of precedence less than `until.minPrec`
* or the sequence of tokens `until.tokens` is encountered
*
* `until` is `{ minPrec:0 }` by default.
*/
parseExpression(until?: Partial<Terminator>): Expression | null;
/**
* Parse a number.
*/
parseNumber(): Expression | null;
/**
* Boundaries are used to detect the end of an expression.
*
* They are used for unusual syntactic constructs, for example
* `\int \sin x dx` where the `dx` is not an argument to the `\sin`
* function, but a boundary of the integral.
*
* They are also useful when handling syntax errors and recovery.
*
* For example, `\begin{bmatrix} 1 & 2 { \end{bmatrix}` has an
* extraneous `{`, but the parser will attempt to recover and continue
* parsing when it encounters the `\end{bmatrix}` boundary.
*/
addBoundary(boundary: LatexToken[]): void;
removeBoundary(): void;
get atBoundary(): boolean;
matchBoundary(): boolean;
boundaryError(msg: string | [string, ...Expression[]]): Expression;
}
/**
*
* The LaTeX serialization options can used with the `expr.toLatex()` method.
*
* @category Latex Parsing and Serialization
*/
export type SerializeLatexOptions = NumberSerializationFormat & {
/**
* If true, prettify the LaTeX output.
*
* For example, render `\frac{a}{b}\frac{c}{d}` as `\frac{ac}{bd}`
*
*/
prettify: boolean;
/**
* LaTeX string used to render an invisible multiply, e.g. in '2x'.
*
* If empty, both operands are concatenated, i.e. `2x`.
*
* Use `\cdot` to insert a `\cdot` operator between them, i.e. `2 \cdot x`.
*
* Empty by default.
*/
invisibleMultiply: LatexString;
/**
* LaTeX string used to render [mixed numbers](https://en.wikipedia.org/wiki/Fraction#Mixed_numbers) e.g. '1 3/4'.
*
* Leave it empty to join the main number and the fraction, i.e. render it
* as `1\frac{3}{4}`.
*
* Use `+` to insert an explicit `+` operator between them,
* i.e. `1+\frac{3}{4}`
*
* Empty by default.
*/
invisiblePlus: LatexString;
/**
* LaTeX string used to render an explicit multiply operator.
*
* For example, `\times`, `\cdot`, etc...
*
* Default: `\times`
*/
multiply: LatexString;
/**
* Serialize the expression `["Error", "'missing'"]`, with this LaTeX string
*
*/
missingSymbol: LatexString;
applyFunctionStyle: (expr: Expression, level: number) => DelimiterScale;
groupStyle: (expr: Expression, level: number) => DelimiterScale;
rootStyle: (expr: Expression, level: number) => 'radical' | 'quotient' | 'solidus';
fractionStyle: (expr: Expression, level: number) => 'quotient' | 'block-quotient' | 'inline-quotient' | 'inline-solidus' | 'nice-solidus' | 'reciprocal' | 'factor';
logicStyle: (expr: Expression, level: number) => 'word' | 'boolean' | 'uppercase-word' | 'punctuation';
powerStyle: (expr: Expression, level: number) => 'root' | 'solidus' | 'quotient';
numericSetStyle: (expr: Expression, level: number) => 'compact' | 'regular' | 'interval' | 'set-builder';
};
/**
*
* An instance of `Serializer` is provided to the `serialize` handlers of custom
* LaTeX dictionary entries.
*
* @category Latex Parsing and Serialization
*
*/
export interface Serializer {
readonly options: Required<SerializeLatexOptions>;
readonly dictionary: IndexedLatexDictionary;
/** "depth" of the expression:
* - 0 for the root
* - 1 for a subexpression of the root
* - 2 for subexpressions of the subexpressions of the root
* - etc...
*
* This allows the serialized LaTeX to vary depending on the depth of the
* expression.
*
* For example use `\Bigl(` for the top level, and `\bigl(` or `(` for others.
*/
level: number;
/** Output a LaTeX string representing the expression */
serialize: (expr: Expression | null | undefined) => string;
serializeFunction(expr: Expression, def?: IndexedLatexDictionaryEntry): LatexString;
serializeSymbol(expr: Expression): LatexString;
/** Output `s` surrounded by delimiters.
*
* If `delimiters` is not specified, use `()`
*
*/
wrapString(s: LatexString, style: DelimiterScale, delimiters?: string): LatexString;
/** A string with the arguments of expr fenced appropriately and separated by
* commas.
*/
wrapArguments(expr: Expression): LatexString;
/** Add a group fence around the expression if it is
* an operator of precedence less than or equal to `prec`.
*/
wrap: (expr: Expression | null | undefined, prec?: number) => LatexString;
/** Add a group fence around the expression if it is
* short (not a function)
*/
wrapShort(expr: Expression | null | undefined): LatexString;
/** Styles */
applyFunctionStyle: (expr: Expression, level: number) => DelimiterScale;
groupStyle: (expr: Expression, level: number) => DelimiterScale;
rootStyle: (expr: Expression, level: number) => 'radical' | 'quotient' | 'solidus';
fractionStyle: (expr: Expression, level: number) => 'quotient' | 'block-quotient' | 'inline-quotient' | 'inline-solidus' | 'nice-solidus' | 'reciprocal' | 'factor';
logicStyle: (expr: Expression, level: number) => 'word' | 'boolean' | 'uppercase-word' | 'punctuation';
powerStyle: (expr: Expression, level: number) => 'root' | 'solidus' | 'quotient';
numericSetStyle: (expr: Expression, level: number) => 'compact' | 'regular' | 'interval' | 'set-builder';
}
/** The `serialize` handler of a custom LaTeX dictionary entry can be
* a function of this type.
*
* @category Latex Parsing and Serialization
*
*/
export type SerializeHandler = (serializer: Serializer, expr: Expression) => string;