/****************************************************************************** * Copyright 2022 TypeFox GmbH * This program and the accompanying materials are made available under the * terms of the MIT License, which is available in the project root. ******************************************************************************/ import map from "lodash-es/map.js" import { ATNState, DecisionState } from "./atn.js" export interface DFA { start?: DFAState states: Record decision: number atnStartState: DecisionState } export interface DFAState { configs: ATNConfigSet edges: Record isAcceptState: boolean prediction: number } export const DFA_ERROR = {} as DFAState export interface ATNConfig { state: ATNState alt: number stack: ATNState[] } export class ATNConfigSet { private map: Record = {} private configs: ATNConfig[] = [] uniqueAlt: number | undefined get size(): number { return this.configs.length } finalize(): void { // Empties the map to free up memory this.map = {} } add(config: ATNConfig): void { const key = getATNConfigKey(config) // Only add configs which don't exist in our map already // While this does not influence the actual algorithm, adding them anyway would massively increase memory consumption if (!(key in this.map)) { this.map[key] = this.configs.length this.configs.push(config) } } get elements(): readonly ATNConfig[] { return this.configs } get alts(): number[] { return map(this.configs, (e) => e.alt) } get key(): string { let value = "" for (const k in this.map) { value += k + ":" } return value } } export function getATNConfigKey(config: ATNConfig, alt = true) { return `${alt ? `a${config.alt}` : ""}s${ config.state.stateNumber }:${config.stack.map((e) => e.stateNumber.toString()).join("_")}` }