mirror of
https://github.com/ParkerTenBroeck/automata.git
synced 2026-06-07 05:28:45 -04:00
fixed parser
This commit is contained in:
parent
7971c61c74
commit
c35d7a9192
4 changed files with 110 additions and 64 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
type=NPDA
|
//type=NPDA
|
||||||
Q = {q0, q1} // states
|
Q = {q0, q1} // states
|
||||||
E = {a, b} // alphabet
|
E = {a, b} // alphabet
|
||||||
T = {z0, A, B} // stack
|
T = {z0, A, B} // stack
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use super::lexer::{Lexer, Token};
|
||||||
|
|
||||||
pub struct Parser<'a> {
|
pub struct Parser<'a> {
|
||||||
lexer: Lexer<'a>,
|
lexer: Lexer<'a>,
|
||||||
peek: Spanned<Option<Token<'a>>>,
|
peek: Option<Spanned<Token<'a>>>,
|
||||||
logs: Logs<'a>,
|
logs: Logs<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ impl<'a> Parser<'a> {
|
||||||
pub fn new(lexer: Lexer<'a>) -> Self {
|
pub fn new(lexer: Lexer<'a>) -> Self {
|
||||||
Parser {
|
Parser {
|
||||||
logs: Logs::new(lexer.input()),
|
logs: Logs::new(lexer.input()),
|
||||||
peek: Spanned(None, Span(0,0)),
|
peek: None,
|
||||||
lexer,
|
lexer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,33 +24,39 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance_line(&mut self) {
|
fn advance_line(&mut self) {
|
||||||
|
if self.peek_token().is_none(){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if self.expect_token(Token::LineEnd).0 {
|
if self.expect_token(Token::LineEnd).0 {
|
||||||
self.peek = Spanned(None, Span(0,0));
|
self.peek = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_token(&mut self) -> Spanned<Option<Token<'a>>> {
|
fn next_token(&mut self) -> Option<Spanned<Token<'a>>> {
|
||||||
match self.peek.0 {
|
match self.peek {
|
||||||
Some(Token::LineEnd) => return self.peek,
|
Some(Spanned(Token::LineEnd, _)) => return self.peek,
|
||||||
Some(_) => return Spanned(self.peek.0.take(), self.peek.1),
|
Some(_) => return self.peek.take(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
match self.lexer.next() {
|
match self.lexer.next() {
|
||||||
Some(Spanned(Ok(Token::Comment(_)), _)) => {}
|
Some(Spanned(Ok(Token::Comment(_)), _)) => {}
|
||||||
Some(Spanned(Ok(Token::LineEnd), span)) => {
|
Some(Spanned(Ok(Token::LineEnd), span)) => {
|
||||||
self.peek = Spanned(Some(Token::LineEnd), span);
|
self.peek = Some(Spanned(Token::LineEnd, span));
|
||||||
return self.peek;
|
return self.peek;
|
||||||
}
|
}
|
||||||
Some(Spanned(Ok(ok), r)) => return Spanned(Some(ok), r),
|
Some(Spanned(Ok(ok), r)) => return Some(Spanned(ok, r)),
|
||||||
Some(Spanned(Err(err), span)) => self.logs.emit_error(format!("lexer: {err:?}"), span),
|
Some(Spanned(Err(err), span)) => {
|
||||||
None => return Spanned(None, self.lexer.eof_span())
|
self.logs.emit_error(format!("lexer: {err:?}"), span)
|
||||||
|
}
|
||||||
|
None => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek_token(&mut self) -> Spanned<Option<Token<'a>>> {
|
fn peek_token(&mut self) -> Option<Spanned<Token<'a>>> {
|
||||||
if self.peek.0.is_none() {
|
if self.peek.is_none() {
|
||||||
self.peek = self.next_token();
|
self.peek = self.next_token();
|
||||||
}
|
}
|
||||||
self.peek
|
self.peek
|
||||||
|
|
@ -79,14 +85,14 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
fn parse_symbol(&mut self) -> Spanned<Symbol<'a>> {
|
fn parse_symbol(&mut self) -> Spanned<Symbol<'a>> {
|
||||||
match self.next_token() {
|
match self.next_token() {
|
||||||
Spanned(Some(Token::Tilde), r) => Spanned(Symbol::Epsilon, r),
|
Some(Spanned(Token::Tilde, r)) => Spanned(Symbol::Epsilon, r),
|
||||||
Spanned(Some(Token::Ident("epsilon")), r) => Spanned(Symbol::Epsilon, r),
|
Some(Spanned(Token::Ident("epsilon"), r)) => Spanned(Symbol::Epsilon, r),
|
||||||
Spanned(Some(Token::Ident(super::EPSILON_LOWER)), r) => Spanned(Symbol::Epsilon, r),
|
Some(Spanned(Token::Ident(super::EPSILON_LOWER), r)) => Spanned(Symbol::Epsilon, r),
|
||||||
Spanned(Some(Token::Ident(ident)), r) => Spanned(Symbol::Ident(ident), r),
|
Some(Spanned(Token::Ident(ident), r)) => Spanned(Symbol::Ident(ident), r),
|
||||||
Spanned(Some(got), span) => {
|
Some(Spanned(got, span)) => {
|
||||||
self.logs.emit_error(
|
self.logs.emit_error(
|
||||||
format!(
|
format!(
|
||||||
"unexpected token {:#}, expected {:}|{:} (symbol)",
|
"unexpected {:#}, expected {:} | {:} (symbol)",
|
||||||
got,
|
got,
|
||||||
Token::Tilde,
|
Token::Tilde,
|
||||||
Token::Ident("")
|
Token::Ident("")
|
||||||
|
|
@ -95,14 +101,14 @@ impl<'a> Parser<'a> {
|
||||||
);
|
);
|
||||||
Spanned(Symbol::Ident("<INVALID>"), span)
|
Spanned(Symbol::Ident("<INVALID>"), span)
|
||||||
}
|
}
|
||||||
Spanned(None, span) => {
|
None => {
|
||||||
self.logs.emit_error(
|
self.logs.emit_error(
|
||||||
format!(
|
format!(
|
||||||
"unexpected eof expected {:} | {:} (symbol)",
|
"unexpected eof expected {:} | {:} (symbol)",
|
||||||
Token::Tilde,
|
Token::Tilde,
|
||||||
Token::Ident("")
|
Token::Ident("")
|
||||||
),
|
),
|
||||||
span,
|
self.eof(),
|
||||||
);
|
);
|
||||||
Spanned(Symbol::Ident("<INVALID>"), self.eof())
|
Spanned(Symbol::Ident("<INVALID>"), self.eof())
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +160,7 @@ impl<'a> Parser<'a> {
|
||||||
self.next_token();
|
self.next_token();
|
||||||
self.logs.emit_error(
|
self.logs.emit_error(
|
||||||
format!(
|
format!(
|
||||||
"unexpected token {:#}, expected {:}|{:}|{:}|{:}|{:} (item)",
|
"unexpected {:#}, expected {:} | {:} | {:} | {:} | {:} (item)",
|
||||||
got,
|
got,
|
||||||
Token::Tilde,
|
Token::Tilde,
|
||||||
Token::Ident(""),
|
Token::Ident(""),
|
||||||
|
|
@ -192,7 +198,7 @@ impl<'a> Parser<'a> {
|
||||||
Some(Spanned(got, span)) => {
|
Some(Spanned(got, span)) => {
|
||||||
self.logs.emit_error(
|
self.logs.emit_error(
|
||||||
format!(
|
format!(
|
||||||
"unexpected token {:#}, expected {:}|{:}",
|
"unexpected {:#}, expected {:} | {:}",
|
||||||
got,
|
got,
|
||||||
Token::RBrace,
|
Token::RBrace,
|
||||||
Token::RBracket
|
Token::RBracket
|
||||||
|
|
@ -268,41 +274,61 @@ impl<'a> Parser<'a> {
|
||||||
lhs_group.0.push(sym);
|
lhs_group.0.push(sym);
|
||||||
}
|
}
|
||||||
if !self.expect_token(Token::LSmallArrow).0 {
|
if !self.expect_token(Token::LSmallArrow).0 {
|
||||||
return Some(Spanned(TopLevel::ProductionRule(Spanned(lhs_group, start.join(lhs_group_end)), Spanned(vec![], lhs_group_end)), start.join(lhs_group_end)))
|
return Some(Spanned(
|
||||||
|
TopLevel::ProductionRule(
|
||||||
|
Spanned(lhs_group, start.join(lhs_group_end)),
|
||||||
|
Spanned(vec![], lhs_group_end),
|
||||||
|
),
|
||||||
|
start.join(lhs_group_end),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut groups = Vec::new();
|
let mut groups = Vec::new();
|
||||||
|
|
||||||
while !matches!(self.peek_token(), None | Some(Spanned(Token::LineEnd, _))){
|
loop {
|
||||||
let mut group = ProductionGroup(vec![]);
|
let mut group = ProductionGroup(vec![]);
|
||||||
while !matches!(self.peek_token(), None | Some(Spanned(Token::LineEnd|Token::Or, _))){
|
while !matches!(
|
||||||
|
self.peek_token(),
|
||||||
|
None | Some(Spanned(Token::LineEnd | Token::Or, _))
|
||||||
|
) {
|
||||||
group.0.push(self.parse_symbol());
|
group.0.push(self.parse_symbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.0.is_empty() {
|
if group.0.is_empty() {
|
||||||
let span = if let Some(Spanned(_, span)) = self.peek_token(){
|
let eof = self.eof();
|
||||||
span
|
let span = self.peek_token().map(|t| t.1).unwrap_or(eof);
|
||||||
}else{
|
self.logs
|
||||||
self.eof()
|
.emit_error("cannot have empty production group", span);
|
||||||
};
|
|
||||||
self.logs.emit_error("cannot have empty production rule", span);
|
|
||||||
}
|
|
||||||
if matches!(self.peek_token(), Some(Spanned(Token::Or, _))){
|
|
||||||
self.next_token();
|
|
||||||
// if matches!(self.peek_token(), None|Spanned(Token::Or|Token::LineEnd))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let group_start = group.0.first().map(|g| g.1).unwrap_or(start);
|
let group_start = group.0.first().map(|g| g.1).unwrap_or(start);
|
||||||
let group_end = group.0.last().map(|g| g.1).unwrap_or(start);
|
let group_end = group.0.last().map(|g| g.1).unwrap_or(start);
|
||||||
groups.push(Spanned(group, group_start.join(group_end)))
|
groups.push(Spanned(group, group_start.join(group_end)));
|
||||||
|
|
||||||
|
if matches!(self.peek_token(), Some(Spanned(Token::Or, _))) {
|
||||||
|
self.next_token();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if groups.is_empty() {
|
if groups.is_empty() {
|
||||||
self.logs.emit_error("cannot have empty production rule", start.join(lhs_group_end));
|
self.logs.emit_error(
|
||||||
|
"cannot have empty production rule",
|
||||||
|
start.join(lhs_group_end),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rules_start = groups.first().map(|f| f.1).unwrap_or(start);
|
let rules_start = groups.first().map(|f| f.1).unwrap_or(start);
|
||||||
let rules_end = groups.last().map(|f| f.1).unwrap_or(start);
|
let rules_end = groups.last().map(|f| f.1).unwrap_or(start);
|
||||||
|
|
||||||
Some(Spanned(TopLevel::ProductionRule(Spanned(lhs_group, start.join(lhs_group_end)), Spanned(groups, rules_start.join(rules_end))), start.join(rules_end)))
|
Some(Spanned(
|
||||||
|
TopLevel::ProductionRule(
|
||||||
|
Spanned(lhs_group, start.join(lhs_group_end)),
|
||||||
|
Spanned(groups, rules_start.join(rules_end)),
|
||||||
|
),
|
||||||
|
start.join(rules_end),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_transition_function(
|
fn parse_transition_function(
|
||||||
|
|
@ -350,7 +376,7 @@ impl<'a> Parser<'a> {
|
||||||
break Some(pr);
|
break Some(pr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Spanned(Token::Ident(ident), start), _) => {
|
(Spanned(Token::Ident(ident), start), Some(Spanned(Token::Eq, _))) => {
|
||||||
let name = Spanned(ident, start);
|
let name = Spanned(ident, start);
|
||||||
if !self.expect_token(Token::Eq).0 {
|
if !self.expect_token(Token::Eq).0 {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -359,19 +385,39 @@ impl<'a> Parser<'a> {
|
||||||
let span = start.join(item.1);
|
let span = start.join(item.1);
|
||||||
break Some(Spanned(TopLevel::Item(name, item), span));
|
break Some(Spanned(TopLevel::Item(name, item), span));
|
||||||
}
|
}
|
||||||
_ => {
|
(Spanned(Token::Ident(_), _), after) => {
|
||||||
|
match after {
|
||||||
|
Some(Spanned(tok, span)) => {
|
||||||
self.logs.emit_error(
|
self.logs.emit_error(
|
||||||
format!(
|
format!(
|
||||||
"unexpected token {:#}, expected {:}",
|
"unexpected {:#}, expected {:} | {:}",
|
||||||
next.0,
|
tok,
|
||||||
Token::Ident("")
|
Token::Eq,
|
||||||
|
Token::LSmallArrow
|
||||||
),
|
),
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.logs.emit_error(
|
||||||
|
format!(
|
||||||
|
"unexpected eof, expected {:} | {:}",
|
||||||
|
Token::Eq,
|
||||||
|
Token::LSmallArrow
|
||||||
|
),
|
||||||
|
self.eof(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while !matches!(self.next_token(), None | Some(Spanned(Token::LineEnd, _))) {}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.logs.emit_error(
|
||||||
|
format!("unexpected {:#}, expected {:}", next.0, Token::Ident("")),
|
||||||
next.1,
|
next.1,
|
||||||
);
|
);
|
||||||
while !matches!(self.next_token(), None|Some(Spanned(Token::LineEnd, _))){
|
while !matches!(self.next_token(), None | Some(Spanned(Token::LineEnd, _))) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.advance_line();
|
self.advance_line();
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let input = "aababdsaab";
|
let input = "aababaaba";
|
||||||
println!("running on: '{input}'");
|
println!("running on: '{input}'");
|
||||||
let mut simulator = npda::Simulator::begin(input, table);
|
let mut simulator = npda::Simulator::begin(input, table);
|
||||||
loop {
|
loop {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue