You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.4 KiB
JavaScript
126 lines
3.4 KiB
JavaScript
// @flow
|
|
|
|
import {Token} from "./Token";
|
|
import type Namespace from "./Namespace";
|
|
import type {Mode} from "./types";
|
|
|
|
/**
|
|
* Provides context to macros defined by functions. Implemented by
|
|
* MacroExpander.
|
|
*/
|
|
export interface MacroContextInterface {
|
|
mode: Mode;
|
|
|
|
/**
|
|
* Object mapping macros to their expansions.
|
|
*/
|
|
macros: Namespace<MacroDefinition>;
|
|
|
|
/**
|
|
* Returns the topmost token on the stack, without expanding it.
|
|
* Similar in behavior to TeX's `\futurelet`.
|
|
*/
|
|
future(): Token;
|
|
|
|
/**
|
|
* Remove and return the next unexpanded token.
|
|
*/
|
|
popToken(): Token;
|
|
|
|
/**
|
|
* Consume all following space tokens, without expansion.
|
|
*/
|
|
consumeSpaces(): void;
|
|
|
|
/**
|
|
* Expand the next token only once if possible.
|
|
*/
|
|
expandOnce(expandableOnly?: boolean): number | boolean;
|
|
|
|
/**
|
|
* Expand the next token only once (if possible), and return the resulting
|
|
* top token on the stack (without removing anything from the stack).
|
|
* Similar in behavior to TeX's `\expandafter\futurelet`.
|
|
*/
|
|
expandAfterFuture(): Token;
|
|
|
|
/**
|
|
* Recursively expand first token, then return first non-expandable token.
|
|
*/
|
|
expandNextToken(): Token;
|
|
|
|
/**
|
|
* Fully expand the given macro name and return the resulting list of
|
|
* tokens, or return `undefined` if no such macro is defined.
|
|
*/
|
|
expandMacro(name: string): Token[] | void;
|
|
|
|
/**
|
|
* Fully expand the given macro name and return the result as a string,
|
|
* or return `undefined` if no such macro is defined.
|
|
*/
|
|
expandMacroAsText(name: string): string | void;
|
|
|
|
/**
|
|
* Fully expand the given token stream and return the resulting list of
|
|
* tokens. Note that the input tokens are in reverse order, but the
|
|
* output tokens are in forward order.
|
|
*/
|
|
expandTokens(tokens: Token[]): Token[];
|
|
|
|
/**
|
|
* Consume an argument from the token stream, and return the resulting array
|
|
* of tokens and start/end token.
|
|
*/
|
|
consumeArg(delims?: ?string[]): MacroArg;
|
|
|
|
/**
|
|
* Consume the specified number of arguments from the token stream,
|
|
* and return the resulting array of arguments.
|
|
*/
|
|
consumeArgs(numArgs: number): Token[][];
|
|
|
|
/**
|
|
* Determine whether a command is currently "defined" (has some
|
|
* functionality), meaning that it's a macro (in the current group),
|
|
* a function, a symbol, or one of the special commands listed in
|
|
* `implicitCommands`.
|
|
*/
|
|
isDefined(name: string): boolean;
|
|
|
|
/**
|
|
* Determine whether a command is expandable.
|
|
*/
|
|
isExpandable(name: string): boolean;
|
|
}
|
|
|
|
export type MacroArg = {
|
|
tokens: Token[],
|
|
start: Token,
|
|
end: Token
|
|
};
|
|
|
|
/** Macro tokens (in reverse order). */
|
|
export type MacroExpansion = {
|
|
tokens: Token[],
|
|
numArgs: number,
|
|
delimiters?: string[][],
|
|
unexpandable?: boolean, // used in \let
|
|
};
|
|
|
|
export type MacroDefinition = string | MacroExpansion |
|
|
(MacroContextInterface => (string | MacroExpansion));
|
|
export type MacroMap = {[string]: MacroDefinition};
|
|
|
|
/**
|
|
* All registered global/built-in macros.
|
|
* `macros.js` exports this same dictionary again and makes it public.
|
|
* `Parser.js` requires this dictionary via `macros.js`.
|
|
*/
|
|
export const _macros: MacroMap = {};
|
|
|
|
// This function might one day accept an additional argument and do more things.
|
|
export default function defineMacro(name: string, body: MacroDefinition) {
|
|
_macros[name] = body;
|
|
}
|