mod parser;
mod reduction;
mod table;
mod terminal;
use proc_macro2::TokenStream;
use quote::quote;
use crate::grammar::Grammar;
use crate::lr::{GrammarInternal, to_grammar_internal};
#[derive(Debug, Clone)]
pub struct CodegenContext {
pub(crate) grammar: GrammarInternal,
pub visibility: String,
pub name: String,
pub use_absolute_path: bool,
pub start_symbol: String,
pub expect_rr: usize,
pub expect_sr: usize,
pub algorithm: crate::LrAlgorithm,
}
impl CodegenContext {
pub fn from_grammar(
grammar_def: &Grammar,
visibility: &str,
use_absolute_path: bool,
) -> Result<Self, String> {
let grammar = to_grammar_internal(grammar_def)?;
let algorithm = match grammar_def.mode.as_str() {
"lr" | "lr1" => crate::LrAlgorithm::Lr1,
_ => crate::LrAlgorithm::Lalr1,
};
Ok(CodegenContext {
grammar,
visibility: visibility.to_string(),
name: grammar_def.name.clone(),
use_absolute_path,
start_symbol: grammar_def.start.clone(),
expect_rr: grammar_def.expect_rr,
expect_sr: grammar_def.expect_sr,
algorithm,
})
}
pub fn core_path(&self) -> &'static str {
if self.use_absolute_path {
"::gazelle"
} else {
"gazelle"
}
}
pub fn core_path_tokens(&self) -> TokenStream {
if self.use_absolute_path {
quote! { ::gazelle }
} else {
quote! { gazelle }
}
}
pub fn get_terminal_type(&self, name: &str) -> Option<&Option<String>> {
let sym = self.grammar.symbols.get(name)?;
self.grammar.terminal_types.get(&sym.id())
}
pub fn get_prec_terminal_type(&self, name: &str) -> Option<&Option<String>> {
let sym = self.grammar.symbols.get(name)?;
self.grammar.prec_terminal_types.get(&sym.id())
}
pub fn get_rule_result_type(&self, name: &str) -> Option<&String> {
let sym = self.grammar.symbols.get(name)?;
self.grammar.nt_types.get(&sym.id())?.as_ref()
}
}
pub fn generate_tokens(ctx: &CodegenContext) -> Result<TokenStream, String> {
let (compiled, info) = table::build_table(ctx)?;
let table_statics = table::generate_table_statics(ctx, &compiled, &info);
let terminal_code = terminal::generate(ctx, &info);
let parser_code = parser::generate(ctx, &info)?;
Ok(quote! {
#table_statics
#terminal_code
#parser_code
})
}