Fix node-types bugs involving aliases and external tokens
This commit is contained in:
parent
1b5ae380ce
commit
fc19312913
3 changed files with 69 additions and 48 deletions
|
|
@ -401,13 +401,7 @@ fn variable_type_for_child_type(
|
||||||
lexical_grammar: &LexicalGrammar,
|
lexical_grammar: &LexicalGrammar,
|
||||||
) -> VariableType {
|
) -> VariableType {
|
||||||
match child_type {
|
match child_type {
|
||||||
ChildType::Aliased(alias) => {
|
ChildType::Aliased(alias) => alias.kind(),
|
||||||
if alias.is_named {
|
|
||||||
VariableType::Named
|
|
||||||
} else {
|
|
||||||
VariableType::Anonymous
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ChildType::Normal(symbol) => {
|
ChildType::Normal(symbol) => {
|
||||||
if syntax_grammar.supertype_symbols.contains(&symbol) {
|
if syntax_grammar.supertype_symbols.contains(&symbol) {
|
||||||
VariableType::Named
|
VariableType::Named
|
||||||
|
|
@ -583,9 +577,7 @@ pub(crate) fn generate_node_types_json(
|
||||||
subtypes.sort_unstable();
|
subtypes.sort_unstable();
|
||||||
subtypes.dedup();
|
subtypes.dedup();
|
||||||
node_type_json.subtypes = Some(subtypes);
|
node_type_json.subtypes = Some(subtypes);
|
||||||
} else if variable.kind.is_visible()
|
} else if !syntax_grammar.variables_to_inline.contains(&symbol) {
|
||||||
&& !syntax_grammar.variables_to_inline.contains(&symbol)
|
|
||||||
{
|
|
||||||
// If a rule is aliased under multiple names, then its information
|
// If a rule is aliased under multiple names, then its information
|
||||||
// contributes to multiple entries in the final JSON.
|
// contributes to multiple entries in the final JSON.
|
||||||
for alias in aliases_by_symbol
|
for alias in aliases_by_symbol
|
||||||
|
|
@ -597,9 +589,11 @@ pub(crate) fn generate_node_types_json(
|
||||||
if let Some(alias) = alias {
|
if let Some(alias) = alias {
|
||||||
kind = &alias.value;
|
kind = &alias.value;
|
||||||
is_named = alias.is_named;
|
is_named = alias.is_named;
|
||||||
} else {
|
} else if variable.kind.is_visible() {
|
||||||
kind = &variable.name;
|
kind = &variable.name;
|
||||||
is_named = variable.kind == VariableType::Named;
|
is_named = variable.kind == VariableType::Named;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There may already be an entry with this name, because multiple
|
// There may already be an entry with this name, because multiple
|
||||||
|
|
@ -639,25 +633,49 @@ pub(crate) fn generate_node_types_json(
|
||||||
|
|
||||||
let mut anonymous_node_types = Vec::new();
|
let mut anonymous_node_types = Vec::new();
|
||||||
|
|
||||||
for (i, variable) in lexical_grammar.variables.iter().enumerate() {
|
let empty = HashSet::new();
|
||||||
for alias in aliases_by_symbol
|
let regular_tokens = lexical_grammar
|
||||||
.get(&Symbol::terminal(i))
|
.variables
|
||||||
.unwrap_or(&HashSet::new())
|
.iter()
|
||||||
{
|
.enumerate()
|
||||||
let kind;
|
.flat_map(|(i, variable)| {
|
||||||
let is_named;
|
aliases_by_symbol
|
||||||
if let Some(alias) = alias {
|
.get(&Symbol::terminal(i))
|
||||||
kind = &alias.value;
|
.unwrap_or(&empty)
|
||||||
is_named = alias.is_named;
|
.iter()
|
||||||
} else {
|
.map(move |alias| {
|
||||||
kind = &variable.name;
|
if let Some(alias) = alias {
|
||||||
is_named = variable.kind == VariableType::Named;
|
(&alias.value, alias.kind())
|
||||||
}
|
} else {
|
||||||
|
(&variable.name, variable.kind)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let external_tokens =
|
||||||
|
syntax_grammar
|
||||||
|
.external_tokens
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(i, token)| {
|
||||||
|
aliases_by_symbol
|
||||||
|
.get(&Symbol::external(i))
|
||||||
|
.unwrap_or(&empty)
|
||||||
|
.iter()
|
||||||
|
.map(move |alias| {
|
||||||
|
if let Some(alias) = alias {
|
||||||
|
(&alias.value, alias.kind())
|
||||||
|
} else {
|
||||||
|
(&token.name, token.kind)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
if is_named {
|
for (name, kind) in regular_tokens.chain(external_tokens) {
|
||||||
let node_type_json = node_types_json.entry(kind.clone()).or_insert(NodeInfoJSON {
|
match kind {
|
||||||
kind: kind.clone(),
|
VariableType::Named => {
|
||||||
named: is_named,
|
let node_type_json = node_types_json.entry(name.clone()).or_insert(NodeInfoJSON {
|
||||||
|
kind: name.clone(),
|
||||||
|
named: true,
|
||||||
fields: None,
|
fields: None,
|
||||||
children: None,
|
children: None,
|
||||||
subtypes: None,
|
subtypes: None,
|
||||||
|
|
@ -670,15 +688,15 @@ pub(crate) fn generate_node_types_json(
|
||||||
field.required = false;
|
field.required = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if variable.kind == VariableType::Anonymous {
|
|
||||||
anonymous_node_types.push(NodeInfoJSON {
|
|
||||||
kind: kind.clone(),
|
|
||||||
named: is_named,
|
|
||||||
fields: None,
|
|
||||||
children: None,
|
|
||||||
subtypes: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
VariableType::Anonymous => anonymous_node_types.push(NodeInfoJSON {
|
||||||
|
kind: name.clone(),
|
||||||
|
named: false,
|
||||||
|
fields: None,
|
||||||
|
children: None,
|
||||||
|
subtypes: None,
|
||||||
|
}),
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1284,6 +1302,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_node_types_with_tokens_aliased_to_match_rules() {
|
fn test_node_types_with_tokens_aliased_to_match_rules() {
|
||||||
let node_types = get_node_types(InputGrammar {
|
let node_types = get_node_types(InputGrammar {
|
||||||
|
|
|
||||||
|
|
@ -135,11 +135,7 @@ impl Generator {
|
||||||
|
|
||||||
for alias in &production_info.alias_sequence {
|
for alias in &production_info.alias_sequence {
|
||||||
if let Some(alias) = &alias {
|
if let Some(alias) = &alias {
|
||||||
let alias_kind = if alias.is_named {
|
let alias_kind = alias.kind();
|
||||||
VariableType::Named
|
|
||||||
} else {
|
|
||||||
VariableType::Anonymous
|
|
||||||
};
|
|
||||||
let matching_symbol = self.parse_table.symbols.iter().cloned().find(|symbol| {
|
let matching_symbol = self.parse_table.symbols.iter().cloned().find(|symbol| {
|
||||||
let (name, kind) = self.metadata_for_symbol(*symbol);
|
let (name, kind) = self.metadata_for_symbol(*symbol);
|
||||||
name == alias.value && kind == alias_kind
|
name == alias.value && kind == alias_kind
|
||||||
|
|
@ -336,12 +332,7 @@ impl Generator {
|
||||||
// If so, add an entry to the symbol map that deduplicates these two symbols,
|
// 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.
|
// so that only one of them will ever be returned via the public API.
|
||||||
if let Some(alias) = self.simple_aliases.get(symbol) {
|
if let Some(alias) = self.simple_aliases.get(symbol) {
|
||||||
let kind = if alias.is_named {
|
let kind = alias.kind();
|
||||||
VariableType::Named
|
|
||||||
} else {
|
|
||||||
VariableType::Anonymous
|
|
||||||
};
|
|
||||||
|
|
||||||
for other_symbol in &self.parse_table.symbols {
|
for other_symbol in &self.parse_table.symbols {
|
||||||
if other_symbol == symbol {
|
if other_symbol == symbol {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::grammars::VariableType;
|
||||||
use smallbitvec::SmallBitVec;
|
use smallbitvec::SmallBitVec;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
@ -139,6 +140,16 @@ impl Rule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Alias {
|
||||||
|
pub fn kind(&self) -> VariableType {
|
||||||
|
if self.is_named {
|
||||||
|
VariableType::Named
|
||||||
|
} else {
|
||||||
|
VariableType::Anonymous
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl Rule {
|
impl Rule {
|
||||||
pub fn terminal(index: usize) -> Self {
|
pub fn terminal(index: usize) -> Self {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue