123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /*************************************************************
- *
- * Copyright (c) 2017-2022 The MathJax Consortium
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * @fileoverview Singleton class for handling symbol maps.
- *
- * @author v.sorge@mathjax.org (Volker Sorge)
- */
- import {AbstractSymbolMap, SymbolMap} from './SymbolMap.js';
- import {ParseInput, ParseResult, ParseMethod} from './Types.js';
- // import {ParserConfiguration} from './Configuration.js';
- import {PrioritizedList} from '../../util/PrioritizedList.js';
- import {FunctionList} from '../../util/FunctionList.js';
- export type HandlerType = 'delimiter' | 'macro' | 'character' | 'environment';
- export type HandlerConfig = {[P in HandlerType]?: string[]};
- export type FallbackConfig = {[P in HandlerType]?: ParseMethod};
- export namespace MapHandler {
- let maps: Map<string, SymbolMap> = new Map();
- /**
- * Adds a new symbol map to the map handler. Might overwrite an existing
- * symbol map of the same name.
- *
- * @param {SymbolMap} map Registers a new symbol map.
- */
- export let register = function(map: SymbolMap): void {
- maps.set(map.name, map);
- };
- /**
- * Looks up a symbol map if it exists.
- *
- * @param {string} name The name of the symbol map.
- * @return {SymbolMap} The symbol map with the given name or null.
- */
- export let getMap = function(name: string): SymbolMap {
- return maps.get(name);
- };
- }
- /**
- * Class of symbol mappings that are active in a configuration.
- */
- export class SubHandler {
- private _configuration: PrioritizedList<SymbolMap> = new PrioritizedList<SymbolMap>();
- private _fallback: FunctionList = new FunctionList();
- /**
- * Adds a list of symbol maps to the handler.
- * @param {string[]} maps The names of the symbol maps to add.
- * @param {ParseMethod} fallback A fallback method.
- * @param {number} priority Optionally a priority.
- */
- public add(maps: string[], fallback: ParseMethod,
- priority: number = PrioritizedList.DEFAULTPRIORITY) {
- for (const name of maps.slice().reverse()) {
- let map = MapHandler.getMap(name);
- if (!map) {
- this.warn('Configuration ' + name + ' not found! Omitted.');
- return;
- }
- this._configuration.add(map, priority);
- }
- if (fallback) {
- this._fallback.add(fallback, priority);
- }
- }
- /**
- * Parses the given input with the first applicable symbol map.
- * @param {ParseInput} input The input for the parser.
- * @return {ParseResult} The output of the parsing function.
- */
- public parse(input: ParseInput): ParseResult {
- for (let {item: map} of this._configuration) {
- const result = map.parse(input);
- if (result) {
- return result;
- }
- }
- let [env, symbol] = input;
- Array.from(this._fallback)[0].item(env, symbol);
- }
- /**
- * Maps a symbol to its "parse value" if it exists.
- *
- * @param {string} symbol The symbol to parse.
- * @return {T} A boolean, Character, or Macro.
- */
- public lookup<T>(symbol: string): T {
- let map = this.applicable(symbol) as AbstractSymbolMap<T>;
- return map ? map.lookup(symbol) : null;
- }
- /**
- * Checks if a symbol is contained in one of the symbol mappings of this
- * configuration.
- *
- * @param {string} symbol The symbol to parse.
- * @return {boolean} True if the symbol is contained in the mapping.
- */
- public contains(symbol: string): boolean {
- return this.applicable(symbol) ? true : false;
- }
- /**
- * @override
- */
- public toString(): string {
- let names = [];
- for (let {item: map} of this._configuration) {
- names.push(map.name);
- }
- return names.join(', ');
- }
- /**
- * Retrieves the first applicable symbol map in the configuration.
- * @param {string} symbol The symbol to parse.
- * @return {SymbolMap} A map that can parse the symbol.
- */
- public applicable(symbol: string): SymbolMap {
- for (let {item: map} of this._configuration) {
- if (map.contains(symbol)) {
- return map;
- }
- }
- return null;
- }
- /**
- * Retrieves the map of the given name.
- * @param {string} name Name of the symbol map.
- * @return {SymbolMap} The map if it exists.
- */
- public retrieve(name: string): SymbolMap {
- for (let {item: map} of this._configuration) {
- if (map.name === name) {
- return map;
- }
- }
- return null;
- }
- /**
- * Prints a warning message.
- * @param {string} message The warning.
- */
- private warn(message: string) {
- console.log('TexParser Warning: ' + message);
- }
- }
- export class SubHandlers {
- private map = new Map<HandlerType, SubHandler>();
- /**
- * Adds a symbol map to the configuration if it exists.
- * @param {string} name of the symbol map.
- */
- public add(handlers: HandlerConfig, fallbacks: FallbackConfig,
- priority: number = PrioritizedList.DEFAULTPRIORITY): void {
- for (const key of Object.keys(handlers)) {
- let name = key as HandlerType;
- let subHandler = this.get(name);
- if (!subHandler) {
- subHandler = new SubHandler();
- this.set(name, subHandler);
- }
- subHandler.add(handlers[name], fallbacks[name], priority);
- }
- }
- /**
- * Setter for subhandlers.
- * @param {HandlerType} name The name of the subhandler.
- * @param {SubHandler} subHandler The subhandler.
- */
- public set(name: HandlerType, subHandler: SubHandler) {
- this.map.set(name, subHandler);
- }
- /**
- * Getter for subhandler.
- * @param {HandlerType} name Name of the subhandler.
- * @return {SubHandler} The subhandler by that name if it exists.
- */
- public get(name: HandlerType): SubHandler {
- return this.map.get(name);
- }
- /**
- * Retrieves a symbol map of the given name.
- * @param {string} name Name of the symbol map.
- * @return {SymbolMap} The map if it exists. O/w null.
- */
- public retrieve(name: string): SymbolMap {
- for (const handler of this.map.values()) {
- let map = handler.retrieve(name);
- if (map) {
- return map;
- }
- }
- return null;
- }
- /**
- * All names of registered subhandlers.
- * @return {IterableIterator<string>} Iterable list of keys.
- */
- public keys(): IterableIterator<string> {
- return this.map.keys();
- }
- }
|