Store a mapping to ensure no two symbols map to the same metadata

This commit is contained in:
Max Brunsfeld 2019-12-05 17:21:46 -08:00
parent d6c7b243a7
commit 56c620c005
7 changed files with 128 additions and 33 deletions

View file

@ -35,7 +35,8 @@ const NEW_HEADER_PARTS: [&'static str; 2] = [
"
uint32_t large_state_count;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;",
const uint32_t *small_parse_table_map;
const TSSymbol *public_symbol_map;",
"
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
",

View file

@ -80,6 +80,11 @@ impl Generator {
self.add_stats();
self.add_symbol_enum();
self.add_symbol_names_list();
if self.next_abi {
self.add_unique_symbol_map();
}
self.add_symbol_metadata_list();
if !self.field_names.is_empty() {
@ -320,6 +325,51 @@ impl Generator {
add_line!(self, "");
}
fn add_unique_symbol_map(&mut self) {
add_line!(self, "static TSSymbol ts_symbol_map[] = {{");
indent!(self);
for symbol in &self.parse_table.symbols {
let mut mapping = symbol;
// If this symbol has a simple alias, then check if its alias has the same
// name and kind (e.g. named vs anonymous) as some other symbol in the grammar.
// If so, add an entry to the symbol map that deduplicates these two symbols,
// so that only one of them will ever be returned via the public API.
if let Some(alias) = self.simple_aliases.get(symbol) {
let kind = if alias.is_named {
VariableType::Named
} else {
VariableType::Anonymous
};
for other_symbol in &self.parse_table.symbols {
if other_symbol == symbol {
continue;
}
if let Some(other_alias) = self.simple_aliases.get(other_symbol) {
if other_symbol < symbol && other_alias == alias {
mapping = other_symbol;
break;
}
} else if self.metadata_for_symbol(*other_symbol) == (&alias.value, kind) {
mapping = other_symbol;
break;
}
}
}
add_line!(
self,
"[{}] = {},",
self.symbol_ids[&symbol],
self.symbol_ids[&mapping],
);
}
dedent!(self);
add_line!(self, "}};");
add_line!(self, "");
}
fn add_field_name_enum(&mut self) {
add_line!(self, "enum {{");
indent!(self);
@ -1072,6 +1122,10 @@ impl Generator {
add_line!(self, ".lex_modes = ts_lex_modes,");
add_line!(self, ".symbol_names = ts_symbol_names,");
if self.next_abi {
add_line!(self, ".public_symbol_map = ts_symbol_map,");
}
if !self.parse_table.production_infos.is_empty() {
add_line!(
self,