automata/src/loader/ast.rs
2025-12-19 18:06:21 -05:00

171 lines
5.1 KiB
Rust

use std::ops::Range;
use super::Spanned;
#[derive(Clone, Debug)]
pub struct Tuple<'a>(pub Vec<Spanned<Item<'a>>>);
#[derive(Clone, Copy, Debug)]
pub enum Symbol<'a> {
Epsilon,
Ident(&'a str),
}
#[derive(Clone, Debug)]
pub enum Dest<'a> {
Ident(&'a str),
Function(Spanned<&'a str>, Spanned<Tuple<'a>>),
}
#[derive(Clone, Debug)]
pub enum Item<'a> {
Symbol(Symbol<'a>),
Tuple(Tuple<'a>),
List(List<'a>),
}
#[derive(Clone, Debug)]
pub enum Regex<'a> {
Terminal(&'a str),
Match {
complement: bool,
patterns: Vec<Range<char>>,
},
Concat(Vec<Regex<'a>>),
Star(Box<Regex<'a>>),
Plus(Box<Regex<'a>>),
Union(Vec<Regex<'a>>),
Intersection(Vec<Regex<'a>>),
Complement(Box<Regex<'a>>),
}
#[derive(Clone, Debug)]
pub struct List<'a>(pub Vec<Spanned<Item<'a>>>);
#[derive(Clone, Debug)]
pub enum TopLevel<'a> {
Assignment(Spanned<Dest<'a>>, Spanned<Item<'a>>),
ProductionRule(Spanned<Symbol<'a>>, Spanned<Symbol<'a>>),
Table(),
}
use crate::loader::log::Logs;
impl<'a> Spanned<Item<'a>> {
pub fn expect_ident(&self, logs: &mut Logs<'a>) -> Option<&'a str> {
match &self.0 {
Item::Symbol(Symbol::Ident(ident)) => return Some(ident),
Item::Symbol(Symbol::Epsilon) => {
logs.emit_error("expected ident found epsilon", self.1)
}
Item::Tuple(_) => logs.emit_error("expected ident found tuple", self.1),
Item::List(_) => logs.emit_error("expected ident found list", self.1),
}
None
}
pub fn expect_set(&self, logs: &mut Logs<'a>) -> Option<&[Spanned<Item<'a>>]> {
match &self.0 {
Item::Symbol(Symbol::Ident(_)) => logs.emit_error("expected set found ident", self.1),
Item::Symbol(Symbol::Epsilon) => logs.emit_error("expected set found epsilon", self.1),
Item::Tuple(_) => logs.emit_error("expected set found tuple", self.1),
Item::List(list) => return Some(&list.0),
}
None
}
pub fn expect_list(&self, logs: &mut Logs<'a>) -> Option<&[Spanned<Item<'a>>]> {
match &self.0 {
Item::Symbol(Symbol::Ident(_)) => logs.emit_error("expected list found ident", self.1),
Item::Symbol(Symbol::Epsilon) => logs.emit_error("expected list found epsilon", self.1),
Item::Tuple(_) => logs.emit_error("expected list found tuple", self.1),
Item::List(list) => return Some(&list.0),
}
None
}
pub fn list_weak(&self) -> &[Spanned<Item<'a>>] {
match &self.0 {
Item::List(list) => &list.0,
_ => std::slice::from_ref(self),
}
}
pub fn set_weak(&self) -> &[Spanned<Item<'a>>] {
match &self.0 {
Item::List(list) => &list.0,
_ => std::slice::from_ref(self),
}
}
pub fn expect_tuple(&self, logs: &mut Logs<'a>) -> Option<Spanned<&Tuple<'a>>> {
match &self.0 {
Item::Symbol(Symbol::Ident(_)) => logs.emit_error("expected tuple found ident", self.1),
Item::Symbol(Symbol::Epsilon) => {
logs.emit_error("expected tuple found epsilon", self.1)
}
Item::Tuple(tuple) => return Some(Spanned(tuple, self.1)),
Item::List(_) => logs.emit_error("expected tuple found list", self.1),
}
None
}
}
impl<'a, 'b> Spanned<&'b Tuple<'a>> {
pub fn expect_dfa_transition(&self, logs: &mut Logs<'a>) -> ! {
todo!()
}
pub fn expect_nfa_transition(&self, logs: &mut Logs<'a>) -> ! {
todo!()
}
pub fn expect_dpda_transition(&self, logs: &mut Logs<'a>) -> ! {
todo!()
}
pub fn expect_npda_transition_function(
&self,
logs: &mut Logs<'a>,
) -> Option<(Spanned<&'a str>, Spanned<Symbol<'a>>, Spanned<&'a str>)> {
match &self.0.0[..] {
[
Spanned(Item::Symbol(Symbol::Ident(state)), state_span),
Spanned(Item::Symbol(letter), letter_span),
Spanned(Item::Symbol(Symbol::Ident(symbol)), symbol_span),
] => {
return Some((
Spanned(state, *state_span),
Spanned(*letter, *letter_span),
Spanned(symbol, *symbol_span),
));
}
_ => logs.emit_error(
"expected NPDA transition function (ident, ident|~, ident)",
self.1,
),
}
None
}
pub fn expect_npda_transition(
&self,
logs: &mut Logs<'a>,
) -> Option<(Spanned<&'a str>, &'b [Spanned<Item<'a>>])> {
match &self.0.0[..] {
[
Spanned(Item::Symbol(Symbol::Ident(state)), state_span),
list,
] => {
return Some((Spanned(state, *state_span), list.list_weak()));
}
_ => logs.emit_error("expected NPDA transition (ident, item|[item])", self.1),
}
None
}
pub fn expect_tm_transition(&self, logs: &mut Logs<'a>) -> ! {
todo!()
}
pub fn expect_ntm_transition(&self, logs: &mut Logs<'a>) -> ! {
todo!()
}
}