Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn StateTableError to an enum, handle self-loop for #290 #294

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lrtable/src/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub mod statetable;

pub use crate::{
stategraph::StateGraph,
statetable::{Action, StateTable, StateTableError, StateTableErrorKind},
statetable::{Action, StateTable, StateTableError},
};
use cfgrammar::yacc::YaccGrammar;

Expand Down
58 changes: 34 additions & 24 deletions lrtable/src/lib/statetable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,20 @@ where
}
}

/// The various different possible Yacc parser errors.
#[derive(Debug)]
pub enum StateTableErrorKind {
AcceptReduceConflict,
}

/// Any error from the Yacc parser returns an instance of this struct.
#[derive(Debug)]
pub struct StateTableError<StorageT> {
pub kind: StateTableErrorKind,
pub pidx: PIdx<StorageT>,
pub enum StateTableError<StorageT> {
AcceptReduceConflict(PIdx<StorageT>),
StateGraphSelfLoop(RIdx<StorageT>),
}

impl<StorageT: Debug> Error for StateTableError<StorageT> {}

impl<StorageT> fmt::Display for StateTableError<StorageT> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match self.kind {
StateTableErrorKind::AcceptReduceConflict => "Accept/reduce conflict",
let s = match self {
StateTableError::AcceptReduceConflict(_) => "Accept/reduce conflict",
StateTableError::StateGraphSelfLoop(_) => "Recursive rule",
};
write!(f, "{}", s)
}
Expand Down Expand Up @@ -209,10 +204,7 @@ where
Action::Reduce(r_pidx) => {
if pidx == grm.start_prod() && tidx == usize::from(grm.eof_token_idx())
{
return Err(StateTableError {
kind: StateTableErrorKind::AcceptReduceConflict,
pidx,
});
return Err(StateTableError::AcceptReduceConflict(pidx));
}
// By default, Yacc resolves reduce/reduce conflicts in favour
// of the earlier production in the grammar.
Expand All @@ -226,10 +218,7 @@ where
}
}
Action::Accept => {
return Err(StateTableError {
kind: StateTableErrorKind::AcceptReduceConflict,
pidx,
});
return Err(StateTableError::AcceptReduceConflict(pidx));
}
Action::Error => {
if pidx == grm.start_prod() && tidx == usize::from(grm.eof_token_idx())
Expand All @@ -255,6 +244,10 @@ where
debug_assert!(gotos[off] == 0);
// Since 0 is reserved for no entry, encode states by adding 1
gotos[off] = usize::from(*ref_stidx) + 1;

if usize::from(stidx) == usize::from(*ref_stidx) {
return Err(StateTableError::StateGraphSelfLoop(s_ridx));
}
}
Symbol::Token(s_tidx) => {
// Populate shifts
Expand Down Expand Up @@ -590,7 +583,7 @@ mod test {
};
use std::collections::HashSet;

use super::{Action, StateTable, StateTableError, StateTableErrorKind};
use super::{Action, StateTable, StateTableError};
use crate::{pager::pager_stategraph, StIdx};

#[test]
Expand Down Expand Up @@ -975,10 +968,27 @@ D : D;
let sg = pager_stategraph(&grm);
match StateTable::new(&grm, &sg) {
Ok(_) => panic!("Infinitely recursive rule let through"),
Err(StateTableError {
kind: StateTableErrorKind::AcceptReduceConflict,
pidx,
}) if pidx == PIdx(1) => (),
Err(StateTableError::AcceptReduceConflict(pidx)) if pidx == PIdx(1) => (),
Err(e) => panic!("Incorrect error returned {:?}", e),
}
}
#[test]
fn recursive_rule() {
// issue #290
let grm = YaccGrammar::new(
YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
r#"
%%
Start: Bar;
Foo: "a" | ;
Bar: Foo | Foo Bar;
"#,
)
.unwrap();
let sg = pager_stategraph(&grm);
match StateTable::new(&grm, &sg) {
Ok(_) => panic!("Infinitely recursive rule let through"),
Err(StateTableError::StateGraphSelfLoop(_)) => (),
Err(e) => panic!("Incorrect error returned {:?}", e),
}
}
Expand Down