use super::search_table::SearchTableSet;
use super::StateIdx;
use super::DFA;
use crate::ast::RuleRhs;
use crate::collections::Map;
use crate::dfa::simplify::Trans;
use crate::semantic_action_table::{SemanticActionIdx, SemanticActionTable};
pub struct CgCtx {
semantic_action_table: SemanticActionTable,
lexer_name: syn::Ident,
token_type: syn::Type,
user_error_type: Option<syn::Type>,
rule_states: Map<String, StateIdx>,
inlined_states: Vec<StateIdx>,
codegen_state: CgState,
}
struct CgState {
search_tables: SearchTableSet,
}
impl CgCtx {
pub fn new(
dfa: &DFA<Trans<SemanticActionIdx>, SemanticActionIdx>,
semantic_action_table: SemanticActionTable,
lexer_name: syn::Ident,
token_type: syn::Type,
user_error_type: Option<syn::Type>,
rule_states: Map<String, StateIdx>,
) -> CgCtx {
let inlined_states: Vec<StateIdx> = dfa
.states
.iter()
.enumerate()
.filter_map(|(state_idx, state)| {
if state.predecessors.len() == 1 {
Some(StateIdx(state_idx))
} else {
None
}
})
.collect();
CgCtx {
semantic_action_table,
lexer_name,
token_type,
user_error_type,
rule_states,
inlined_states,
codegen_state: CgState {
search_tables: SearchTableSet::new(),
},
}
}
pub fn lexer_name(&self) -> &syn::Ident {
&self.lexer_name
}
pub fn renumber_state(&self, state: StateIdx) -> StateIdx {
match self.inlined_states.binary_search(&state) {
Ok(idx) | Err(idx) => state.map(|state_idx| state_idx - idx),
}
}
pub fn n_inlined_states(&self) -> usize {
self.inlined_states.len()
}
pub fn token_type(&self) -> &syn::Type {
&self.token_type
}
pub fn user_error_type(&self) -> Option<&syn::Type> {
self.user_error_type.as_ref()
}
pub fn add_search_table(&mut self, ranges: Vec<(char, char)>) -> syn::Ident {
self.codegen_state.search_tables.add_table(ranges)
}
pub fn take_search_tables(&mut self) -> SearchTableSet {
std::mem::replace(&mut self.codegen_state.search_tables, SearchTableSet::new())
}
pub fn rule_states(&self) -> &Map<String, StateIdx> {
&self.rule_states
}
pub fn iter_semantic_actions(&self) -> impl Iterator<Item = (SemanticActionIdx, &RuleRhs)> {
self.semantic_action_table.iter()
}
pub fn semantic_action_fn_ident(&self, action: SemanticActionIdx) -> syn::Ident {
syn::Ident::new(
&format!("{}_ACTION_{}", self.lexer_name, action.as_usize()),
self.lexer_name.span(),
)
}
}