automata/web/root/src/automata.ts
2026-01-12 23:34:06 -05:00

202 lines
5.8 KiB
TypeScript

export type Machine = Fa | Pda | Tm;
export function parse_machine_from_json(json: string): Machine {
const machine: Machine = JSON.parse(json);
machine.states = new Map(Object.entries(machine.states));
if (machine.alphabet) {
machine.alphabet = new Map(Object.entries(machine.alphabet));
}
if (machine.final_states) {
machine.final_states = new Map(Object.entries(machine.final_states));
}
// deno-lint-ignore no-explicit-any
const transitions = machine.transitions as any as [any, any];
machine.transitions = new Map();
for (const [key, value] of transitions) {
machine.transitions.set(key, value);
}
machine.edges = new Map();
machine.transitions_components = new Map();
switch (machine.type) {
case "fa":
{
for (const [from, tos] of machine.transitions) {
for (const to of tos) {
const layer_0 = machine.transitions_components;
if (!layer_0.has(from.state)) layer_0.set(from.state, new Map());
const layer_1 = machine.transitions_components.get(from.state)!;
if (!layer_1.has(from.letter)) layer_1.set(from.letter, []);
const layer_2 = layer_1.get(from.letter)!;
layer_2.push(to);
const edge = from.state + "#" + to.state;
if (!machine.edges.has(edge)) machine.edges.set(edge, []);
machine.edges.get(edge)?.push({
repr: from.letter ? from.letter : "ε",
function: to.function,
transition: to.transition,
});
}
}
}
break;
case "pda":
{
machine.symbols = new Map(Object.entries(machine.symbols));
for (const [from, tos] of machine.transitions) {
for (const to of tos) {
const layer_0 = machine.transitions_components;
if (!layer_0.has(from.state)) layer_0.set(from.state, new Map());
const layer_1 = machine.transitions_components.get(from.state)!;
if (!layer_1.has(from.symbol)) layer_1.set(from.symbol, new Map());
const layer_2 = layer_1.get(from.symbol)!;
if (!layer_2.has(from.letter)) layer_2.set(from.letter, []);
const layer_3 = layer_2.get(from.letter)!;
layer_3.push(to);
const edge = from.state + "#" + to.state;
if (!machine.edges.has(edge)) machine.edges.set(edge, []);
machine.edges.get(edge)?.push({
repr: (from.letter ? from.letter : "ε") + "," + from.symbol +
"->[" + to.stack + "]",
function: to.function,
transition: to.transition,
});
}
}
}
break;
case "tm":
{
machine.symbols = new Map(Object.entries(machine.symbols));
for (const [from, tos] of machine.transitions) {
for (const to of tos) {
const layer_0 = machine.transitions_components;
if (!layer_0.has(from.state)) layer_0.set(from.state, new Map());
const layer_1 = machine.transitions_components.get(from.state)!;
if (!layer_1.has(from.symbol)) layer_1.set(from.symbol, []);
const layer_2 = layer_1.get(from.symbol)!;
layer_2.push(to);
const edge = from.state + "#" + to.state;
if (!machine.edges.has(edge)) machine.edges.set(edge, []);
machine.edges.get(edge)?.push({
repr: from.symbol + "->" + to.symbol + "," + to.direction,
function: to.function,
transition: to.transition,
});
}
}
}
break;
}
return machine;
}
export type State = string;
export type Symbol = string;
export type Letter = string;
export type Span = readonly [number, number];
export type StateInfo = { readonly definition: Span };
export type LetterInfo = { readonly definition: Span };
export type SymbolInfo = { readonly definition: Span };
export type FaTransFrom = {
state: State;
letter: Letter | null;
};
export type FaTransTo = {
readonly state: State;
readonly transition: Span;
readonly function: Span;
};
export type Edge = {
readonly repr: string;
readonly function: Span;
readonly transition: Span;
};
export type Fa = {
type: "fa";
initial_state: State;
states: Map<State, StateInfo>;
alphabet: Map<Letter, LetterInfo>;
final_states: Map<State, StateInfo>;
transitions: Map<FaTransFrom, FaTransTo[]>;
transitions_components: Map<State, Map<Letter | null, FaTransTo[]>>;
edges: Map<string, Edge[]>;
};
export type PdaTransFrom = {
readonly state: State;
readonly letter: Letter | null;
readonly symbol: Symbol;
};
export type PdaTransTo = {
readonly state: State;
readonly stack: readonly Symbol[];
readonly transition: Span;
readonly function: Span;
};
export type Pda = {
type: "pda";
initial_state: State;
initial_stack: Symbol;
states: Map<State, StateInfo>;
symbols: Map<Symbol, SymbolInfo>;
alphabet: Map<Letter, LetterInfo>;
final_states: Map<State, StateInfo> | null;
transitions: Map<PdaTransFrom, PdaTransTo[]>;
transitions_components: Map<
State,
Map<Symbol, Map<Letter | null, PdaTransTo[]>>
>;
edges: Map<string, Edge[]>;
};
export type TmTransFrom = {
readonly state: State;
readonly symbol: Symbol;
};
export type TmTransTo = {
readonly state: State;
readonly symbol: Symbol;
readonly direction: "<" | ">" | "_";
readonly transition: Span;
readonly function: Span;
};
export type Tm = {
type: "tm";
initial_state: State;
blank_symbol: Symbol;
states: Map<State, StateInfo>;
symbols: Map<Symbol, SymbolInfo>;
alphabet: Map<Letter, LetterInfo>;
final_states: Map<State, StateInfo>;
transitions: Map<TmTransFrom, TmTransTo[]>;
transitions_components: Map<State, Map<Symbol, TmTransTo[]>>;
edges: Map<string, Edge[]>;
};