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;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(previous) = self
|
if let Some(previous) = self
|
||||||
|
|
@ -258,7 +258,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -292,7 +292,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if self.states.contains_key(&State(ident)) {
|
if self.states.contains_key(&State(ident)) {
|
||||||
|
|
@ -366,7 +366,7 @@ impl<'a, 'b> FaCompiler<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for item in list {
|
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;
|
continue;
|
||||||
};
|
};
|
||||||
let next_state = Spanned(next_state, item.1);
|
let next_state = Spanned(next_state, item.1);
|
||||||
|
|
@ -413,11 +413,11 @@ impl<'a> Spanned<&ast::Tuple<'a>> {
|
||||||
ctx: &mut Context<'a>,
|
ctx: &mut Context<'a>,
|
||||||
) -> Option<(Spanned<&'a str>, Spanned<ast::Symbol<'a>>)> {
|
) -> Option<(Spanned<&'a str>, Spanned<ast::Symbol<'a>>)> {
|
||||||
match &self.0.0[..] {
|
match &self.0.0[..] {
|
||||||
[
|
[state, letter]
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
if let Some(state) = state.string_weak()
|
||||||
Spanned(ast::Item::Symbol(letter), letter_span),
|
&& let Some(letter) = letter.sym_weak() =>
|
||||||
] => {
|
{
|
||||||
return Some((Spanned(state, *state_span), Spanned(*letter, *letter_span)));
|
return Some((state, letter));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
_ = ctx.emit_error(
|
_ = ctx.emit_error(
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
||||||
.emit_error("accept by already set", top_level)
|
.emit_error("accept by already set", top_level)
|
||||||
.emit_info("previously defined here", previous);
|
.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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -343,7 +343,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(previous) = self
|
if let Some(previous) = self
|
||||||
|
|
@ -372,7 +372,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(previous) = self
|
if let Some(previous) = self
|
||||||
|
|
@ -401,7 +401,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -435,7 +435,7 @@ impl<'a, 'b> PdaCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if self.states.contains_key(&State(ident)) {
|
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(_))) {
|
if matches!(symbol.0, ast::Item::Symbol(Sym::Epsilon(_))) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ident = symbol.expect_ident(self.ctx)?;
|
let ident = symbol.expect_ident_weak(self.ctx)?;
|
||||||
|
|
||||||
if !self.symbols.contains_key(&Symbol(ident)) {
|
if !self.symbols.contains_key(&Symbol(ident)) {
|
||||||
self.ctx
|
self.ctx
|
||||||
|
|
@ -611,16 +611,12 @@ impl<'a, 'b> Spanned<&'b ast::Tuple<'a>> {
|
||||||
ctx: &mut Context<'a>,
|
ctx: &mut Context<'a>,
|
||||||
) -> Option<(Spanned<&'a str>, Spanned<ast::Symbol<'a>>, Spanned<&'a str>)> {
|
) -> Option<(Spanned<&'a str>, Spanned<ast::Symbol<'a>>, Spanned<&'a str>)> {
|
||||||
match &self.0.0[..] {
|
match &self.0.0[..] {
|
||||||
[
|
[state, letter, symbol]
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
if let Some(state) = state.string_weak()
|
||||||
Spanned(ast::Item::Symbol(letter), letter_span),
|
&& let Some(letter) = letter.sym_weak()
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(symbol)), symbol_span),
|
&& let Some(symbol) = symbol.string_weak() =>
|
||||||
] => {
|
{
|
||||||
return Some((
|
return Some((state, letter, symbol));
|
||||||
Spanned(state, *state_span),
|
|
||||||
Spanned(*letter, *letter_span),
|
|
||||||
Spanned(symbol, *symbol_span),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
_ = ctx.emit_error(
|
_ = ctx.emit_error(
|
||||||
|
|
@ -636,11 +632,8 @@ impl<'a, 'b> Spanned<&'b ast::Tuple<'a>> {
|
||||||
ctx: &mut Context<'a>,
|
ctx: &mut Context<'a>,
|
||||||
) -> Option<(Spanned<&'a str>, &'b [Spanned<ast::Item<'a>>])> {
|
) -> Option<(Spanned<&'a str>, &'b [Spanned<ast::Item<'a>>])> {
|
||||||
match &self.0.0[..] {
|
match &self.0.0[..] {
|
||||||
[
|
[state, list] if let Some(state) = state.string_weak() => {
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
return Some((state, list.list_weak()));
|
||||||
list,
|
|
||||||
] => {
|
|
||||||
return Some((Spanned(state, *state_span), list.list_weak()));
|
|
||||||
}
|
}
|
||||||
_ => _ = ctx.emit_error("expected PDA transition (state, symbol|[symbol])", self.1),
|
_ => _ = ctx.emit_error("expected PDA transition (state, symbol|[symbol])", self.1),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(previous) = self
|
if let Some(previous) = self
|
||||||
|
|
@ -282,7 +282,7 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(previous) = self
|
if let Some(previous) = self
|
||||||
|
|
@ -311,7 +311,7 @@ impl<'a, 'b> TmCompiler<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for item in list {
|
for item in list {
|
||||||
let Some(ident) = item.expect_ident(self.ctx) else {
|
let Some(ident) = item.expect_ident_weak(self.ctx) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if self.states.contains_key(&State(ident)) {
|
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);
|
.emit_error("transition state not defined as state", to_state.1);
|
||||||
continue;
|
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
|
let entry: &mut _ = self
|
||||||
.transitions
|
.transitions
|
||||||
|
|
@ -452,11 +459,11 @@ impl<'a> Spanned<&ast::Tuple<'a>> {
|
||||||
ctx: &mut Context<'a>,
|
ctx: &mut Context<'a>,
|
||||||
) -> Option<(Spanned<&'a str>, Spanned<&'a str>)> {
|
) -> Option<(Spanned<&'a str>, Spanned<&'a str>)> {
|
||||||
match &self.0.0[..] {
|
match &self.0.0[..] {
|
||||||
[
|
[state, tape]
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
if let Some(state) = state.string_weak()
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(tape)), tape_span),
|
&& let Some(tape) = tape.string_weak() =>
|
||||||
] => {
|
{
|
||||||
return Some((Spanned(state, *state_span), Spanned(*tape, *tape_span)));
|
return Some((state, tape));
|
||||||
}
|
}
|
||||||
_ => _ = ctx.emit_error("expected TM transition function (state, symbol)", self.1),
|
_ => _ = 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>,
|
ctx: &mut Context<'a>,
|
||||||
) -> Option<(Spanned<&'a str>, Spanned<&'a str>, Spanned<Direction>)> {
|
) -> Option<(Spanned<&'a str>, Spanned<&'a str>, Spanned<Direction>)> {
|
||||||
match &self.0.0[..] {
|
match &self.0.0[..] {
|
||||||
[
|
[state, tape, direction]
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(state)), state_span),
|
if let Some(state) = state.string_weak()
|
||||||
Spanned(ast::Item::Symbol(ast::Symbol::Ident(tape)), tape_span),
|
&& let Some(tape) = tape.string_weak()
|
||||||
Spanned(ast::Item::Symbol(direction), direction_span),
|
&& let Some(direction) = direction.sym_weak() =>
|
||||||
] => {
|
{
|
||||||
let direction = match direction {
|
let direction_span = direction.1;
|
||||||
|
let direction = match direction.0 {
|
||||||
ast::Symbol::Ident("left" | "L" | "<") => Direction::Left,
|
ast::Symbol::Ident("left" | "L" | "<") => Direction::Left,
|
||||||
ast::Symbol::Ident("right" | "R" | ">") => Direction::Right,
|
ast::Symbol::Ident("right" | "R" | ">") => Direction::Right,
|
||||||
ast::Symbol::Epsilon(_) | ast::Symbol::Ident("~") => Direction::None,
|
ast::Symbol::Epsilon(_) | ast::Symbol::Ident("~") => Direction::None,
|
||||||
ast::Symbol::Ident(ident) => {
|
ast::Symbol::Ident(ident) => {
|
||||||
ctx.emit_error(
|
ctx.emit_error(
|
||||||
format!("invalid direction specified '{ident}'"),
|
format!("invalid direction specified '{ident}'"),
|
||||||
*direction_span,
|
direction.1,
|
||||||
);
|
);
|
||||||
Direction::None
|
Direction::None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Some((
|
return Some((state, tape, Spanned(direction, direction_span)));
|
||||||
Spanned(state, *state_span),
|
|
||||||
Spanned(*tape, *tape_span),
|
|
||||||
Spanned(direction, *direction_span),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
_ = ctx.emit_error(
|
_ = ctx.emit_error(
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pub enum Symbol<'a> {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Item<'a> {
|
pub enum Item<'a> {
|
||||||
Symbol(Symbol<'a>),
|
Symbol(Symbol<'a>),
|
||||||
String(Cow<'a, str>),
|
String(&'a str),
|
||||||
Tuple(Tuple<'a>),
|
Tuple(Tuple<'a>),
|
||||||
List(List<'a>),
|
List(List<'a>),
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ pub struct List<'a>(pub Vec<Spanned<Item<'a>>>, pub ListKind);
|
||||||
pub enum ProductionUnit<'a> {
|
pub enum ProductionUnit<'a> {
|
||||||
Epsilon(&'a str),
|
Epsilon(&'a str),
|
||||||
Ident(&'a str),
|
Ident(&'a str),
|
||||||
String(Cow<'a, str>),
|
String(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -73,7 +73,7 @@ pub enum TopLevel<'a> {
|
||||||
use crate::loader::{Context, log::LogSink};
|
use crate::loader::{Context, log::LogSink};
|
||||||
|
|
||||||
impl<'a> Spanned<Item<'a>> {
|
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 {
|
match &self.0 {
|
||||||
Item::Symbol(sym) => return Some(*sym),
|
Item::Symbol(sym) => return Some(*sym),
|
||||||
Item::Tuple(_) => _ = ctx.emit_error("expected ident found tuple", self.1),
|
Item::Tuple(_) => _ = ctx.emit_error("expected ident found tuple", self.1),
|
||||||
|
|
@ -83,15 +83,15 @@ impl<'a> Spanned<Item<'a>> {
|
||||||
None
|
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 {
|
match &self.0 {
|
||||||
Item::Symbol(Symbol::Ident(ident)) => return Some(ident),
|
Item::Symbol(Symbol::Ident(ident)) => return Some(ident),
|
||||||
|
Item::String(string) => _ = return Some(*string),
|
||||||
Item::Symbol(Symbol::Epsilon(_)) => {
|
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::Tuple(_) => _ = ctx.emit_error("expected ident/string found tuple", self.1),
|
||||||
Item::List(_) => _ = ctx.emit_error("expected ident found list", self.1),
|
Item::List(_) => _ = ctx.emit_error("expected ident/string found list", self.1),
|
||||||
Item::String(_) => _ = ctx.emit_error("expected ident found string", self.1),
|
|
||||||
}
|
}
|
||||||
None
|
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>>> {
|
pub fn expect_tuple(&self, ctx: &mut Context<'a>) -> Option<Spanned<&Tuple<'a>>> {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
Item::Symbol(Symbol::Ident(_)) => {
|
Item::Symbol(Symbol::Ident(_)) => {
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ impl<'a> std::iter::Iterator for Lexer<'a> {
|
||||||
match self.consume() {
|
match self.consume() {
|
||||||
Some('"') => {
|
Some('"') => {
|
||||||
break Ok(Token::String(
|
break Ok(Token::String(
|
||||||
&self.input[start + 1..self.position],
|
&self.input[start + 1..self.position-1],
|
||||||
StringKind::Regular,
|
StringKind::Regular,
|
||||||
escaped,
|
escaped,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -231,11 +231,11 @@ impl<'a> Display for LogEntryDisplay<'a> {
|
||||||
}
|
}
|
||||||
for grapheme in line.graphemes(true) {
|
for grapheme in line.graphemes(true) {
|
||||||
if (span.0..span.1).contains(&index) {
|
if (span.0..span.1).contains(&index) {
|
||||||
for _ in 0..width(grapheme){
|
for _ in 0..width(grapheme) {
|
||||||
write!(f, "~")?;
|
write!(f, "~")?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _ in 0..width(grapheme){
|
for _ in 0..width(grapheme) {
|
||||||
write!(f, " ")?;
|
write!(f, " ")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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> {
|
fn parse_type<'a>(item: Option<S<TopLevel<'a>>>, ctx: &mut Context<'a>) -> Option<Type> {
|
||||||
let (str, span) = match item {
|
let (str, span) = match item {
|
||||||
Some(S(TopLevel::Item(S("type", _), item @ S(_, span)), _)) => {
|
Some(S(TopLevel::Item(S("type", _), item @ S(_, span)), _)) => {
|
||||||
(item.expect_ident(ctx)?, span)
|
(item.expect_ident_weak(ctx)?, span)
|
||||||
}
|
}
|
||||||
Some(S(_, span)) => {
|
Some(S(_, span)) => {
|
||||||
ctx.emit_error("expected type=<type> as first item", 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))
|
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 {
|
let (r, k, e, s) = match tok {
|
||||||
S(T::String(r, k, e), s) => (r, k, e, s),
|
S(T::String(r, k, e), s) => (r, k, e, s),
|
||||||
S(t, s) => {
|
S(t, s) => {
|
||||||
|
|
@ -160,7 +160,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
S(r.into(), s)
|
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();
|
let tok = self.next_token();
|
||||||
self.parse_as_string(tok)
|
self.parse_as_string(tok)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ d(qc, c) = qc
|
||||||
new Example(
|
new Example(
|
||||||
"Tutorial",
|
"Tutorial",
|
||||||
"DPDA Final State",
|
"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
|
type = DPDA
|
||||||
Q = {q0, qas, qeq, qmb, qlb} // states
|
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, a, A) = (qas, [A A])
|
||||||
d(qas, b, A) = (qlb, ~)
|
d(qas, b, A) = (qlb, ~)
|
||||||
|
|
||||||
d(qlb, b, A) = (qeq, ~)
|
d(qlb, b, A) = (qlb, ~)
|
||||||
d(qlb, b, z0) = (qeq, z0)
|
d(qlb, b, z0) = (qeq, z0)
|
||||||
|
|
||||||
d(qeq, b, z0) = (qmb, z0)
|
d(qeq, b, z0) = (qmb, z0)
|
||||||
|
|
@ -369,7 +369,7 @@ d(q1, b, B) = { (q1, epsilon) }`,
|
||||||
),
|
),
|
||||||
|
|
||||||
new Example("TM", "a^nb^n",
|
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
|
type = TM
|
||||||
Q = { q0, q1, q2, q3, q4 } // set of internal states
|
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)
|
B = B // the blank symbol (tape initializer symbol)
|
||||||
q0 = q0 // initial state
|
q0 = q0 // initial state
|
||||||
|
|
||||||
d(q0,a)=(q1,x,R)
|
d(q0,a)=(q1,X,R)
|
||||||
d(q1,a)=(q1,a,R)
|
d(q1,a)=(q1,a,R)
|
||||||
d(q1,Y)=(q1,y,R)
|
d(q1,Y)=(q1,Y,R)
|
||||||
d(q1,b)=(q2,y,L)
|
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,a)=(q2,a,L)
|
||||||
d(q2,X)=(q0,x,R)
|
d(q2,X)=(q0,X,R)
|
||||||
|
|
||||||
d(q0,Y)=(q3,y,R)
|
d(q0,Y)=(q3,Y,R)
|
||||||
d(q3,Y)=(q3,y,R)
|
d(q3,Y)=(q3,Y,R)
|
||||||
d(q3,B)=(q4,B,R)
|
d(q3,B)=(q4,B,R)
|
||||||
|
|
||||||
`),
|
`),
|
||||||
|
|
||||||
// new Example("CFG", "definition",
|
// new Example("CFG", "definition",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use automata::{
|
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;
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
@ -148,65 +151,99 @@ pub struct CompileResult {
|
||||||
pub machine: Option<String>,
|
pub machine: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FixupSpan{
|
trait FixupSpan {
|
||||||
fn fixup(&mut self, func: impl FnMut(Span) -> Span);
|
fn fixup(&mut self, func: impl FnMut(Span) -> Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FixupSpan for Machine<'a>{
|
impl<'a> FixupSpan for Machine<'a> {
|
||||||
fn fixup(&mut self, func: impl FnMut(Span) -> Span) {
|
fn fixup(&mut self, func: impl FnMut(Span) -> Span) {
|
||||||
match self{
|
match self {
|
||||||
Machine::Fa(fa) => fa.fixup(func),
|
Machine::Fa(fa) => fa.fixup(func),
|
||||||
Machine::Pda(pda) => pda.fixup(func),
|
Machine::Pda(pda) => pda.fixup(func),
|
||||||
Machine::Tm(tm) => tm.fixup(func),
|
Machine::Tm(tm) => tm.fixup(func),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> FixupSpan for Fa<'a>{
|
impl<'a> FixupSpan for Fa<'a> {
|
||||||
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
||||||
self.alphabet.values_mut().for_each(|v| v.definition = func(v.definition));
|
self.alphabet
|
||||||
self.states.values_mut().for_each(|v| v.definition = func(v.definition));
|
.values_mut()
|
||||||
self.final_states.values_mut().for_each(|v| v.definition = func(v.definition));
|
.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.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.transition = func(e.transition);
|
||||||
e.function = func(e.function);
|
e.function = func(e.function);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FixupSpan for Pda<'a>{
|
impl<'a> FixupSpan for Pda<'a> {
|
||||||
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
||||||
self.alphabet.values_mut().for_each(|v| v.definition = func(v.definition));
|
self.alphabet
|
||||||
self.states.values_mut().for_each(|v| v.definition = func(v.definition));
|
.values_mut()
|
||||||
self.symbols.values_mut().for_each(|v| v.definition = func(v.definition));
|
.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.states
|
||||||
self.transitions.values_mut().flat_map(|v|v.iter_mut()).for_each(|e|{
|
.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.transition = func(e.transition);
|
||||||
e.function = func(e.function);
|
e.function = func(e.function);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FixupSpan for Tm<'a>{
|
impl<'a> FixupSpan for Tm<'a> {
|
||||||
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
fn fixup(&mut self, mut func: impl FnMut(Span) -> Span) {
|
||||||
self.states.values_mut().for_each(|v| v.definition = func(v.definition));
|
self.states
|
||||||
self.symbols.values_mut().for_each(|v| v.definition = func(v.definition));
|
.values_mut()
|
||||||
self.final_states.values_mut().for_each(|v| v.definition = func(v.definition));
|
.for_each(|v| v.definition = func(v.definition));
|
||||||
self.transitions.values_mut().flat_map(|v|v.iter_mut()).for_each(|e|{
|
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.transition = func(e.transition);
|
||||||
e.function = func(e.function);
|
e.function = func(e.function);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn compile(input: &str) -> CompileResult {
|
pub fn compile(input: &str) -> CompileResult {
|
||||||
let mut ctx = Context::new(input);
|
let mut ctx = Context::new(input);
|
||||||
let result = automata::loader::parse_universal(&mut ctx);
|
let result = automata::loader::parse_universal(&mut ctx);
|
||||||
|
|
||||||
let machine = result.map(|mut result| {
|
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()
|
serde_json::to_string(&result).unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue