import { bus } from "./bus.ts"; export type Category = | "Tutorial" | "DFA" | "NFA" | "DPDA" | "NPDA" | "TM" | "NTM" | "CFG"; export class Example { readonly category: Category; readonly title: string; readonly machine: string; constructor(category: Category, title: string, machine: string) { this.category = category; this.title = title; this.machine = machine; } } export const examples: readonly Example[] = [ new Example( "Tutorial", "DFA", `// strings over a,b which start and end with different letters type = DFA // type of machine DFA, NFA, DPDA, NPDA, DTM, NTM Q = {q0, qa, qa', qb, qb'} // set of states E = {a, b} // alphabet F = {qa', qb'} // set of final states q0 = q0 // initial state // transition function (state, letter) -> state d(q0, a) = qa d(q0, b) = qb d(qa, a) = qa d(qa, b) = qa' d(qa', a) = qa d(qa', b) = qa' d(qb, a) = qb' d(qb, b) = qb d(qb', a) = qb' d(qb', b) = qb`, ), new Example( "Tutorial", "NFA", `// strings of 1's whos length is divisible by two or three and longer than 1 type = NFA // type of machine Q = {q0, q2, q2f, q3, q3', q3f} // set of states E = {1} // alphabet F = {q2f, q3f} // set of final states q0 = q0 // initial state // transition function (state, letter) -> state // non deterministic part d(q0, 1) = q2 d(q0, 1) = q3 d(q2, 1) = q2f d(q2f, 1) = q2 d(q3, 1) = q3' d(q3', 1) = q3f d(q3f, 1) = q3 `, ), new Example( "Tutorial", "NFA with epsilon", `// strings containing only all a's, or all b's, or all c's type = NFA // type of machine Q = {q0, qa, qb, qc} // set of states E = {a, b, c} // alphabet F = {qa, qb, qc} // set of final states q0 = q0 // initial state // transition function (state, letter) -> state // non deterministic part d(q0, epsilon) = qa d(q0, epsilon) = qb d(q0, epsilon) = qc d(qa, a) = qa d(qb, b) = qb d(qc, c) = qc `, ), new Example( "Tutorial", "DPDA Final State", `// Accept strings over a,b of the form a^nb^k where n != k and n,k > 0 type = DPDA Q = {q0, qas, qeq, qmb, qlb} // states E = {a, b} // alphabet T = {z0, A} // stack F = {qmb, qlb} // final states accept = F // accept by final state q0 = q0 z0 = z0 d(q0, a, z0) = (qas, z0) d(qas, a, z0) = (qas, [A z0]) d(qas, b, z0) = (qeq, z0) d(qas, a, A) = (qas, [A A]) d(qas, b, A) = (qlb, ~) d(qlb, b, A) = (qlb, ~) d(qlb, b, z0) = (qeq, z0) d(qeq, b, z0) = (qmb, z0) d(qmb, b, z0) = (qmb, z0)`, ), new Example( "Tutorial", "DPDA Empty Stack", `// Accept strings over a,b which are of form a^n b^n type = DPDA Q = {qa, qb} // states E = {a, b} // alphabet T = {Z0, A} // stack accept = N // accept by empty stack q0 = qa z0 = Z0 // build stack of A's (equal to a's encountered) d(qa, a, Z0) = (qa, [A Z0]) d(qa, a, A) = (qa, [A A]) // transition to b state once a b is encountered d(qa, b, A) = (qb, ~) // consume b's until A's run out d(qb, b, A) = (qb, ~)`, ), // new Example( // "Tutorial", // "NPDA Final State", // ``, // ), new Example( "Tutorial", "NPDA Empty Stack", `// Accept all strings over a,b which are spelt the same backwards and forwards type=NPDA Q = {q0, q1} // states E = {a, b} // alphabet T = {Z0, A, B} // stack accept = E // accept by empty stack q0 = q0 z0 = Z0 // push letters we see to stack d(q0, a, Z0) = (q0, [A Z0]) d(q0, b, Z0) = (q0, [B Z0]) d(q0, a, A) = (q0, [A A]) d(q0, b, A) = (q0, [B A]) d(q0, a, B) = (q0, [A B]) d(q0, b, B) = (q0, [B B]) // transition to q1 // even d(q0, epsilon, Z0) = { (q1, Z0) } d(q0, epsilon, A) = { (q1, A) } d(q0, epsilon, B) = { (q1, B) } // odd d(q0, a, Z0) = { (q1, Z0) } d(q0, a, A) = { (q1, A) } d(q0, a, B) = { (q1, B) } d(q0, b, Z0) = { (q1, Z0) } d(q0, b, A) = { (q1, A) } d(q0, b, B) = { (q1, B) } // consume stack until empty d(q1, a, A) = { (q1, epsilon) } d(q1, b, B) = { (q1, epsilon) }`, ), new Example( "Tutorial", "TM", `// Accept strings over a,b,c of the form a^n b^n c^n, n > 0 type = TM Q = {q1, q2, q3, q4, q5, q6, qf} // states T = {a, b,c, B, X, Y, Z} // stack F = {qf} // final states q0 = q1 B = B d(q1, a) = (q2, X, R) d(q1, Y) = (q5, Y, R) d(q2, a) = (q2, a, R) d(q2, b) = (q3, Y, R) d(q2, Y) = (q2, Y, R) d(q3, b) = (q3, b, R) d(q3, c) = (q4, Z, L) d(q3, Z) = (q3, Z, R) d(q4, a) = (q4, a, L) d(q4, b) = (q4, b, L) d(q4, X) = (q1, X, R) d(q4, Y) = (q4, Y, L) d(q4, Z) = (q4, Z, L) d(q5, Y) = (q5, Y, R) d(q5, Z) = (q6, Z, R) d(q6, B) = (qf, B, R) d(q6, Z) = (q6, Z, R)`, ), // new Example( // "Tutorial", // "NTM", // ``, // ), new Example( "DFA", "modulo", `type=DFA E={1,2,3} Q={q0, q1, q2, q3, q4} F = {q0} q0=q0 d(q0, 1) = q1 d(q1, 1) = q2 d(q2, 1) = q3 d(q3, 1) = q4 d(q4, 1) = q0 d(q0, 2) = q2 d(q1, 2) = q3 d(q2, 2) = q4 d(q3, 2) = q0 d(q4, 2) = q1 d(q0, 3) = q3 d(q1, 3) = q4 d(q2, 3) = q0 d(q3, 3) = q1 d(q4, 3) = q2`, ), new Example( "DPDA", "unequal", `type = DPDA Q = {q0, qas, qeq, qmb, qlb} // states E = {a, b} // alphabet T = {z0, A} // stack F = {qmb, qlb} // final states accept = F // accept by final state q0 = q0 z0 = z0 d(q0, a, z0) = (qas, z0) d(qas, a, z0) = (qas, [A z0]) d(qas, b, z0) = (qeq, z0) d(qas, a, A) = (qas, [A A]) d(qas, b, A) = (qlb, ~) d(qlb, b, A) = (qeq, ~) d(qlb, b, z0) = (qeq, z0) d(qeq, b, z0) = (qmb, z0) d(qmb, b, z0) = (qmb, z0)`, ), new Example( "NPDA", "palindrome", `type=NPDA Q = {q0, q1} // states E = {a, b} // alphabet T = {z0, A, B} // stack accept = E // accept by empty stack q0 = q0 z0 = z0 // push letters we see to stack d(q0, a, z0) = (q0, [A z0]) d(q0, b, z0) = (q0, [B z0]) d(q0, a, A) = (q0, [A A]) d(q0, b, A) = (q0, [B A]) d(q0, a, B) = (q0, [A B]) d(q0, b, B) = (q0, [B B]) // transition to q1 // even d(q0, epsilon, z0) = { (q1, z0) } d(q0, epsilon, A) = { (q1, A) } d(q0, epsilon, B) = { (q1, B) } // odd d(q0, a, z0) = { (q1, z0) } d(q0, a, A) = { (q1, A) } d(q0, a, B) = { (q1, B) } d(q0, b, z0) = { (q1, z0) } d(q0, b, A) = { (q1, A) } d(q0, b, B) = { (q1, B) } // consume stack until empty d(q1, a, A) = { (q1, epsilon) } d(q1, b, B) = { (q1, epsilon) }`, ), new Example( "NPDA", "kleen star stack", `type=NPDA Q = {q0, q1} // states E = {a, b} // alphabet T = {z0, A, B} // stack accept = E // accept by empty stack q0 = q0 z0 = z0 // construct all possible permutations of A's and B's d(q0, epsilon, z0) = { (q0, [A z0]), (q0, [B z0]) } d(q0, epsilon, A) = { (q0, [A A]), (q0, [B A]) } d(q0, epsilon, B) = { (q0, [A B]), (q0, [B B]) } // transition to q1 d(q0, epsilon, z0) = { (q1, z0) } d(q0, epsilon, A) = { (q1, A) } d(q0, epsilon, B) = { (q1, B) } // consume stack until empty d(q1, a, A) = { (q1, epsilon) } d(q1, b, B) = { (q1, epsilon) }`, ), new Example("TM", "a^nb^n", `// accepts all strings on {a,b}+ of the form anbn type = TM Q = { q0, q1, q2, q3, q4 } // set of internal states F = { q4 } // set of final states T = { a, b, X, Y, B } // tape alphabet B = B // the blank symbol (tape initializer symbol) q0 = q0 // initial state d(q0,a)=(q1,x,R) d(q1,a)=(q1,a,R) d(q1,Y)=(q1,y,R) d(q1,b)=(q2,y,L) d(q2,Y)=(q2,y,L) d(q2,a)=(q2,a,L) d(q2,X)=(q0,x,R) d(q0,Y)=(q3,y,R) d(q3,Y)=(q3,y,R) d(q3,B)=(q4,B,R) `), // new Example("CFG", "definition", // `// CFG's aren't supported yet, and this definition is not complete. // // This is the definition for the grammar the definition has itself // type=CFG // S -> TopLevel | TopLevel S // TopLevel -> Ident "=" Item // Item // TopLevel -> Ident Tuple "=" Item // Transition Functions // TopLevel -> Production | Table // Item -> Symbol | String | Tuple | List // Symbol -> Ident | "~" // String -> "\"" "\"" // Tuple -> "(" ItemList ")" // List -> "{" ItemList "}" | "[" ItemList "]" // ItemList -> ~ | Item ItemList | Item "," ItemList // Production -> ProductionGroup "->" ProductionGroupList // ProductionGroupList -> ProductionGroup | ProductionGroupList "|" ProductionGroup // ProductionGroup -> ProductionUnit | ProductionGroup ProductionUnit // ProductionUnit -> Ident | "~" | String // `) ]; const CATEGORY_ORDER: Category[] = [ "Tutorial", "DFA", "NFA", "DPDA", "NPDA", "TM", "NTM", "CFG", ]; function buildExamplesDropdown( selectEl: HTMLSelectElement, examples: readonly Example[], onPick?: (ex: Example) => void, ) { // Clear everything except the first placeholder option (if present) const keepFirstPlaceholder = selectEl.options.length > 0 && selectEl.options[0].disabled && selectEl.options[0].value === ""; selectEl.innerHTML = ""; if (keepFirstPlaceholder) { const placeholder = document.createElement("option"); placeholder.value = ""; placeholder.disabled = true; placeholder.selected = true; placeholder.textContent = "Choose an example…"; selectEl.appendChild(placeholder); } // Group examples by category const grouped = new Map(); for (const ex of examples) { if (!grouped.has(ex.category)) grouped.set(ex.category, []); grouped.get(ex.category)!.push(ex); } // Optional: sort titles within each group for (const [cat, list] of grouped) { // list.sort((a, b) => a.title.localeCompare(b.title)); grouped.set(cat, list); } // Create optgroups in your preferred order (and then any extras) const categoriesToRender: Category[] = [ ...CATEGORY_ORDER.filter((c) => grouped.has(c)), ...Array.from(grouped.keys()).filter((c) => !CATEGORY_ORDER.includes(c)) .sort(), ]; // We'll store a stable reference via an index into the examples array // (simplest + avoids encoding large machine strings into