diff --git a/cli/src/generate/build_tables/build_lex_table.rs b/cli/src/generate/build_tables/build_lex_table.rs index 42a95e4c..be265b7a 100644 --- a/cli/src/generate/build_tables/build_lex_table.rs +++ b/cli/src/generate/build_tables/build_lex_table.rs @@ -1,7 +1,7 @@ use super::coincident_tokens::CoincidentTokenIndex; use super::item::TokenSet; -use super::split_state_id_groups; use super::token_conflicts::TokenConflictMap; +use crate::generate::dedup::split_state_id_groups; use crate::generate::grammars::{LexicalGrammar, SyntaxGrammar}; use crate::generate::nfa::{CharacterSet, NfaCursor}; use crate::generate::rules::Symbol; diff --git a/cli/src/generate/build_tables/minimize_parse_table.rs b/cli/src/generate/build_tables/minimize_parse_table.rs index d1823fc7..906ce685 100644 --- a/cli/src/generate/build_tables/minimize_parse_table.rs +++ b/cli/src/generate/build_tables/minimize_parse_table.rs @@ -1,6 +1,6 @@ use super::item::TokenSet; -use super::split_state_id_groups; use super::token_conflicts::TokenConflictMap; +use crate::generate::dedup::split_state_id_groups; use crate::generate::grammars::{LexicalGrammar, SyntaxGrammar, VariableType}; use crate::generate::rules::{AliasMap, Symbol}; use crate::generate::tables::{ParseAction, ParseState, ParseStateId, ParseTable, ParseTableEntry}; diff --git a/cli/src/generate/build_tables/mod.rs b/cli/src/generate/build_tables/mod.rs index d2425dc5..54356d8d 100644 --- a/cli/src/generate/build_tables/mod.rs +++ b/cli/src/generate/build_tables/mod.rs @@ -349,67 +349,3 @@ fn all_chars_are_alphabetical(cursor: &NfaCursor) -> bool { } }) } - -fn split_state_id_groups( - states: &Vec, - state_ids_by_group_id: &mut Vec>, - group_ids_by_state_id: &mut Vec, - start_group_id: usize, - mut f: impl FnMut(&S, &S, &Vec) -> bool, -) -> bool { - let mut result = false; - - let mut group_id = start_group_id; - while group_id < state_ids_by_group_id.len() { - let state_ids = &state_ids_by_group_id[group_id]; - let mut split_state_ids = Vec::new(); - - let mut i = 0; - while i < state_ids.len() { - let left_state_id = state_ids[i]; - if split_state_ids.contains(&left_state_id) { - i += 1; - continue; - } - - let left_state = &states[left_state_id]; - - // Identify all of the other states in the group that are incompatible with - // this state. - let mut j = i + 1; - while j < state_ids.len() { - let right_state_id = state_ids[j]; - if split_state_ids.contains(&right_state_id) { - j += 1; - continue; - } - let right_state = &states[right_state_id]; - - if f(left_state, right_state, &group_ids_by_state_id) { - split_state_ids.push(right_state_id); - } - - j += 1; - } - - i += 1; - } - - // If any states were removed from the group, add them all as a new group. - if split_state_ids.len() > 0 { - result = true; - state_ids_by_group_id[group_id].retain(|i| !split_state_ids.contains(&i)); - - let new_group_id = state_ids_by_group_id.len(); - for id in &split_state_ids { - group_ids_by_state_id[*id] = new_group_id; - } - - state_ids_by_group_id.push(split_state_ids); - } - - group_id += 1; - } - - result -} diff --git a/cli/src/generate/dedup.rs b/cli/src/generate/dedup.rs new file mode 100644 index 00000000..dcba2318 --- /dev/null +++ b/cli/src/generate/dedup.rs @@ -0,0 +1,63 @@ +pub(crate) fn split_state_id_groups( + states: &Vec, + state_ids_by_group_id: &mut Vec>, + group_ids_by_state_id: &mut Vec, + start_group_id: usize, + mut f: impl FnMut(&S, &S, &Vec) -> bool, +) -> bool { + let mut result = false; + + let mut group_id = start_group_id; + while group_id < state_ids_by_group_id.len() { + let state_ids = &state_ids_by_group_id[group_id]; + let mut split_state_ids = Vec::new(); + + let mut i = 0; + while i < state_ids.len() { + let left_state_id = state_ids[i]; + if split_state_ids.contains(&left_state_id) { + i += 1; + continue; + } + + let left_state = &states[left_state_id]; + + // Identify all of the other states in the group that are incompatible with + // this state. + let mut j = i + 1; + while j < state_ids.len() { + let right_state_id = state_ids[j]; + if split_state_ids.contains(&right_state_id) { + j += 1; + continue; + } + let right_state = &states[right_state_id]; + + if f(left_state, right_state, &group_ids_by_state_id) { + split_state_ids.push(right_state_id); + } + + j += 1; + } + + i += 1; + } + + // If any states were removed from the group, add them all as a new group. + if split_state_ids.len() > 0 { + result = true; + state_ids_by_group_id[group_id].retain(|i| !split_state_ids.contains(&i)); + + let new_group_id = state_ids_by_group_id.len(); + for id in &split_state_ids { + group_ids_by_state_id[*id] = new_group_id; + } + + state_ids_by_group_id.push(split_state_ids); + } + + group_id += 1; + } + + result +} diff --git a/cli/src/generate/mod.rs b/cli/src/generate/mod.rs index f625c9f8..e4daa071 100644 --- a/cli/src/generate/mod.rs +++ b/cli/src/generate/mod.rs @@ -11,6 +11,7 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; mod build_tables; +mod dedup; mod grammars; mod nfa; mod node_types;