mirror of
https://github.com/ParkerTenBroeck/automata.git
synced 2026-06-07 05:28:45 -04:00
Merge branch 'main' into gh-pages
This commit is contained in:
commit
d644ce8528
10 changed files with 160 additions and 106 deletions
|
|
@ -229,7 +229,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(previous) = self
|
||||
|
|
@ -258,7 +258,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if self.states.contains_key(&State(ident)) {
|
||||
|
|
@ -366,7 +366,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
|||
};
|
||||
|
||||
for item in list {
|
||||
let Some(next_state) = item.expect_ident(self.ctx) else {
|
||||
let Some(next_state) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
let next_state = Spanned(next_state, item.1);
|
||||
|
|
@ -413,11 +413,11 @@ impl<'a> Spanned<&ast::Tuple<'a>> {
|
|||
ctx: &mut Context<'a>,
|
||||
) -> Option<(Spanned<&'a str>, Spanned<ast::Symbol<'a>>)> {
|
||||
match &self.0.0[..] {
|
||||
[
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
||||
Spanned(ast::Item::Symbol(letter), letter_span),
|
||||
] => {
|
||||
return Some((Spanned(state, *state_span), Spanned(*letter, *letter_span)));
|
||||
[state, letter]
|
||||
if let Some(state) = state.string_weak()
|
||||
&& let Some(letter) = letter.sym_weak() =>
|
||||
{
|
||||
return Some((state, letter));
|
||||
}
|
||||
_ => {
|
||||
_ = ctx.emit_error(
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
|||
.emit_error("accept by already set", top_level)
|
||||
.emit_info("previously defined here", previous);
|
||||
}
|
||||
let Some(by) = item.expect_ident(self.ctx) else {
|
||||
let Some(by) = item.expect_ident_weak(self.ctx) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -343,7 +343,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(previous) = self
|
||||
|
|
@ -372,7 +372,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(previous) = self
|
||||
|
|
@ -401,7 +401,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if self.states.contains_key(&State(ident)) {
|
||||
|
|
@ -562,7 +562,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
|||
if matches!(symbol.0, ast::Item::Symbol(Sym::Epsilon(_))) {
|
||||
return None;
|
||||
}
|
||||
let ident = symbol.expect_ident(self.ctx)?;
|
||||
let ident = symbol.expect_ident_weak(self.ctx)?;
|
||||
|
||||
if !self.symbols.contains_key(&Symbol(ident)) {
|
||||
self.ctx
|
||||
|
|
@ -611,16 +611,12 @@ impl<'a, 'b> Spanned<&'b ast::Tuple<'a>> {
|
|||
ctx: &mut Context<'a>,
|
||||
) -> Option<(Spanned<&'a str>, Spanned<ast::Symbol<'a>>, Spanned<&'a str>)> {
|
||||
match &self.0.0[..] {
|
||||
[
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
||||
Spanned(ast::Item::Symbol(letter), letter_span),
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(symbol)), symbol_span),
|
||||
] => {
|
||||
return Some((
|
||||
Spanned(state, *state_span),
|
||||
Spanned(*letter, *letter_span),
|
||||
Spanned(symbol, *symbol_span),
|
||||
));
|
||||
[state, letter, symbol]
|
||||
if let Some(state) = state.string_weak()
|
||||
&& let Some(letter) = letter.sym_weak()
|
||||
&& let Some(symbol) = symbol.string_weak() =>
|
||||
{
|
||||
return Some((state, letter, symbol));
|
||||
}
|
||||
_ => {
|
||||
_ = ctx.emit_error(
|
||||
|
|
@ -636,11 +632,8 @@ impl<'a, 'b> Spanned<&'b ast::Tuple<'a>> {
|
|||
ctx: &mut Context<'a>,
|
||||
) -> Option<(Spanned<&'a str>, &'b [Spanned<ast::Item<'a>>])> {
|
||||
match &self.0.0[..] {
|
||||
[
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
||||
list,
|
||||
] => {
|
||||
return Some((Spanned(state, *state_span), list.list_weak()));
|
||||
[state, list] if let Some(state) = state.string_weak() => {
|
||||
return Some((state, list.list_weak()));
|
||||
}
|
||||
_ => _ = ctx.emit_error("expected PDA transition (state, symbol|[symbol])", self.1),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(previous) = self
|
||||
|
|
@ -282,7 +282,7 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(previous) = self
|
||||
|
|
@ -311,7 +311,7 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
|||
return;
|
||||
};
|
||||
for item in list {
|
||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
||||
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||
continue;
|
||||
};
|
||||
if self.states.contains_key(&State(ident)) {
|
||||
|
|
@ -413,6 +413,13 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
|||
.emit_error("transition state not defined as state", to_state.1);
|
||||
continue;
|
||||
};
|
||||
if !self.symbols.contains_key(&Symbol(to_tape.0)) {
|
||||
self.ctx.emit_error(
|
||||
"transition tape symbol not defined as tape symbol",
|
||||
to_tape.1,
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
let entry: &mut _ = self
|
||||
.transitions
|
||||
|
|
@ -452,11 +459,11 @@ impl<'a> Spanned<&ast::Tuple<'a>> {
|
|||
ctx: &mut Context<'a>,
|
||||
) -> Option<(Spanned<&'a str>, Spanned<&'a str>)> {
|
||||
match &self.0.0[..] {
|
||||
[
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(tape)), tape_span),
|
||||
] => {
|
||||
return Some((Spanned(state, *state_span), Spanned(*tape, *tape_span)));
|
||||
[state, tape]
|
||||
if let Some(state) = state.string_weak()
|
||||
&& let Some(tape) = tape.string_weak() =>
|
||||
{
|
||||
return Some((state, tape));
|
||||
}
|
||||
_ => _ = ctx.emit_error("expected TM transition function (state, symbol)", self.1),
|
||||
}
|
||||
|
|
@ -468,28 +475,25 @@ impl<'a> Spanned<&ast::Tuple<'a>> {
|
|||
ctx: &mut Context<'a>,
|
||||
) -> Option<(Spanned<&'a str>, Spanned<&'a str>, Spanned<Direction>)> {
|
||||
match &self.0.0[..] {
|
||||
[
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(tape)), tape_span),
|
||||
Spanned(ast::Item::Symbol(direction), direction_span),
|
||||
] => {
|
||||
let direction = match direction {
|
||||
[state, tape, direction]
|
||||
if let Some(state) = state.string_weak()
|
||||
&& let Some(tape) = tape.string_weak()
|
||||
&& let Some(direction) = direction.sym_weak() =>
|
||||
{
|
||||
let direction_span = direction.1;
|
||||
let direction = match direction.0 {
|
||||
ast::Symbol::Ident("left" | "L" | "<") => Direction::Left,
|
||||
ast::Symbol::Ident("right" | "R" | ">") => Direction::Right,
|
||||
ast::Symbol::Epsilon(_) | ast::Symbol::Ident("~") => Direction::None,
|
||||
ast::Symbol::Ident(ident) => {
|
||||
ctx.emit_error(
|
||||
format!("invalid direction specified '{ident}'"),
|
||||
*direction_span,
|
||||
direction.1,
|
||||
);
|
||||
Direction::None
|
||||
}
|
||||
};
|
||||
return Some((
|
||||
Spanned(state, *state_span),
|
||||
Spanned(*tape, *tape_span),
|
||||
Spanned(direction, *direction_span),
|
||||
));
|
||||
return Some((state, tape, Spanned(direction, direction_span)));
|
||||
}
|
||||
_ => {
|
||||
_ = ctx.emit_error(
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub enum Symbol<'a> {
|
|||
#[derive(Clone, Debug)]
|
||||
pub enum Item<'a> {
|
||||
Symbol(Symbol<'a>),
|
||||
String(Cow<'a, str>),
|
||||
String(&'a str),
|
||||
Tuple(Tuple<'a>),
|
||||
List(List<'a>),
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ pub struct List<'a>(pub Vec<Spanned<Item<'a>>>, pub ListKind);
|
|||
pub enum ProductionUnit<'a> {
|
||||
Epsilon(&'a str),
|
||||
Ident(&'a str),
|
||||
String(Cow<'a, str>),
|
||||
String(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -73,7 +73,7 @@ pub enum TopLevel<'a> {
|
|||
use crate::loader::{Context, log::LogSink};
|
||||
|
||||
impl<'a> Spanned<Item<'a>> {
|
||||
pub fn expect_symbol(&self, ctx: &mut Context<'a>) -> Option<Symbol<'a>> {
|
||||
pub fn expect_symbol_weak(&self, ctx: &mut Context<'a>) -> Option<Symbol<'a>> {
|
||||
match &self.0 {
|
||||
Item::Symbol(sym) => return Some(*sym),
|
||||
Item::Tuple(_) => _ = ctx.emit_error("expected ident found tuple", self.1),
|
||||
|
|
@ -83,15 +83,15 @@ impl<'a> Spanned<Item<'a>> {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn expect_ident(&self, ctx: &mut Context<'a>) -> Option<&'a str> {
|
||||
pub fn expect_ident_weak(&self, ctx: &mut Context<'a>) -> Option<&'a str> {
|
||||
match &self.0 {
|
||||
Item::Symbol(Symbol::Ident(ident)) => return Some(ident),
|
||||
Item::String(string) => _ = return Some(*string),
|
||||
Item::Symbol(Symbol::Epsilon(_)) => {
|
||||
_ = ctx.emit_error("expected ident found epsilon", self.1)
|
||||
_ = ctx.emit_error("expected ident/string found epsilon", self.1)
|
||||
}
|
||||
Item::Tuple(_) => _ = ctx.emit_error("expected ident found tuple", self.1),
|
||||
Item::List(_) => _ = ctx.emit_error("expected ident found list", self.1),
|
||||
Item::String(_) => _ = ctx.emit_error("expected ident found string", self.1),
|
||||
Item::Tuple(_) => _ = ctx.emit_error("expected ident/string found tuple", self.1),
|
||||
Item::List(_) => _ = ctx.emit_error("expected ident/string found list", self.1),
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
@ -140,6 +140,25 @@ impl<'a> Spanned<Item<'a>> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn string_weak(&self) -> Option<Spanned<&'a str>> {
|
||||
match &self.0 {
|
||||
Item::Symbol(Symbol::Ident(ident)) => Some(Spanned(ident, self.1)),
|
||||
Item::Symbol(_) => None,
|
||||
Item::String(ident) => Some(Spanned(ident, self.1)),
|
||||
Item::Tuple(_) => None,
|
||||
Item::List(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sym_weak(&self) -> Option<Spanned<Symbol<'a>>> {
|
||||
match &self.0 {
|
||||
Item::Symbol(symbol) => Some(Spanned(*symbol, self.1)),
|
||||
Item::String(ident) => Some(Spanned(Symbol::Ident(ident), self.1)),
|
||||
Item::Tuple(_) => None,
|
||||
Item::List(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_tuple(&self, ctx: &mut Context<'a>) -> Option<Spanned<&Tuple<'a>>> {
|
||||
match &self.0 {
|
||||
Item::Symbol(Symbol::Ident(_)) => {
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ impl<'a> std::iter::Iterator for Lexer<'a> {
|
|||
match self.consume() {
|
||||
Some('"') => {
|
||||
break Ok(Token::String(
|
||||
&self.input[start + 1..self.position],
|
||||
&self.input[start + 1..self.position-1],
|
||||
StringKind::Regular,
|
||||
escaped,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ pub fn parse_universal<'a>(ctx: &mut Context<'a>) -> Option<Machine<'a>> {
|
|||
fn parse_type<'a>(item: Option<S<TopLevel<'a>>>, ctx: &mut Context<'a>) -> Option<Type> {
|
||||
let (str, span) = match item {
|
||||
Some(S(TopLevel::Item(S("type", _), item @ S(_, span)), _)) => {
|
||||
(item.expect_ident(ctx)?, span)
|
||||
(item.expect_ident_weak(ctx)?, span)
|
||||
}
|
||||
Some(S(_, span)) => {
|
||||
ctx.emit_error("expected type=<type> as first item", span)
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
S(Tuple(items), start.join(end))
|
||||
}
|
||||
|
||||
fn parse_as_string(&mut self, tok: S<T<'a>>) -> S<Cow<'a, str>> {
|
||||
fn parse_as_string(&mut self, tok: S<T<'a>>) -> S<&'a str> {
|
||||
let (r, k, e, s) = match tok {
|
||||
S(T::String(r, k, e), s) => (r, k, e, s),
|
||||
S(t, s) => {
|
||||
|
|
@ -160,7 +160,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
S(r.into(), s)
|
||||
}
|
||||
|
||||
fn parse_string(&mut self) -> S<Cow<'a, str>> {
|
||||
fn parse_string(&mut self) -> S<&'a str> {
|
||||
let tok = self.next_token();
|
||||
self.parse_as_string(tok)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ d(qc, c) = qc
|
|||
new Example(
|
||||
"Tutorial",
|
||||
"DPDA Final State",
|
||||
`// Accept strings over a,b of the form a^nb^k n != k n,k > 0
|
||||
`// 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
|
||||
|
|
@ -122,7 +122,7 @@ 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, A) = (qlb, ~)
|
||||
d(qlb, b, z0) = (qeq, z0)
|
||||
|
||||
d(qeq, b, z0) = (qmb, z0)
|
||||
|
|
@ -369,7 +369,7 @@ d(q1, b, B) = { (q1, epsilon) }`,
|
|||
),
|
||||
|
||||
new Example("TM", "a^nb^n",
|
||||
`// accepts all strings on {a,b}+ of the form anbn
|
||||
`// accepts all strings on {a,b}+ of the form a^n^bn
|
||||
|
||||
type = TM
|
||||
Q = { q0, q1, q2, q3, q4 } // set of internal states
|
||||
|
|
@ -378,18 +378,19 @@ 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(q0,a)=(q1,X,R)
|
||||
d(q1,a)=(q1,a,R)
|
||||
d(q1,Y)=(q1,y,R)
|
||||
d(q1,b)=(q2,y,L)
|
||||
d(q1,Y)=(q1,Y,R)
|
||||
d(q1,b)=(q2,Y,L)
|
||||
|
||||
d(q2,Y)=(q2,y,L)
|
||||
d(q2,Y)=(q2,Y,L)
|
||||
d(q2,a)=(q2,a,L)
|
||||
d(q2,X)=(q0,x,R)
|
||||
d(q2,X)=(q0,X,R)
|
||||
|
||||
d(q0,Y)=(q3,y,R)
|
||||
d(q3,Y)=(q3,y,R)
|
||||
d(q0,Y)=(q3,Y,R)
|
||||
d(q3,Y)=(q3,Y,R)
|
||||
d(q3,B)=(q4,B,R)
|
||||
|
||||
`),
|
||||
|
||||
// new Example("CFG", "definition",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use automata::{
|
||||
automatan::{fa::Fa, pda::Pda, tm::Tm}, delta_lower, epsilon, gamma_upper, loader::{self, Context, Machine, Span, Spanned, lexer::Lexer}, sigma_upper
|
||||
automatan::{fa::Fa, pda::Pda, tm::Tm},
|
||||
delta_lower, epsilon, gamma_upper,
|
||||
loader::{self, Context, Machine, Span, Spanned, lexer::Lexer},
|
||||
sigma_upper,
|
||||
};
|
||||
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
|
@ -163,10 +166,19 @@ impl<'a> FixupSpan for Machine<'a>{
|
|||
}
|
||||
impl<'a> FixupSpan for Fa<'a> {
|
||||
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
||||
self.alphabet.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.states.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.final_states.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.transitions.values_mut().flat_map(|v|v.iter_mut()).for_each(|e|{
|
||||
self.alphabet
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.states
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.final_states
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.transitions
|
||||
.values_mut()
|
||||
.flat_map(|v| v.iter_mut())
|
||||
.for_each(|e| {
|
||||
e.transition = func(e.transition);
|
||||
e.function = func(e.function);
|
||||
});
|
||||
|
|
@ -175,11 +187,24 @@ impl<'a> FixupSpan for Fa<'a>{
|
|||
|
||||
impl<'a> FixupSpan for Pda<'a> {
|
||||
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
||||
self.alphabet.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.states.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.symbols.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.final_states.as_mut().unwrap_or(&mut HashMap::new()).values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.transitions.values_mut().flat_map(|v|v.iter_mut()).for_each(|e|{
|
||||
self.alphabet
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.states
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.symbols
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.final_states
|
||||
.as_mut()
|
||||
.unwrap_or(&mut HashMap::new())
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.transitions
|
||||
.values_mut()
|
||||
.flat_map(|v| v.iter_mut())
|
||||
.for_each(|e| {
|
||||
e.transition = func(e.transition);
|
||||
e.function = func(e.function);
|
||||
});
|
||||
|
|
@ -188,25 +213,37 @@ impl<'a> FixupSpan for Pda<'a>{
|
|||
|
||||
impl<'a> FixupSpan for Tm<'a> {
|
||||
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
||||
self.states.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.symbols.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.final_states.values_mut().for_each(|v| v.definition = func(v.definition));
|
||||
self.transitions.values_mut().flat_map(|v|v.iter_mut()).for_each(|e|{
|
||||
self.states
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.symbols
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.final_states
|
||||
.values_mut()
|
||||
.for_each(|v| v.definition = func(v.definition));
|
||||
self.transitions
|
||||
.values_mut()
|
||||
.flat_map(|v| v.iter_mut())
|
||||
.for_each(|e| {
|
||||
e.transition = func(e.transition);
|
||||
e.function = func(e.function);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn compile(input: &str) -> CompileResult {
|
||||
let mut ctx = Context::new(input);
|
||||
let result = automata::loader::parse_universal(&mut ctx);
|
||||
|
||||
let machine = result.map(|mut result| {
|
||||
result.fixup(|span|Span(input[..span.0].chars().map(char::len_utf16).sum(), input[..span.1].chars().map(char::len_utf16).sum()));
|
||||
result.fixup(|span| {
|
||||
Span(
|
||||
input[..span.0].chars().map(char::len_utf16).sum(),
|
||||
input[..span.1].chars().map(char::len_utf16).sum(),
|
||||
)
|
||||
});
|
||||
serde_json::to_string(&result).unwrap()
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue