UNPKG

antlr4ng

Version:

Alternative JavaScript/TypeScript runtime for ANTLR4

306 lines (301 loc) 10.5 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/atn/LexerActionExecutor.ts var LexerActionExecutor_exports = {}; __export(LexerActionExecutor_exports, { LexerActionExecutor: () => LexerActionExecutor }); module.exports = __toCommonJS(LexerActionExecutor_exports); // src/utils/MurmurHash.ts var c1 = 3432918353; var c2 = 461845907; var r1 = 15; var r2 = 13; var m = 5; var n = 3864292196; var MurmurHash = class _MurmurHash { static { __name(this, "MurmurHash"); } static defaultSeed = 701; constructor() { } /** * Initialize the hash using the specified {@code seed}. * * @param seed the seed * * @returns the intermediate hash value */ static initialize(seed = _MurmurHash.defaultSeed) { return seed; } static updateFromComparable(hash, value) { return this.update(hash, value?.hashCode() ?? 0); } /** * Update the intermediate hash value for the next input {@code value}. * * @param hash The intermediate hash value. * @param value the value to add to the current hash. * * @returns the updated intermediate hash value */ static update(hash, value) { value = Math.imul(value, c1); value = value << r1 | value >>> 32 - r1; value = Math.imul(value, c2); hash = hash ^ value; hash = hash << r2 | hash >>> 32 - r2; hash = Math.imul(hash, m) + n; return hash; } /** * Apply the final computation steps to the intermediate value {@code hash} * to form the final result of the MurmurHash 3 hash function. * * @param hash The intermediate hash value. * @param entryCount The number of values added to the hash. * * @returns the final hash result */ static finish(hash, entryCount) { hash ^= entryCount * 4; hash ^= hash >>> 16; hash = Math.imul(hash, 2246822507); hash ^= hash >>> 13; hash = Math.imul(hash, 3266489909); hash ^= hash >>> 16; return hash; } /** * An all-in-one convenience method to compute a hash for a single value. * * @param value The value to hash. * @param seed The seed for the hash value. * * @returns The computed hash. */ static hashCode(value, seed) { return _MurmurHash.finish(_MurmurHash.update(seed ?? _MurmurHash.defaultSeed, value), 1); } }; // src/atn/LexerIndexedCustomAction.ts var LexerIndexedCustomAction = class _LexerIndexedCustomAction { static { __name(this, "LexerIndexedCustomAction"); } offset; action; actionType; isPositionDependent = true; cachedHashCode; constructor(offset, action) { this.actionType = action.actionType; this.offset = offset; this.action = action; } /** * This method calls {@link execute} on the result of {@link getAction} * using the provided `lexer`. */ execute(lexer) { this.action.execute(lexer); } hashCode() { if (this.cachedHashCode === void 0) { let hash = MurmurHash.initialize(); hash = MurmurHash.update(hash, this.offset); hash = MurmurHash.updateFromComparable(hash, this.action); this.cachedHashCode = MurmurHash.finish(hash, 2); } return this.cachedHashCode; } equals(other) { if (this === other) { return true; } if (!(other instanceof _LexerIndexedCustomAction)) { return false; } return this.offset === other.offset && this.action === other.action; } }; // src/atn/LexerActionExecutor.ts var LexerActionExecutor = class _LexerActionExecutor { static { __name(this, "LexerActionExecutor"); } lexerActions; actionType; isPositionDependent = false; cachedHashCode; /** * Represents an executor for a sequence of lexer actions which traversed during * the matching operation of a lexer rule (token). * * The executor tracks position information for position-dependent lexer actions * efficiently, ensuring that actions appearing only at the end of the rule do * not cause bloating of the {@link DFA} created for the lexer. */ constructor(lexerActions) { this.actionType = -1; this.lexerActions = lexerActions ?? []; return this; } /** * Creates a {@link LexerActionExecutor} which executes the actions for * the input `lexerActionExecutor` followed by a specified * `lexerAction`. * * @param lexerActionExecutor The executor for actions already traversed by * the lexer while matching a token within a particular * {@link LexerATNConfig}. If this is `null`, the method behaves as * though it were an empty executor. * @param lexerAction The lexer action to execute after the actions * specified in `lexerActionExecutor`. * * @returns {LexerActionExecutor} A {@link LexerActionExecutor} for executing the combine actions * of `lexerActionExecutor` and `lexerAction`. */ static append(lexerActionExecutor, lexerAction) { if (lexerActionExecutor === null) { return new _LexerActionExecutor([lexerAction]); } const lexerActions = lexerActionExecutor.lexerActions.concat([lexerAction]); return new _LexerActionExecutor(lexerActions); } /** * Creates a {@link LexerActionExecutor} which encodes the current offset * for position-dependent lexer actions. * * Normally, when the executor encounters lexer actions where * {@link LexerAction//isPositionDependent} returns `true`, it calls * {@link IntStream.seek} on the input {@link CharStream} to set the input * position to the *end* of the current token. This behavior provides * for efficient DFA representation of lexer actions which appear at the end * of a lexer rule, even when the lexer rule matches a variable number of * characters. * * Prior to traversing a match transition in the ATN, the current offset * from the token start index is assigned to all position-dependent lexer * actions which have not already been assigned a fixed offset. By storing * the offsets relative to the token start index, the DFA representation of * lexer actions which appear in the middle of tokens remains efficient due * to sharing among tokens of the same length, regardless of their absolute * position in the input stream. * * If the current executor already has offsets assigned to all * position-dependent lexer actions, the method returns `this`. * * @param offset The current offset to assign to all position-dependent * lexer actions which do not already have offsets assigned. * * @returns {LexerActionExecutor} A {@link LexerActionExecutor} which stores input stream offsets * for all position-dependent lexer actions. */ fixOffsetBeforeMatch(offset) { let updatedLexerActions = null; for (let i = 0; i < this.lexerActions.length; i++) { if (this.lexerActions[i].isPositionDependent && !(this.lexerActions[i] instanceof LexerIndexedCustomAction)) { if (updatedLexerActions === null) { updatedLexerActions = this.lexerActions.concat([]); } updatedLexerActions[i] = new LexerIndexedCustomAction( offset, this.lexerActions[i] ); } } if (updatedLexerActions === null) { return this; } else { return new _LexerActionExecutor(updatedLexerActions); } } /** * Execute the actions encapsulated by this executor within the context of a * particular {@link Lexer}. * * This method calls {@link IntStream.seek} to set the position of the * `input` {@link CharStream} prior to calling * {@link LexerAction.execute} on a position-dependent action. Before the * method returns, the input position will be restored to the same position * it was in when the method was invoked. * * @param lexer The lexer instance. * @param input The input stream which is the source for the current token. * When this method is called, the current {@link IntStream.index} for * `input` should be the start of the following token, i.e. 1 * character past the end of the current token. * @param startIndex The token start index. This value may be passed to * {@link IntStream.seek} to set the `input` position to the beginning * of the token. */ execute(lexer, input, startIndex) { if (input === void 0 || startIndex === void 0) { return; } let requiresSeek = false; const stopIndex = input.index; try { for (const lexerAction of this.lexerActions) { let action = lexerAction; if (lexerAction instanceof LexerIndexedCustomAction) { const offset = lexerAction.offset; input.seek(startIndex + offset); action = lexerAction.action; requiresSeek = startIndex + offset !== stopIndex; } else if (lexerAction.isPositionDependent) { input.seek(stopIndex); requiresSeek = false; } action.execute(lexer); } } finally { if (requiresSeek) { input.seek(stopIndex); } } } hashCode() { if (this.cachedHashCode === void 0) { let hashCode = MurmurHash.initialize(7); for (const lexerAction of this.lexerActions) { hashCode = MurmurHash.update(hashCode, lexerAction.hashCode()); } this.cachedHashCode = MurmurHash.finish(hashCode, this.lexerActions.length); } return this.cachedHashCode; } equals(other) { if (this === other) { return true; } if (this.cachedHashCode !== other.cachedHashCode) { return false; } if (this.lexerActions.length !== other.lexerActions.length) { return false; } return this.lexerActions.every((action, index) => { return action.equals(other.lexerActions[index]); }); } };