diff --git a/src/utils/follow/mod.rs b/src/utils/follow/mod.rs index 8934b2d..95f65c6 100644 --- a/src/utils/follow/mod.rs +++ b/src/utils/follow/mod.rs @@ -1,6 +1,9 @@ use crate::utils::follow::builder::FollowBuilder; use bnf::{Grammar, Term}; +use itertools::Itertools; use std::collections::{HashMap, HashSet}; +use tabled::builder::Builder; +use tabled::Table; mod builder; @@ -17,4 +20,58 @@ impl<'grammar> Follow<'grammar> { // TODO: remove the unwrap? self.follow.get(x).unwrap().iter() } + + pub fn tabled(&self) -> Table { + let mut table = Builder::new(); + table.set_header(["Term", "Follow(X)"]); + for (term, first) in self + .follow + .iter() + .filter(|(term, _)| matches!(term, Term::Nonterminal(_))) + .sorted_by(|a, b| a.0.cmp(b.0)) + { + table.push_record([term.to_string(), first.iter().sorted().join(", ")]); + } + table.build() + } +} + +#[cfg(test)] +mod tests { + use crate::utils::follow::Follow; + use bnf::Term; + use std::str::FromStr; + + #[test] + fn it_works() { + let grammar = r#" + ::= + ::= '+' | 'ε' + ::= + ::= '*' | 'ε' + ::= '(' ')' | 'id' + "# + .parse() + .unwrap(); + let start = Term::from_str("").unwrap(); + let follow = Follow::new(&grammar, &start); + insta::assert_display_snapshot!(follow.tabled()); + } + + #[test] + fn test_case_1() { + let grammar = r#" +

::= 'id' + ::= '∃' | '∀' + ::= '=' + ::= + ::= '+' | 'ε' + ::= '(' ')' | 'id' + "# + .parse() + .unwrap(); + let start = Term::from_str("

").unwrap(); + let follow = Follow::new(&grammar, &start); + insta::assert_display_snapshot!(follow.tabled()); + } } diff --git a/src/utils/follow/snapshots/context_free__utils__follow__tests__case_1.snap b/src/utils/follow/snapshots/context_free__utils__follow__tests__case_1.snap new file mode 100644 index 0000000..c197cd5 --- /dev/null +++ b/src/utils/follow/snapshots/context_free__utils__follow__tests__case_1.snap @@ -0,0 +1,19 @@ +--- +source: src/utils/follow/mod.rs +expression: follow.tabled() +--- ++------+--------------------+ +| Term | Follow(X) | ++------+--------------------+ +| | "$", ")", "=" | ++------+--------------------+ +| | "$", ")", "=" | ++------+--------------------+ +|

| "$" | ++------+--------------------+ +| | "id" | ++------+--------------------+ +| | "$" | ++------+--------------------+ +| | "$", ")", "+", "=" | ++------+--------------------+ diff --git a/src/utils/follow/snapshots/context_free__utils__follow__tests__it_works.snap b/src/utils/follow/snapshots/context_free__utils__follow__tests__it_works.snap new file mode 100644 index 0000000..de29f88 --- /dev/null +++ b/src/utils/follow/snapshots/context_free__utils__follow__tests__it_works.snap @@ -0,0 +1,17 @@ +--- +source: src/utils/follow/mod.rs +expression: follow.tabled() +--- ++------+--------------------+ +| Term | Follow(X) | ++------+--------------------+ +| | "$", ")" | ++------+--------------------+ +| | "$", ")" | ++------+--------------------+ +| | "$", ")", "*", "+" | ++------+--------------------+ +| | "$", ")", "+" | ++------+--------------------+ +| | "$", ")", "+" | ++------+--------------------+