summaryrefslogtreecommitdiff
path: root/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'grammar')
-rw-r--r--grammar/src/label.rs6
-rw-r--r--grammar/src/lib.rs20
-rw-r--r--grammar/src/tests/test_grammar_left_closure.rs55
3 files changed, 26 insertions, 55 deletions
diff --git a/grammar/src/label.rs b/grammar/src/label.rs
index 058baaf..e3f3422 100644
--- a/grammar/src/label.rs
+++ b/grammar/src/label.rs
@@ -119,6 +119,12 @@ impl GrammarLabel {
self.end
}
+ /// Set the start.
+ #[inline]
+ pub fn set_start(&mut self, pos: usize) {
+ self.start = pos;
+ }
+
/// Return the start in the input.
#[inline]
pub fn start(&self) -> usize {
diff --git a/grammar/src/lib.rs b/grammar/src/lib.rs
index ab0f693..21ce2b4 100644
--- a/grammar/src/lib.rs
+++ b/grammar/src/lib.rs
@@ -25,6 +25,12 @@ use std::{
fmt::Display,
};
+/// The index of the starting non-terminal.
+///
+/// By convention this is the zero-th non-terminal. I define this
+/// constant just for the sake of clarity.
+pub const START_NONTERMINAL: usize = 0;
+
/// The type of a terminal.
///
/// For the time being this is a wrapper around a string, but in the
@@ -478,8 +484,17 @@ impl Grammar {
/// Return true if and only if the terminal can appear as the
/// first terminal in a string expanded from the non-terminal.
+ ///
+ /// # Errors
+ ///
+ /// If `non_terminal` or `terminal` is out of bounds, the function
+ /// returns an error indicating this fact.
#[inline]
pub fn is_first_of(&self, non_terminal: usize, terminal: usize) -> Result<bool, Error> {
+ if terminal >= self.ter_num() {
+ return Err(Error::IndexOutOfBounds(terminal, self.ter_num()));
+ }
+
Ok(self
.firsts
.get(non_terminal)
@@ -488,6 +503,11 @@ impl Grammar {
}
/// Return true if and only if the non-terminal is nullable.
+ ///
+ /// # Error
+ ///
+ /// If `non_terminal` is out of bounds, return the corresponding
+ /// error.
#[inline]
pub fn is_nullable(&self, non_terminal: usize) -> Result<bool, Error> {
Ok(self
diff --git a/grammar/src/tests/test_grammar_left_closure.rs b/grammar/src/tests/test_grammar_left_closure.rs
index ffc7c0f..be1df9d 100644
--- a/grammar/src/tests/test_grammar_left_closure.rs
+++ b/grammar/src/tests/test_grammar_left_closure.rs
@@ -82,59 +82,6 @@ fn test_nfa() -> Result<(), Box<dyn std::error::Error>> {
}
#[test]
-fn test_remove_epsilon() -> Result<(), Box<dyn std::error::Error>> {
- let mut lock = stdout().lock();
-
- let mut grammar = new_paren_grammar()?;
-
- writeln!(lock, "grammar:")?;
- writeln!(lock, "{grammar}")?;
-
- let closure = new_closure_regex(&mut grammar)?;
-
- let mut accumulator_value: usize = 0;
-
- for regex in closure.iter() {
- writeln!(
- lock,
- "regex: {}",
- regex.to_string_with(|tnt| {
- match tnt {
- TNT::Ter(t) => {
- format!(
- "({})",
- grammar.name_of_tnt(grammar.unpack_tnt(t).unwrap()).unwrap()
- )
- }
- TNT::Non(_) => {
- // hyper non-terminal
- format!("({})", grammar.name_of_tnt(tnt).unwrap())
- }
- }
- })?
- )?;
- writeln!(lock, "regex len = {}", regex.nodes_len())?;
- writeln!(lock, "offset = {accumulator_value}")?;
-
- accumulator_value += regex.nodes_len();
- }
-
- writeln!(lock, "total = {accumulator_value}")?;
-
- let mut nfa = grammar.left_closure_to_nfa(&closure)?;
-
- #[cfg(features = "test-print-viz")]
- nfa.print_viz("nfa_orig.gv")?;
-
- nfa.remove_epsilon(|label| label.get_value().is_none())?;
-
- #[cfg(features = "test-print-viz")]
- nfa.print_viz("nfa_no_epsilon.gv")?;
-
- Ok(())
-}
-
-#[test]
fn test_remove_dead() -> Result<(), Box<dyn std::error::Error>> {
let mut grammar = new_paren_grammar()?;
let closure = new_closure_regex(&mut grammar)?;
@@ -177,8 +124,6 @@ fn test_remove_dead() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(features = "test-print-viz")]
nfa.print_viz("nfa_orig.gv")?;
- // nfa.remove_epsilon(|label| label.get_value().is_none())?;
-
let accumulators: HashSet<usize> = accumulators.into_iter().collect();
println!("accumulators = {accumulators:?}");