moved frontend to event driven bus, added more simulation stuff

This commit is contained in:
Parker TenBroeck 2026-01-11 00:30:06 -05:00
parent c7309a75d9
commit 8c8bb103b2
17 changed files with 767 additions and 493 deletions

View file

@ -1,8 +1,6 @@
import { network, updateVisualization } from "./visualizer.ts";
export type Machine = Fa | Pda | Tm;
export function machine_from_json(json: string): Machine {
export function parse_machine_from_json(json: string): Machine {
const machine: Machine = JSON.parse(json);
machine.states = new Map(Object.entries(machine.states));
@ -202,219 +200,3 @@ export type Tm = {
edges: Map<string, Edge[]>;
};
export type SimStepResult = "pending" | "accept" | "reject";
export class FaState {
readonly state: State;
readonly position: number;
readonly input: string;
readonly accepted: boolean = false;
private repr!: string;
constructor(state: State, position: number, input: string){
this.state=state;
this.position=position;
this.input = input;
}
toString(): string{
if(!this.repr) this.repr = this.state + " " + this.position;
return this.repr
}
};
export class FaSim {
current_states: Map<string, FaState[]> = new Map();
accepted: FaState[] = []
step(): SimStepResult {
return "pending";
}
}
export class PdaState {
readonly state: State;
readonly stack: Symbol[];
readonly position: number;
readonly input: string;
readonly accepted: boolean = false
private repr!: string;
constructor(state: State, stack: Symbol[], position: number, input: string){
this.state=state;
this.stack=stack;
this.position=position;
this.input = input;
}
toString(): string{
if(!this.repr) this.repr = this.state + " [" + this.stack + "]" + " " + this.position;
return this.repr
}
};
export class PdaSim {
machine: Pda;
paths: PdaState[];
input: string;
current_states: Map<string, PdaState[]> = new Map();
accepted: PdaState[] = []
constructor(machine: Pda, input: string) {
this.machine = machine;
this.paths = [new PdaState(machine.initial_state, [machine.initial_stack], 0, input)];
this.current_states.set(machine.initial_state, [this.paths[0]])
this.input = input;
}
step(): SimStepResult {
if (this.paths.length == 0) return "reject";
if (this.accepted.length != 0) return "accept";
const paths: PdaState[] = [];
this.current_states.clear();
const push = (state: PdaState) => {
paths.push(state);
if (!this.current_states.has(state.state)) this.current_states.set(state.state, []);
this.current_states.get(state.state)?.push(state);
if (
state.position == this.input.length && this.machine.final_states &&
this.machine.final_states.has(state.state)
||
state.position == this.input.length && !this.machine.final_states &&
state.stack.length == 1 && state.stack[0] == this.machine.initial_stack
) {
// @ts-expect-error sillllyyyy
state.accepted = true
this.accepted.push(state);
}
};
for (const path of this.paths) {
const stack = path.stack.pop()!;
const letter_map = this.machine.transitions_components.get(path.state)
?.get(stack);
if (!letter_map) continue;
for (const to of letter_map.get(null) ?? []) {
push(new PdaState(to.state, path.stack.concat(to.stack), path.position, this.input));
}
if (path.position >= this.input.length) continue;
const char = this.input.charAt(path.position);
for (const to of letter_map.get(char) ?? []) {
push(new PdaState(to.state, path.stack.concat(to.stack), path.position+1, this.input));
}
}
this.paths = paths;
if (this.paths.length == 0) return "reject";
if (this.accepted.length != 0) return "accept";
return "pending"
}
}
export class TmState{
readonly state: State;
readonly tape: Symbol[];
readonly position: number;
readonly input: string;
readonly accepted: boolean = false
private repr!: string;
constructor(state: State, tape: Symbol[], position: number, input: string){
this.state=state;
this.tape = tape;
this.position=position;
this.input = input;
}
toString(): string{
if(!this.repr) this.repr = this.state + " " + this.position;
return this.repr
}
}
export class TmSim {
current_states: Map<string, TmState[]> = new Map();
accepted: TmState[] = []
step(): SimStepResult {
return "pending"
}
}
export type Sim = FaSim | PdaSim | TmSim | null
export let sim: Sim = null;
export let automaton: Machine = {
type: "fa",
alphabet: new Map(),
final_states: new Map(),
initial_state: "",
states: new Map(),
transitions: new Map(),
transitions_components: new Map(),
edges: new Map(),
};
export function clearSimulation(){
setSimulation(null);
}
export function setSimulation(sim_: Sim){
sim = sim_;
network.redraw()
}
export function setAutomaton(auto: Machine) {
automaton = auto;
sim = null;
updateVisualization()
}
export function clearAutomaton() {
setAutomaton({
type: "fa",
alphabet: new Map(),
final_states: new Map(),
initial_state: "",
states: new Map(),
transitions: new Map(),
transitions_components: new Map(),
edges: new Map(),
});
}
export function stepSimulation(): void {
if (sim) {
console.log(sim.step());
}
network.redraw()
}
export function resetSimulation(): void {
switch (automaton.type) {
case "fa":
break;
case "pda":
setSimulation(new PdaSim(automaton as Pda, "aabbaabbaa"));
break;
case "tm":
break;
}
}