diff --git a/crates/generate/src/build_tables/build_parse_table.rs b/crates/generate/src/build_tables/build_parse_table.rs index 8869d4e6d..133508077 100644 --- a/crates/generate/src/build_tables/build_parse_table.rs +++ b/crates/generate/src/build_tables/build_parse_table.rs @@ -15,7 +15,7 @@ use super::{ }; use crate::{ Diagnostic, - build_tables::item::{LookaheadSetPool, prec_display}, + build_tables::item::{LookaheadSetPool, START_PRODUCTION_ID, prec_display}, grammars::{LexicalGrammar, PrecedenceEntry, ReservedWordSetId, SyntaxGrammar, VariableType}, node_types::VariableInfo, rules::{Associativity, Precedence, Symbol, SymbolType, TokenSet}, @@ -73,6 +73,7 @@ struct ParseTableBuilder<'a> { core_ids_by_core: FxHashMap, usize>, state_ids_by_item_set: IndexMap, ParseStateId, BuildHasherDefault>, preceding_symbols_by_id: Vec, + production_info_ids_by_prod_id: Vec>, parse_state_queue: VecDeque, non_terminal_extra_states: Vec<(Symbol, usize)>, actual_conflicts: FxHashSet>, @@ -270,6 +271,7 @@ impl<'a> ParseTableBuilder<'a> { state_ids_by_item_set: IndexMap::default(), core_ids_by_core: FxHashMap::default(), preceding_symbols_by_id: Vec::new(), + production_info_ids_by_prod_id: vec![None; syntax_grammar.productions.len()], parse_state_queue: VecDeque::new(), actual_conflicts: syntax_grammar.expected_conflicts.iter().cloned().collect(), parse_table: ParseTable { @@ -1138,6 +1140,10 @@ impl<'a> ParseTableBuilder<'a> { } fn get_production_id(&mut self, item: &ParseItem) -> ProductionInfoId { + debug_assert_ne!(item.prod_id, START_PRODUCTION_ID); + if let Some(id) = self.production_info_ids_by_prod_id[item.prod_id as usize] { + return id; + } let mut production_info = ProductionInfo { alias_sequence: Vec::new(), field_map: BTreeMap::new(), @@ -1191,7 +1197,7 @@ impl<'a> ParseTableBuilder<'a> { item.production(self.syntax_grammar).steps.len(); } - if let Some(index) = self + let id = if let Some(index) = self .parse_table .production_infos .iter() @@ -1201,7 +1207,9 @@ impl<'a> ParseTableBuilder<'a> { } else { self.parse_table.production_infos.push(production_info); self.parse_table.production_infos.len() - 1 - } + }; + self.production_info_ids_by_prod_id[item.prod_id as usize] = Some(id); + id } fn symbol_name(&self, symbol: Symbol) -> String {