From 381cb09c647a056b29006bfeeab2b37dce6f2c8b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 17 Jun 2019 11:35:06 -0700 Subject: [PATCH 1/4] Include info about children w/o fields in node-types.json --- cli/src/generate/grammars.rs | 2 +- cli/src/generate/node_types.rs | 131 ++++++++++++++++++++++++--------- 2 files changed, 97 insertions(+), 36 deletions(-) diff --git a/cli/src/generate/grammars.rs b/cli/src/generate/grammars.rs index f904efa3..bca03c39 100644 --- a/cli/src/generate/grammars.rs +++ b/cli/src/generate/grammars.rs @@ -2,7 +2,7 @@ use super::nfa::Nfa; use super::rules::{Alias, Associativity, Rule, Symbol}; use hashbrown::HashMap; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub(crate) enum VariableType { Hidden, Auxiliary, diff --git a/cli/src/generate/node_types.rs b/cli/src/generate/node_types.rs index f43ffce2..60a8f430 100644 --- a/cli/src/generate/node_types.rs +++ b/cli/src/generate/node_types.rs @@ -23,6 +23,7 @@ pub(crate) struct FieldInfo { pub(crate) struct VariableInfo { pub fields: HashMap, pub child_types: Vec, + pub child_types_without_fields: Vec, pub has_multi_step_production: bool, } @@ -34,6 +35,8 @@ pub(crate) struct NodeInfoJSON { #[serde(skip_serializing_if = "Option::is_none")] fields: Option>, #[serde(skip_serializing_if = "Option::is_none")] + children: Option, + #[serde(skip_serializing_if = "Option::is_none")] subtypes: Option>, } @@ -63,6 +66,7 @@ pub(crate) fn get_variable_info( let mut info = VariableInfo { fields: HashMap::new(), child_types: Vec::new(), + child_types_without_fields: Vec::new(), has_multi_step_production: false, }; let is_recursive = variable @@ -83,15 +87,21 @@ pub(crate) fn get_variable_info( }; if let Some(field_name) = &step.field_name { - let field_info = info.fields.entry(field_name.clone()).or_insert(FieldInfo { - multiple: false, - required: true, - types: Vec::new(), - }); + let field_info = info.fields + .entry(field_name.clone()) + .or_insert(FieldInfo { + multiple: false, + required: true, + types: Vec::new(), + }); field_info.multiple |= is_recursive; if let Err(i) = field_info.types.binary_search(&child_type) { field_info.types.insert(i, child_type.clone()); } + } else if variable_type_for_child_type(&child_type, syntax_grammar, lexical_grammar) == VariableType::Named { + if let Err(i) = info.child_types_without_fields.binary_search(&child_type) { + info.child_types_without_fields.insert(i, child_type.clone()); + } } if let Err(i) = info.child_types.binary_search(&child_type) { @@ -107,9 +117,18 @@ pub(crate) fn get_variable_info( .filter_map(|s| s.field_name.as_ref()) .collect(); for (field_name, field_info) in info.fields.iter_mut() { - if !production_fields.contains(&field_name) { + let mut occurrence_count = 0; + for f in &production_fields { + if *f == field_name { + occurrence_count += 1; + } + } + if occurrence_count == 0 { field_info.required = false; } + if occurrence_count > 1 { + field_info.multiple = true; + } } } @@ -135,6 +154,7 @@ pub(crate) fn get_variable_info( && !syntax_grammar.variables[child_symbol.index] .kind .is_visible() + && !syntax_grammar.supertype_symbols.contains(&child_symbol) { let child_variable_info = &result[child_symbol.index]; @@ -169,25 +189,32 @@ pub(crate) fn get_variable_info( } } - if !syntax_grammar.supertype_symbols.contains(&child_symbol) { - // Inherit child types from this hidden child + // Inherit child types from this hidden child + for child_type in &child_variable_info.child_types { + if let Err(i) = variable_info.child_types.binary_search(&child_type) + { + variable_info.child_types.insert(i, child_type.clone()); + done = false; + } + } + + // If any field points to this hidden child, inherit child types + // for the field. + if let Some(field_name) = &step.field_name { + let field_info = variable_info.fields.get_mut(field_name).unwrap(); for child_type in &child_variable_info.child_types { - if let Err(i) = variable_info.child_types.binary_search(&child_type) - { - variable_info.child_types.insert(i, child_type.clone()); + if let Err(i) = field_info.types.binary_search(&child_type) { + field_info.types.insert(i, child_type.clone()); done = false; } } - - // If any field points to this hidden child, inherit child types - // for the field. - if let Some(field_name) = &step.field_name { - let field_info = variable_info.fields.get_mut(field_name).unwrap(); - for child_type in &child_variable_info.child_types { - if let Err(i) = field_info.types.binary_search(&child_type) { - field_info.types.insert(i, child_type.clone()); - done = false; - } + } else { + // Inherit child types without fields from this hidden child + for child_type in &child_variable_info.child_types_without_fields { + if let Err(i) = variable_info.child_types_without_fields.binary_search(&child_type) + { + variable_info.child_types_without_fields.insert(i, child_type.clone()); + done = false; } } } @@ -217,20 +244,8 @@ pub(crate) fn get_variable_info( } } - let child_type_is_visible = |child_type: &ChildType| match child_type { - ChildType::Aliased(_) => true, - ChildType::Normal(symbol) => { - if syntax_grammar.supertype_symbols.contains(&symbol) { - return true; - } - let variable_kind = match symbol.kind { - SymbolType::NonTerminal => syntax_grammar.variables[symbol.index].kind, - SymbolType::Terminal => lexical_grammar.variables[symbol.index].kind, - SymbolType::External => syntax_grammar.external_tokens[symbol.index].kind, - _ => VariableType::Hidden, - }; - variable_kind.is_visible() - } + let child_type_is_visible = |t: &ChildType| { + variable_type_for_child_type(t, syntax_grammar, lexical_grammar) >= VariableType::Anonymous }; for supertype_symbol in &syntax_grammar.supertype_symbols { @@ -259,12 +274,42 @@ pub(crate) fn get_variable_info( field_info.types.retain(child_type_is_visible); } + variable_info.child_types_without_fields.retain(child_type_is_visible); + result[i] = variable_info; } Ok(result) } +fn variable_type_for_child_type( + child_type: &ChildType, + syntax_grammar: &SyntaxGrammar, + lexical_grammar: &LexicalGrammar, +) -> VariableType { + match child_type { + ChildType::Aliased(alias) => { + if alias.is_named { + VariableType::Named + } else { + VariableType::Anonymous + } + } + ChildType::Normal(symbol) => { + if syntax_grammar.supertype_symbols.contains(&symbol) { + return VariableType::Named; + } else { + match symbol.kind { + SymbolType::NonTerminal => syntax_grammar.variables[symbol.index].kind, + SymbolType::Terminal => lexical_grammar.variables[symbol.index].kind, + SymbolType::External => syntax_grammar.external_tokens[symbol.index].kind, + _ => VariableType::Hidden, + } + } + } + } +} + fn sorted_vec_replace(left: &mut Vec, right: &Vec, value: T) -> bool where T: Eq + Ord, @@ -366,6 +411,7 @@ pub(crate) fn generate_node_types_json( kind: name.clone(), named: true, fields: None, + children: None, subtypes: None, }); let mut subtypes = info @@ -384,6 +430,7 @@ pub(crate) fn generate_node_types_json( kind: name.clone(), named: true, fields: None, + children: None, subtypes: None, }); let mut fields_json = BTreeMap::new(); @@ -403,6 +450,13 @@ pub(crate) fn generate_node_types_json( field_info_json.types.dedup(); } node_type_json.fields = Some(fields_json); + if info.child_types_without_fields.len() > 0 { + node_type_json.children = Some(FieldInfoJSON { + multiple: true, + required: false, + types: info.child_types_without_fields.iter().map(child_type_to_node_type).collect(), + }); + } } } @@ -414,6 +468,7 @@ pub(crate) fn generate_node_types_json( kind: variable.name.clone(), named: true, fields: None, + children: None, subtypes: None, }); } else if variable.kind == VariableType::Anonymous { @@ -421,6 +476,7 @@ pub(crate) fn generate_node_types_json( kind: variable.name.clone(), named: false, fields: None, + children: None, subtypes: None, }); } @@ -471,6 +527,7 @@ mod tests { kind: "v1".to_string(), named: true, subtypes: None, + children: None, fields: Some( vec![ ( @@ -507,6 +564,7 @@ mod tests { kind: ";".to_string(), named: false, subtypes: None, + children: None, fields: None } ); @@ -516,6 +574,7 @@ mod tests { kind: "v2".to_string(), named: true, subtypes: None, + children: None, fields: None } ); @@ -565,6 +624,7 @@ mod tests { kind: "_v2".to_string(), named: true, fields: None, + children: None, subtypes: Some(vec![ NodeTypeJSON { kind: "*".to_string(), @@ -587,6 +647,7 @@ mod tests { kind: "v1".to_string(), named: true, subtypes: None, + children: None, fields: Some( vec![( "f1".to_string(), From 0a2b183bd0632920e342b0b6848d876ffe810dc9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 17 Jun 2019 12:26:18 -0700 Subject: [PATCH 2/4] Add a unit test for the children property in node-types --- cli/src/generate/node_types.rs | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/cli/src/generate/node_types.rs b/cli/src/generate/node_types.rs index 60a8f430..56ebba61 100644 --- a/cli/src/generate/node_types.rs +++ b/cli/src/generate/node_types.rs @@ -667,6 +667,85 @@ mod tests { ); } + #[test] + fn test_node_types_for_children_without_fields() { + let node_types = get_node_types(InputGrammar { + name: String::new(), + extra_tokens: Vec::new(), + external_tokens: Vec::new(), + expected_conflicts: Vec::new(), + variables_to_inline: Vec::new(), + word_token: None, + supertype_symbols: vec![], + variables: vec![ + Variable { + name: "v1".to_string(), + kind: VariableType::Named, + rule: Rule::seq(vec![ + Rule::named("v2"), + Rule::field("f1".to_string(), Rule::named("v3")), + Rule::named("v4") + ]), + }, + Variable { + name: "v2".to_string(), + kind: VariableType::Named, + rule: Rule::string("x"), + }, + Variable { + name: "v3".to_string(), + kind: VariableType::Named, + rule: Rule::string("x"), + }, + Variable { + name: "v4".to_string(), + kind: VariableType::Named, + rule: Rule::string("x"), + }, + ], + }); + + assert_eq!( + node_types[0], + NodeInfoJSON { + kind: "v1".to_string(), + named: true, + subtypes: None, + children: Some(FieldInfoJSON { + multiple: true, + required: false, + types: vec![ + NodeTypeJSON { + kind: "v2".to_string(), + named: true, + }, + NodeTypeJSON { + kind: "v4".to_string(), + named: true, + }, + ] + }), + fields: Some( + vec![ + ( + "f1".to_string(), + FieldInfoJSON { + multiple: false, + required: true, + types: vec![NodeTypeJSON { + kind: "v3".to_string(), + named: true, + }] + } + ), + ] + .into_iter() + .collect() + ) + } + ); + } + #[test] fn test_get_variable_info() { let variable_info = get_variable_info( From ee1d4d6b2c5e4e1cd61c33b13ef1aedc0bd9cb54 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 19 Jun 2019 15:30:48 -0700 Subject: [PATCH 3/4] Fix handling of inlined rules in node-types generation --- cli/src/generate/build_tables/item.rs | 4 +- cli/src/generate/grammars.rs | 1 + cli/src/generate/mod.rs | 2 +- cli/src/generate/node_types.rs | 318 ++++++++++++++++---------- 4 files changed, 205 insertions(+), 120 deletions(-) diff --git a/cli/src/generate/build_tables/item.rs b/cli/src/generate/build_tables/item.rs index 60751002..3bea6293 100644 --- a/cli/src/generate/build_tables/item.rs +++ b/cli/src/generate/build_tables/item.rs @@ -272,7 +272,9 @@ impl<'a> ParseItemSet<'a> { } pub fn core(&self) -> ParseItemSetCore<'a> { - ParseItemSetCore { entries: self.entries.iter().map(|e| e.0).collect() } + ParseItemSetCore { + entries: self.entries.iter().map(|e| e.0).collect(), + } } } diff --git a/cli/src/generate/grammars.rs b/cli/src/generate/grammars.rs index bca03c39..df22eaff 100644 --- a/cli/src/generate/grammars.rs +++ b/cli/src/generate/grammars.rs @@ -64,6 +64,7 @@ pub(crate) struct Production { pub dynamic_precedence: i32, } +#[derive(Default)] pub(crate) struct InlinedProductionMap { pub productions: Vec, pub production_map: HashMap<(*const Production, u32), Vec>, diff --git a/cli/src/generate/mod.rs b/cli/src/generate/mod.rs index b779a004..68bebc1f 100644 --- a/cli/src/generate/mod.rs +++ b/cli/src/generate/mod.rs @@ -97,7 +97,7 @@ fn generate_parser_for_grammar_with_opts( let input_grammar = parse_grammar(grammar_json)?; let (syntax_grammar, lexical_grammar, inlines, simple_aliases) = prepare_grammar(&input_grammar)?; - let variable_info = node_types::get_variable_info(&syntax_grammar, &lexical_grammar)?; + let variable_info = node_types::get_variable_info(&syntax_grammar, &lexical_grammar, &inlines)?; let node_types_json = node_types::generate_node_types_json( &syntax_grammar, &lexical_grammar, diff --git a/cli/src/generate/node_types.rs b/cli/src/generate/node_types.rs index 56ebba61..51f902f5 100644 --- a/cli/src/generate/node_types.rs +++ b/cli/src/generate/node_types.rs @@ -1,4 +1,7 @@ -use super::grammars::{LexicalGrammar, SyntaxGrammar, VariableType}; +use super::grammars::{ + InlinedProductionMap, LexicalGrammar, Production, ProductionStep, SyntaxGrammar, + SyntaxVariable, VariableType, +}; use super::rules::{Alias, AliasMap, Symbol, SymbolType}; use crate::error::{Error, Result}; use hashbrown::HashMap; @@ -57,11 +60,13 @@ pub(crate) struct FieldInfoJSON { pub(crate) fn get_variable_info( syntax_grammar: &SyntaxGrammar, lexical_grammar: &LexicalGrammar, + inlines: &InlinedProductionMap, ) -> Result> { let mut result = Vec::new(); // Determine which field names and child node types can appear directly // within each type of node. + let mut steps = Vec::new(); for (i, variable) in syntax_grammar.variables.iter().enumerate() { let mut info = VariableInfo { fields: HashMap::new(), @@ -69,44 +74,42 @@ pub(crate) fn get_variable_info( child_types_without_fields: Vec::new(), has_multi_step_production: false, }; - let is_recursive = variable - .productions - .iter() - .any(|p| p.steps.iter().any(|s| s.symbol == Symbol::non_terminal(i))); - for production in &variable.productions { - if production.steps.len() > 1 { - info.has_multi_step_production = true; + steps.clear(); + if get_all_child_steps(variable, inlines, &mut steps) > 1 { + info.has_multi_step_production = true; + } + + let is_recursive = steps.iter().any(|s| s.symbol == Symbol::non_terminal(i)); + + for step in &steps { + let child_type = if let Some(alias) = &step.alias { + ChildType::Aliased(alias.clone()) + } else { + ChildType::Normal(step.symbol) + }; + + if let Some(field_name) = &step.field_name { + let field_info = info.fields.entry(field_name.clone()).or_insert(FieldInfo { + multiple: false, + required: true, + types: Vec::new(), + }); + field_info.multiple |= is_recursive; + if let Err(i) = field_info.types.binary_search(&child_type) { + field_info.types.insert(i, child_type.clone()); + } + } else if variable_type_for_child_type(&child_type, syntax_grammar, lexical_grammar) + == VariableType::Named + { + if let Err(i) = info.child_types_without_fields.binary_search(&child_type) { + info.child_types_without_fields + .insert(i, child_type.clone()); + } } - for step in &production.steps { - let child_type = if let Some(alias) = &step.alias { - ChildType::Aliased(alias.clone()) - } else { - ChildType::Normal(step.symbol) - }; - - if let Some(field_name) = &step.field_name { - let field_info = info.fields - .entry(field_name.clone()) - .or_insert(FieldInfo { - multiple: false, - required: true, - types: Vec::new(), - }); - field_info.multiple |= is_recursive; - if let Err(i) = field_info.types.binary_search(&child_type) { - field_info.types.insert(i, child_type.clone()); - } - } else if variable_type_for_child_type(&child_type, syntax_grammar, lexical_grammar) == VariableType::Named { - if let Err(i) = info.child_types_without_fields.binary_search(&child_type) { - info.child_types_without_fields.insert(i, child_type.clone()); - } - } - - if let Err(i) = info.child_types.binary_search(&child_type) { - info.child_types.insert(i, child_type.clone()); - } + if let Err(i) = info.child_types.binary_search(&child_type) { + info.child_types.insert(i, child_type.clone()); } } @@ -146,76 +149,80 @@ pub(crate) fn get_variable_info( let mut variable_info = VariableInfo::default(); mem::swap(&mut variable_info, &mut result[i]); - for production in &variable.productions { - for step in &production.steps { - let child_symbol = step.symbol; - if step.alias.is_none() - && child_symbol.kind == SymbolType::NonTerminal - && !syntax_grammar.variables[child_symbol.index] - .kind - .is_visible() - && !syntax_grammar.supertype_symbols.contains(&child_symbol) - { - let child_variable_info = &result[child_symbol.index]; + steps.clear(); + get_all_child_steps(variable, inlines, &mut steps); - // If a hidden child can have multiple children, then this - // node can appear to have multiple children. - if child_variable_info.has_multi_step_production { - variable_info.has_multi_step_production = true; + for step in &steps { + let child_symbol = step.symbol; + if step.alias.is_none() + && child_symbol.kind == SymbolType::NonTerminal + && !syntax_grammar.variables[child_symbol.index] + .kind + .is_visible() + && !syntax_grammar.supertype_symbols.contains(&child_symbol) + { + let child_variable_info = &result[child_symbol.index]; + + // If a hidden child can have multiple children, then this + // node can appear to have multiple children. + if child_variable_info.has_multi_step_production { + variable_info.has_multi_step_production = true; + } + + // Inherit fields from this hidden child + for (field_name, child_field_info) in &child_variable_info.fields { + let field_info = variable_info + .fields + .entry(field_name.clone()) + .or_insert_with(|| { + done = false; + child_field_info.clone() + }); + if child_field_info.multiple && !field_info.multiple { + field_info.multiple = child_field_info.multiple; + done = false; } - - // Inherit fields from this hidden child - for (field_name, child_field_info) in &child_variable_info.fields { - let field_info = variable_info - .fields - .entry(field_name.clone()) - .or_insert_with(|| { - done = false; - child_field_info.clone() - }); - if child_field_info.multiple && !field_info.multiple { - field_info.multiple = child_field_info.multiple; + if !child_field_info.required && field_info.required { + field_info.required = child_field_info.required; + done = false; + } + for child_type in &child_field_info.types { + if let Err(i) = field_info.types.binary_search(&child_type) { + field_info.types.insert(i, child_type.clone()); done = false; } - if !child_field_info.required && field_info.required { - field_info.required = child_field_info.required; - done = false; - } - for child_type in &child_field_info.types { - if let Err(i) = field_info.types.binary_search(&child_type) { - field_info.types.insert(i, child_type.clone()); - done = false; - } - } } + } - // Inherit child types from this hidden child + // Inherit child types from this hidden child + for child_type in &child_variable_info.child_types { + if let Err(i) = variable_info.child_types.binary_search(&child_type) { + variable_info.child_types.insert(i, child_type.clone()); + done = false; + } + } + + // If any field points to this hidden child, inherit child types + // for the field. + if let Some(field_name) = &step.field_name { + let field_info = variable_info.fields.get_mut(field_name).unwrap(); for child_type in &child_variable_info.child_types { - if let Err(i) = variable_info.child_types.binary_search(&child_type) - { - variable_info.child_types.insert(i, child_type.clone()); + if let Err(i) = field_info.types.binary_search(&child_type) { + field_info.types.insert(i, child_type.clone()); done = false; } } - - // If any field points to this hidden child, inherit child types - // for the field. - if let Some(field_name) = &step.field_name { - let field_info = variable_info.fields.get_mut(field_name).unwrap(); - for child_type in &child_variable_info.child_types { - if let Err(i) = field_info.types.binary_search(&child_type) { - field_info.types.insert(i, child_type.clone()); - done = false; - } - } - } else { - // Inherit child types without fields from this hidden child - for child_type in &child_variable_info.child_types_without_fields { - if let Err(i) = variable_info.child_types_without_fields.binary_search(&child_type) - { - variable_info.child_types_without_fields.insert(i, child_type.clone()); - done = false; - } + } else { + // Inherit child types without fields from this hidden child + for child_type in &child_variable_info.child_types_without_fields { + if let Err(i) = variable_info + .child_types_without_fields + .binary_search(&child_type) + { + variable_info + .child_types_without_fields + .insert(i, child_type.clone()); + done = false; } } } @@ -262,19 +269,27 @@ pub(crate) fn get_variable_info( // subtypes with a single supertype. for (_, field_info) in variable_info.fields.iter_mut() { for supertype_symbol in &syntax_grammar.supertype_symbols { - if sorted_vec_replace( + sorted_vec_replace( &mut field_info.types, &result[supertype_symbol.index].child_types, ChildType::Normal(*supertype_symbol), - ) { - break; - } + ); } field_info.types.retain(child_type_is_visible); } - variable_info.child_types_without_fields.retain(child_type_is_visible); + for supertype_symbol in &syntax_grammar.supertype_symbols { + sorted_vec_replace( + &mut variable_info.child_types_without_fields, + &result[supertype_symbol.index].child_types, + ChildType::Normal(*supertype_symbol), + ); + } + + variable_info + .child_types_without_fields + .retain(child_type_is_visible); result[i] = variable_info; } @@ -282,6 +297,57 @@ pub(crate) fn get_variable_info( Ok(result) } +// Summarize information about this variable's possible children by walking +// all of its productions. +fn get_all_child_steps( + variable: &SyntaxVariable, + inlines: &InlinedProductionMap, + output: &mut Vec, +) -> usize { + // For each of the given variable's productions, insert all of the reachable steps + // into the output vector, and return the longest possible production length. + return variable + .productions + .iter() + .map(|p| process_production(inlines, p, 0, output)) + .max() + .unwrap_or(0); + + // For the given production suffix, add all of the remaining steps into the output + // vector and return the longest possible production length. + fn process_production( + inlines: &InlinedProductionMap, + production: &Production, + step_index: usize, + output: &mut Vec, + ) -> usize { + let mut max_length = production.steps.len(); + + // Process each of the remaining steps of the production. + for (i, step) in production.steps.iter().enumerate().skip(step_index) { + // If this step is inlined, then process the corresponding suffixes of + // all of the inlined productions instead. + if let Some(inlined_productions) = inlines.inlined_productions(production, i as u32) { + for inlined_production in inlined_productions { + let length = process_production(inlines, inlined_production, i, output); + if length > max_length { + max_length = length; + } + } + break; + } + + // Otherwise, insert this step into the output vector unless it is already + // present. + if let Err(i) = output.binary_search(step) { + output.insert(i, step.clone()); + } + } + + return max_length; + } +} + fn variable_type_for_child_type( child_type: &ChildType, syntax_grammar: &SyntaxGrammar, @@ -314,6 +380,10 @@ fn sorted_vec_replace(left: &mut Vec, right: &Vec, value: T) -> bool where T: Eq + Ord, { + if left.len() == 0 { + return false; + } + let mut i = 0; for right_elem in right.iter() { while left[i] < *right_elem { @@ -422,7 +492,9 @@ pub(crate) fn generate_node_types_json( subtypes.sort_unstable(); subtypes.dedup(); node_type_json.subtypes = Some(subtypes); - } else if variable.kind.is_visible() { + } else if variable.kind.is_visible() + && !syntax_grammar.variables_to_inline.contains(&symbol) + { let node_type_json = node_types_json .entry(name.clone()) @@ -454,7 +526,11 @@ pub(crate) fn generate_node_types_json( node_type_json.children = Some(FieldInfoJSON { multiple: true, required: false, - types: info.child_types_without_fields.iter().map(child_type_to_node_type).collect(), + types: info + .child_types_without_fields + .iter() + .map(child_type_to_node_type) + .collect(), }); } } @@ -684,7 +760,7 @@ mod tests { rule: Rule::seq(vec![ Rule::named("v2"), Rule::field("f1".to_string(), Rule::named("v3")), - Rule::named("v4") + Rule::named("v4"), ]), }, Variable { @@ -726,19 +802,17 @@ mod tests { ] }), fields: Some( - vec![ - ( - "f1".to_string(), - FieldInfoJSON { - multiple: false, - required: true, - types: vec![NodeTypeJSON { - kind: "v3".to_string(), - named: true, - }] - } - ), - ] + vec![( + "f1".to_string(), + FieldInfoJSON { + multiple: false, + required: true, + types: vec![NodeTypeJSON { + kind: "v3".to_string(), + named: true, + }] + } + ),] .into_iter() .collect() ) @@ -804,6 +878,7 @@ mod tests { vec![], ), &build_lexical_grammar(), + &InlinedProductionMap::default(), ) .unwrap(); @@ -872,6 +947,7 @@ mod tests { vec![], ), &build_lexical_grammar(), + &InlinedProductionMap::default(), ) .unwrap(); @@ -927,6 +1003,7 @@ mod tests { vec![Symbol::non_terminal(1)], ), &build_lexical_grammar(), + &InlinedProductionMap::default(), ) .unwrap(); @@ -948,7 +1025,12 @@ mod tests { fn get_node_types(grammar: InputGrammar) -> Vec { let (syntax_grammar, lexical_grammar, _, simple_aliases) = prepare_grammar(&grammar).unwrap(); - let variable_info = get_variable_info(&syntax_grammar, &lexical_grammar).unwrap(); + let variable_info = get_variable_info( + &syntax_grammar, + &lexical_grammar, + &InlinedProductionMap::default(), + ) + .unwrap(); generate_node_types_json( &syntax_grammar, &lexical_grammar, From 0ad4e147e2c92cc655b09a554893746c9ea285ba Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 19 Jun 2019 15:35:53 -0700 Subject: [PATCH 4/4] Dedup types in children property of node-types --- cli/src/generate/node_types.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cli/src/generate/node_types.rs b/cli/src/generate/node_types.rs index 51f902f5..92b9dd67 100644 --- a/cli/src/generate/node_types.rs +++ b/cli/src/generate/node_types.rs @@ -523,14 +523,17 @@ pub(crate) fn generate_node_types_json( } node_type_json.fields = Some(fields_json); if info.child_types_without_fields.len() > 0 { + let mut children_types = info + .child_types_without_fields + .iter() + .map(child_type_to_node_type) + .collect::>(); + children_types.sort_unstable(); + children_types.dedup(); node_type_json.children = Some(FieldInfoJSON { multiple: true, required: false, - types: info - .child_types_without_fields - .iter() - .map(child_type_to_node_type) - .collect(), + types: children_types, }); } }