1 use super::grammars::{LexicalGrammar, SyntaxGrammar, VariableType};
2 use super::rules::{Alias, AliasMap, Symbol, SymbolType};
3 use anyhow::{anyhow, Result};
4 use serde_derive::Serialize;
5 use std::cmp::Ordering;
6 use std::collections::{BTreeMap, HashMap, HashSet};
7 
8 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
9 pub(crate) enum ChildType {
10     Normal(Symbol),
11     Aliased(Alias),
12 }
13 
14 #[derive(Clone, Debug, Default, PartialEq, Eq)]
15 pub(crate) struct FieldInfo {
16     pub quantity: ChildQuantity,
17     pub types: Vec<ChildType>,
18 }
19 
20 #[derive(Clone, Debug, Default, PartialEq, Eq)]
21 pub(crate) struct VariableInfo {
22     pub fields: HashMap<String, FieldInfo>,
23     pub children: FieldInfo,
24     pub children_without_fields: FieldInfo,
25     pub has_multi_step_production: bool,
26 }
27 
28 #[derive(Debug, Serialize, PartialEq, Eq, Default, PartialOrd, Ord)]
29 pub(crate) struct NodeInfoJSON {
30     #[serde(rename = "type")]
31     kind: String,
32     named: bool,
33     #[serde(skip_serializing_if = "Option::is_none")]
34     fields: Option<BTreeMap<String, FieldInfoJSON>>,
35     #[serde(skip_serializing_if = "Option::is_none")]
36     children: Option<FieldInfoJSON>,
37     #[serde(skip_serializing_if = "Option::is_none")]
38     subtypes: Option<Vec<NodeTypeJSON>>,
39 }
40 
41 #[derive(Clone, Debug, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
42 pub(crate) struct NodeTypeJSON {
43     #[serde(rename = "type")]
44     kind: String,
45     named: bool,
46 }
47 
48 #[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)]
49 pub(crate) struct FieldInfoJSON {
50     multiple: bool,
51     required: bool,
52     types: Vec<NodeTypeJSON>,
53 }
54 
55 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
56 pub struct ChildQuantity {
57     exists: bool,
58     required: bool,
59     multiple: bool,
60 }
61 
62 impl Default for FieldInfoJSON {
default() -> Self63     fn default() -> Self {
64         FieldInfoJSON {
65             multiple: false,
66             required: true,
67             types: Vec::new(),
68         }
69     }
70 }
71 
72 impl Default for ChildQuantity {
default() -> Self73     fn default() -> Self {
74         Self::one()
75     }
76 }
77 
78 impl ChildQuantity {
zero() -> Self79     fn zero() -> Self {
80         ChildQuantity {
81             exists: false,
82             required: false,
83             multiple: false,
84         }
85     }
86 
one() -> Self87     fn one() -> Self {
88         ChildQuantity {
89             exists: true,
90             required: true,
91             multiple: false,
92         }
93     }
94 
append(&mut self, other: ChildQuantity)95     fn append(&mut self, other: ChildQuantity) {
96         if other.exists {
97             if self.exists || other.multiple {
98                 self.multiple = true;
99             }
100             if other.required {
101                 self.required = true;
102             }
103             self.exists = true;
104         }
105     }
106 
union(&mut self, other: ChildQuantity) -> bool107     fn union(&mut self, other: ChildQuantity) -> bool {
108         let mut result = false;
109         if !self.exists && other.exists {
110             result = true;
111             self.exists = true;
112         }
113         if self.required && !other.required {
114             result = true;
115             self.required = false;
116         }
117         if !self.multiple && other.multiple {
118             result = true;
119             self.multiple = true;
120         }
121         result
122     }
123 }
124 
125 /// Compute a summary of the public-facing structure of each variable in the
126 /// grammar. Each variable in the grammar corresponds to a distinct public-facing
127 /// node type.
128 ///
129 /// The information collected about each node type `N` is:
130 /// 1. `child_types` - The types of visible children that can appear within `N`.
131 /// 2. `fields` - The fields that `N` can have. Data regarding each field:
132 ///    * `types` - The types of visible children the field can contain.
133 ///    * `optional` - Do `N` nodes always have this field?
134 ///    * `multiple` - Can `N` nodes have multiple children for this field?
135 /// 3. `children_without_fields` - The *other* named children of `N` that are
136 ///    not associated with fields. Data regarding these children:
137 ///    * `types` - The types of named children with no field.
138 ///    * `optional` - Do `N` nodes always have at least one named child with no field?
139 ///    * `multiple` - Can `N` nodes have multiple named children with no field?
140 ///
141 /// Each summary must account for some indirect factors:
142 /// 1. hidden nodes. When a parent node `N` has a hidden child `C`, the visible
143 ///    children of `C` *appear* to be direct children of `N`.
144 /// 2. aliases. If a parent node type `M` is aliased as some other type `N`,
145 ///    then nodes which *appear* to have type `N` may have internal structure based
146 ///    on `M`.
get_variable_info( syntax_grammar: &SyntaxGrammar, lexical_grammar: &LexicalGrammar, default_aliases: &AliasMap, ) -> Result<Vec<VariableInfo>>147 pub(crate) fn get_variable_info(
148     syntax_grammar: &SyntaxGrammar,
149     lexical_grammar: &LexicalGrammar,
150     default_aliases: &AliasMap,
151 ) -> Result<Vec<VariableInfo>> {
152     let child_type_is_visible = |t: &ChildType| {
153         variable_type_for_child_type(t, syntax_grammar, lexical_grammar) >= VariableType::Anonymous
154     };
155 
156     let child_type_is_named = |t: &ChildType| {
157         variable_type_for_child_type(t, syntax_grammar, lexical_grammar) == VariableType::Named
158     };
159 
160     // Each variable's summary can depend on the summaries of other hidden variables,
161     // and variables can have mutually recursive structure. So we compute the summaries
162     // iteratively, in a loop that terminates only when no more changes are possible.
163     let mut did_change = true;
164     let mut all_initialized = false;
165     let mut result = vec![VariableInfo::default(); syntax_grammar.variables.len()];
166     while did_change {
167         did_change = false;
168 
169         for (i, variable) in syntax_grammar.variables.iter().enumerate() {
170             let mut variable_info = result[i].clone();
171 
172             // Examine each of the variable's productions. The variable's child types can be
173             // immediately combined across all productions, but the child quantities must be
174             // recorded separately for each production.
175             for production in &variable.productions {
176                 let mut production_field_quantities = HashMap::new();
177                 let mut production_children_quantity = ChildQuantity::zero();
178                 let mut production_children_without_fields_quantity = ChildQuantity::zero();
179                 let mut production_has_uninitialized_invisible_children = false;
180 
181                 if production.steps.len() > 1 {
182                     variable_info.has_multi_step_production = true;
183                 }
184 
185                 for step in &production.steps {
186                     let child_symbol = step.symbol;
187                     let child_type = if let Some(alias) = &step.alias {
188                         ChildType::Aliased(alias.clone())
189                     } else if let Some(alias) = default_aliases.get(&step.symbol) {
190                         ChildType::Aliased(alias.clone())
191                     } else {
192                         ChildType::Normal(child_symbol)
193                     };
194 
195                     let child_is_hidden = !child_type_is_visible(&child_type)
196                         && !syntax_grammar.supertype_symbols.contains(&child_symbol);
197 
198                     // Maintain the set of all child types for this variable, and the quantity of
199                     // visible children in this production.
200                     did_change |=
201                         extend_sorted(&mut variable_info.children.types, Some(&child_type));
202                     if !child_is_hidden {
203                         production_children_quantity.append(ChildQuantity::one());
204                     }
205 
206                     // Maintain the set of child types associated with each field, and the quantity
207                     // of children associated with each field in this production.
208                     if let Some(field_name) = &step.field_name {
209                         let field_info = variable_info
210                             .fields
211                             .entry(field_name.clone())
212                             .or_insert(FieldInfo::default());
213                         did_change |= extend_sorted(&mut field_info.types, Some(&child_type));
214 
215                         let production_field_quantity = production_field_quantities
216                             .entry(field_name)
217                             .or_insert(ChildQuantity::zero());
218 
219                         // Inherit the types and quantities of hidden children associated with fields.
220                         if child_is_hidden && child_symbol.is_non_terminal() {
221                             let child_variable_info = &result[child_symbol.index];
222                             did_change |= extend_sorted(
223                                 &mut field_info.types,
224                                 &child_variable_info.children.types,
225                             );
226                             production_field_quantity.append(child_variable_info.children.quantity);
227                         } else {
228                             production_field_quantity.append(ChildQuantity::one());
229                         }
230                     }
231                     // Maintain the set of named children without fields within this variable.
232                     else if child_type_is_named(&child_type) {
233                         production_children_without_fields_quantity.append(ChildQuantity::one());
234                         did_change |= extend_sorted(
235                             &mut variable_info.children_without_fields.types,
236                             Some(&child_type),
237                         );
238                     }
239 
240                     // Inherit all child information from hidden children.
241                     if child_is_hidden && child_symbol.is_non_terminal() {
242                         let child_variable_info = &result[child_symbol.index];
243 
244                         // If a hidden child can have multiple children, then its parent node can
245                         // appear to have multiple children.
246                         if child_variable_info.has_multi_step_production {
247                             variable_info.has_multi_step_production = true;
248                         }
249 
250                         // If a hidden child has fields, then the parent node can appear to have
251                         // those same fields.
252                         for (field_name, child_field_info) in &child_variable_info.fields {
253                             production_field_quantities
254                                 .entry(field_name)
255                                 .or_insert(ChildQuantity::zero())
256                                 .append(child_field_info.quantity);
257                             did_change |= extend_sorted(
258                                 &mut variable_info
259                                     .fields
260                                     .entry(field_name.clone())
261                                     .or_insert(FieldInfo::default())
262                                     .types,
263                                 &child_field_info.types,
264                             );
265                         }
266 
267                         // If a hidden child has children, then the parent node can appear to have
268                         // those same children.
269                         production_children_quantity.append(child_variable_info.children.quantity);
270                         did_change |= extend_sorted(
271                             &mut variable_info.children.types,
272                             &child_variable_info.children.types,
273                         );
274 
275                         // If a hidden child can have named children without fields, then the parent
276                         // node can appear to have those same children.
277                         if step.field_name.is_none() {
278                             let grandchildren_info = &child_variable_info.children_without_fields;
279                             if !grandchildren_info.types.is_empty() {
280                                 production_children_without_fields_quantity
281                                     .append(child_variable_info.children_without_fields.quantity);
282                                 did_change |= extend_sorted(
283                                     &mut variable_info.children_without_fields.types,
284                                     &child_variable_info.children_without_fields.types,
285                                 );
286                             }
287                         }
288                     }
289 
290                     // Note whether or not this production contains children whose summaries
291                     // have not yet been computed.
292                     if child_symbol.index >= i && !all_initialized {
293                         production_has_uninitialized_invisible_children = true;
294                     }
295                 }
296 
297                 // If this production's children all have had their summaries initialized,
298                 // then expand the quantity information with all of the possibilities introduced
299                 // by this production.
300                 if !production_has_uninitialized_invisible_children {
301                     did_change |= variable_info
302                         .children
303                         .quantity
304                         .union(production_children_quantity);
305 
306                     did_change |= variable_info
307                         .children_without_fields
308                         .quantity
309                         .union(production_children_without_fields_quantity);
310 
311                     for (field_name, info) in variable_info.fields.iter_mut() {
312                         did_change |= info.quantity.union(
313                             production_field_quantities
314                                 .get(field_name)
315                                 .cloned()
316                                 .unwrap_or(ChildQuantity::zero()),
317                         );
318                     }
319                 }
320             }
321 
322             result[i] = variable_info;
323         }
324 
325         all_initialized = true;
326     }
327 
328     for supertype_symbol in &syntax_grammar.supertype_symbols {
329         if result[supertype_symbol.index].has_multi_step_production {
330             let variable = &syntax_grammar.variables[supertype_symbol.index];
331             return Err(anyhow!(
332                 concat!(
333                     "Grammar error: Supertype symbols must always ",
334                     "have a single visible child, but `{}` can have multiple"
335                 ),
336                 variable.name
337             ));
338         }
339     }
340 
341     // Update all of the node type lists to eliminate hidden nodes.
342     for supertype_symbol in &syntax_grammar.supertype_symbols {
343         result[supertype_symbol.index]
344             .children
345             .types
346             .retain(child_type_is_visible);
347     }
348     for variable_info in result.iter_mut() {
349         for (_, field_info) in variable_info.fields.iter_mut() {
350             field_info.types.retain(child_type_is_visible);
351         }
352         variable_info.fields.retain(|_, v| !v.types.is_empty());
353         variable_info
354             .children_without_fields
355             .types
356             .retain(child_type_is_visible);
357     }
358 
359     Ok(result)
360 }
361 
generate_node_types_json( syntax_grammar: &SyntaxGrammar, lexical_grammar: &LexicalGrammar, default_aliases: &AliasMap, variable_info: &Vec<VariableInfo>, ) -> Vec<NodeInfoJSON>362 pub(crate) fn generate_node_types_json(
363     syntax_grammar: &SyntaxGrammar,
364     lexical_grammar: &LexicalGrammar,
365     default_aliases: &AliasMap,
366     variable_info: &Vec<VariableInfo>,
367 ) -> Vec<NodeInfoJSON> {
368     let mut node_types_json = BTreeMap::new();
369 
370     let child_type_to_node_type = |child_type: &ChildType| match child_type {
371         ChildType::Aliased(alias) => NodeTypeJSON {
372             kind: alias.value.clone(),
373             named: alias.is_named,
374         },
375         ChildType::Normal(symbol) => {
376             if let Some(alias) = default_aliases.get(&symbol) {
377                 NodeTypeJSON {
378                     kind: alias.value.clone(),
379                     named: alias.is_named,
380                 }
381             } else {
382                 match symbol.kind {
383                     SymbolType::NonTerminal => {
384                         let variable = &syntax_grammar.variables[symbol.index];
385                         NodeTypeJSON {
386                             kind: variable.name.clone(),
387                             named: variable.kind != VariableType::Anonymous,
388                         }
389                     }
390                     SymbolType::Terminal => {
391                         let variable = &lexical_grammar.variables[symbol.index];
392                         NodeTypeJSON {
393                             kind: variable.name.clone(),
394                             named: variable.kind != VariableType::Anonymous,
395                         }
396                     }
397                     SymbolType::External => {
398                         let variable = &syntax_grammar.external_tokens[symbol.index];
399                         NodeTypeJSON {
400                             kind: variable.name.clone(),
401                             named: variable.kind != VariableType::Anonymous,
402                         }
403                     }
404                     _ => panic!("Unexpected symbol type"),
405                 }
406             }
407         }
408     };
409 
410     let populate_field_info_json = |json: &mut FieldInfoJSON, info: &FieldInfo| {
411         if info.types.len() > 0 {
412             json.multiple |= info.quantity.multiple;
413             json.required &= info.quantity.required;
414             json.types
415                 .extend(info.types.iter().map(child_type_to_node_type));
416             json.types.sort_unstable();
417             json.types.dedup();
418         } else {
419             json.required = false;
420         }
421     };
422 
423     let mut aliases_by_symbol = HashMap::new();
424     for (symbol, alias) in default_aliases {
425         aliases_by_symbol.insert(*symbol, {
426             let mut aliases = HashSet::new();
427             aliases.insert(Some(alias.clone()));
428             aliases
429         });
430     }
431     for extra_symbol in &syntax_grammar.extra_symbols {
432         if !default_aliases.contains_key(extra_symbol) {
433             aliases_by_symbol
434                 .entry(*extra_symbol)
435                 .or_insert(HashSet::new())
436                 .insert(None);
437         }
438     }
439     for variable in &syntax_grammar.variables {
440         for production in &variable.productions {
441             for step in &production.steps {
442                 aliases_by_symbol
443                     .entry(step.symbol)
444                     .or_insert(HashSet::new())
445                     .insert(
446                         step.alias
447                             .as_ref()
448                             .or_else(|| default_aliases.get(&step.symbol))
449                             .cloned(),
450                     );
451             }
452         }
453     }
454     aliases_by_symbol.insert(Symbol::non_terminal(0), [None].iter().cloned().collect());
455 
456     let mut subtype_map = Vec::new();
457     for (i, info) in variable_info.iter().enumerate() {
458         let symbol = Symbol::non_terminal(i);
459         let variable = &syntax_grammar.variables[i];
460         if syntax_grammar.supertype_symbols.contains(&symbol) {
461             let node_type_json =
462                 node_types_json
463                     .entry(variable.name.clone())
464                     .or_insert_with(|| NodeInfoJSON {
465                         kind: variable.name.clone(),
466                         named: true,
467                         fields: None,
468                         children: None,
469                         subtypes: None,
470                     });
471             let mut subtypes = info
472                 .children
473                 .types
474                 .iter()
475                 .map(child_type_to_node_type)
476                 .collect::<Vec<_>>();
477             subtypes.sort_unstable();
478             subtypes.dedup();
479             let supertype = NodeTypeJSON {
480                 kind: node_type_json.kind.clone(),
481                 named: true,
482             };
483             subtype_map.push((supertype, subtypes.clone()));
484             node_type_json.subtypes = Some(subtypes);
485         } else if !syntax_grammar.variables_to_inline.contains(&symbol) {
486             // If a rule is aliased under multiple names, then its information
487             // contributes to multiple entries in the final JSON.
488             for alias in aliases_by_symbol
489                 .get(&Symbol::non_terminal(i))
490                 .unwrap_or(&HashSet::new())
491             {
492                 let kind;
493                 let is_named;
494                 if let Some(alias) = alias {
495                     kind = &alias.value;
496                     is_named = alias.is_named;
497                 } else if variable.kind.is_visible() {
498                     kind = &variable.name;
499                     is_named = variable.kind == VariableType::Named;
500                 } else {
501                     continue;
502                 }
503 
504                 // There may already be an entry with this name, because multiple
505                 // rules may be aliased with the same name.
506                 let mut node_type_existed = true;
507                 let node_type_json = node_types_json.entry(kind.clone()).or_insert_with(|| {
508                     node_type_existed = false;
509                     NodeInfoJSON {
510                         kind: kind.clone(),
511                         named: is_named,
512                         fields: Some(BTreeMap::new()),
513                         children: None,
514                         subtypes: None,
515                     }
516                 });
517 
518                 let fields_json = node_type_json.fields.as_mut().unwrap();
519                 for (new_field, field_info) in info.fields.iter() {
520                     let field_json = fields_json.entry(new_field.clone()).or_insert_with(|| {
521                         // If another rule is aliased with the same name, and does *not* have this field,
522                         // then this field cannot be required.
523                         let mut field_json = FieldInfoJSON::default();
524                         if node_type_existed {
525                             field_json.required = false;
526                         }
527                         field_json
528                     });
529                     populate_field_info_json(field_json, field_info);
530                 }
531 
532                 // If another rule is aliased with the same name, any fields that aren't present in this
533                 // cannot be required.
534                 for (existing_field, field_json) in fields_json.iter_mut() {
535                     if !info.fields.contains_key(existing_field) {
536                         field_json.required = false;
537                     }
538                 }
539 
540                 populate_field_info_json(
541                     node_type_json
542                         .children
543                         .get_or_insert(FieldInfoJSON::default()),
544                     &info.children_without_fields,
545                 );
546             }
547         }
548     }
549 
550     // Sort the subtype map so that subtypes are listed before their supertypes.
551     subtype_map.sort_by(|a, b| {
552         if b.1.contains(&a.0) {
553             Ordering::Less
554         } else if a.1.contains(&b.0) {
555             Ordering::Greater
556         } else {
557             Ordering::Equal
558         }
559     });
560 
561     for (_, node_type_json) in node_types_json.iter_mut() {
562         if node_type_json
563             .children
564             .as_ref()
565             .map_or(false, |c| c.types.is_empty())
566         {
567             node_type_json.children = None;
568         }
569 
570         if let Some(children) = &mut node_type_json.children {
571             process_supertypes(children, &subtype_map);
572         }
573         if let Some(fields) = &mut node_type_json.fields {
574             for (_, field_info) in fields.iter_mut() {
575                 process_supertypes(field_info, &subtype_map);
576             }
577         }
578     }
579 
580     let mut anonymous_node_types = Vec::new();
581 
582     let empty = HashSet::new();
583     let regular_tokens = lexical_grammar
584         .variables
585         .iter()
586         .enumerate()
587         .flat_map(|(i, variable)| {
588             aliases_by_symbol
589                 .get(&Symbol::terminal(i))
590                 .unwrap_or(&empty)
591                 .iter()
592                 .map(move |alias| {
593                     if let Some(alias) = alias {
594                         (&alias.value, alias.kind())
595                     } else {
596                         (&variable.name, variable.kind)
597                     }
598                 })
599         });
600     let external_tokens =
601         syntax_grammar
602             .external_tokens
603             .iter()
604             .enumerate()
605             .flat_map(|(i, token)| {
606                 aliases_by_symbol
607                     .get(&Symbol::external(i))
608                     .unwrap_or(&empty)
609                     .iter()
610                     .map(move |alias| {
611                         if let Some(alias) = alias {
612                             (&alias.value, alias.kind())
613                         } else {
614                             (&token.name, token.kind)
615                         }
616                     })
617             });
618 
619     for (name, kind) in regular_tokens.chain(external_tokens) {
620         match kind {
621             VariableType::Named => {
622                 let node_type_json = node_types_json.entry(name.clone()).or_insert(NodeInfoJSON {
623                     kind: name.clone(),
624                     named: true,
625                     fields: None,
626                     children: None,
627                     subtypes: None,
628                 });
629                 if let Some(children) = &mut node_type_json.children {
630                     children.required = false;
631                 }
632                 if let Some(fields) = &mut node_type_json.fields {
633                     for (_, field) in fields.iter_mut() {
634                         field.required = false;
635                     }
636                 }
637             }
638             VariableType::Anonymous => anonymous_node_types.push(NodeInfoJSON {
639                 kind: name.clone(),
640                 named: false,
641                 fields: None,
642                 children: None,
643                 subtypes: None,
644             }),
645             _ => {}
646         }
647     }
648 
649     let mut result = node_types_json.into_iter().map(|e| e.1).collect::<Vec<_>>();
650     result.extend(anonymous_node_types.into_iter());
651     result.sort_unstable_by(|a, b| {
652         b.subtypes
653             .is_some()
654             .cmp(&a.subtypes.is_some())
655             .then_with(|| {
656                 let a_is_leaf = a.children.is_none() && a.fields.is_none();
657                 let b_is_leaf = b.children.is_none() && b.fields.is_none();
658                 a_is_leaf.cmp(&b_is_leaf)
659             })
660             .then_with(|| a.kind.cmp(&b.kind))
661     });
662     result.dedup();
663     result
664 }
665 
process_supertypes( info: &mut FieldInfoJSON, subtype_map: &Vec<(NodeTypeJSON, Vec<NodeTypeJSON>)>, )666 fn process_supertypes(
667     info: &mut FieldInfoJSON,
668     subtype_map: &Vec<(NodeTypeJSON, Vec<NodeTypeJSON>)>,
669 ) {
670     for (supertype, subtypes) in subtype_map {
671         if info.types.contains(supertype) {
672             info.types.retain(|t| !subtypes.contains(t));
673         }
674     }
675 }
676 
variable_type_for_child_type( child_type: &ChildType, syntax_grammar: &SyntaxGrammar, lexical_grammar: &LexicalGrammar, ) -> VariableType677 fn variable_type_for_child_type(
678     child_type: &ChildType,
679     syntax_grammar: &SyntaxGrammar,
680     lexical_grammar: &LexicalGrammar,
681 ) -> VariableType {
682     match child_type {
683         ChildType::Aliased(alias) => alias.kind(),
684         ChildType::Normal(symbol) => {
685             if syntax_grammar.supertype_symbols.contains(&symbol) {
686                 VariableType::Named
687             } else if syntax_grammar.variables_to_inline.contains(&symbol) {
688                 VariableType::Hidden
689             } else {
690                 match symbol.kind {
691                     SymbolType::NonTerminal => syntax_grammar.variables[symbol.index].kind,
692                     SymbolType::Terminal => lexical_grammar.variables[symbol.index].kind,
693                     SymbolType::External => syntax_grammar.external_tokens[symbol.index].kind,
694                     _ => VariableType::Hidden,
695                 }
696             }
697         }
698     }
699 }
700 
extend_sorted<'a, T>(vec: &mut Vec<T>, values: impl IntoIterator<Item = &'a T>) -> bool where T: Clone + Eq + Ord, T: 'a,701 fn extend_sorted<'a, T>(vec: &mut Vec<T>, values: impl IntoIterator<Item = &'a T>) -> bool
702 where
703     T: Clone + Eq + Ord,
704     T: 'a,
705 {
706     values.into_iter().any(|value| {
707         if let Err(i) = vec.binary_search(&value) {
708             vec.insert(i, value.clone());
709             true
710         } else {
711             false
712         }
713     })
714 }
715 
716 #[cfg(test)]
717 mod tests {
718     use super::*;
719     use crate::generate::grammars::{
720         InputGrammar, LexicalVariable, Production, ProductionStep, SyntaxVariable, Variable,
721     };
722     use crate::generate::prepare_grammar::prepare_grammar;
723     use crate::generate::rules::Rule;
724 
725     #[test]
test_node_types_simple()726     fn test_node_types_simple() {
727         let node_types = get_node_types(InputGrammar {
728             name: String::new(),
729             word_token: None,
730             extra_symbols: vec![],
731             external_tokens: vec![],
732             supertype_symbols: vec![],
733             expected_conflicts: vec![],
734             variables_to_inline: vec![],
735             precedence_orderings: vec![],
736             variables: vec![
737                 Variable {
738                     name: "v1".to_string(),
739                     kind: VariableType::Named,
740                     rule: Rule::seq(vec![
741                         Rule::field("f1".to_string(), Rule::named("v2")),
742                         Rule::field("f2".to_string(), Rule::string(";")),
743                     ]),
744                 },
745                 Variable {
746                     name: "v2".to_string(),
747                     kind: VariableType::Named,
748                     rule: Rule::string("x"),
749                 },
750                 // This rule is not reachable from the start symbol
751                 // so it won't be present in the node_types
752                 Variable {
753                     name: "v3".to_string(),
754                     kind: VariableType::Named,
755                     rule: Rule::string("y"),
756                 },
757             ],
758         });
759 
760         assert_eq!(node_types.len(), 3);
761 
762         assert_eq!(
763             node_types[0],
764             NodeInfoJSON {
765                 kind: "v1".to_string(),
766                 named: true,
767                 subtypes: None,
768                 children: None,
769                 fields: Some(
770                     vec![
771                         (
772                             "f1".to_string(),
773                             FieldInfoJSON {
774                                 multiple: false,
775                                 required: true,
776                                 types: vec![NodeTypeJSON {
777                                     kind: "v2".to_string(),
778                                     named: true,
779                                 }]
780                             }
781                         ),
782                         (
783                             "f2".to_string(),
784                             FieldInfoJSON {
785                                 multiple: false,
786                                 required: true,
787                                 types: vec![NodeTypeJSON {
788                                     kind: ";".to_string(),
789                                     named: false,
790                                 }]
791                             }
792                         ),
793                     ]
794                     .into_iter()
795                     .collect()
796                 )
797             }
798         );
799         assert_eq!(
800             node_types[1],
801             NodeInfoJSON {
802                 kind: ";".to_string(),
803                 named: false,
804                 subtypes: None,
805                 children: None,
806                 fields: None
807             }
808         );
809         assert_eq!(
810             node_types[2],
811             NodeInfoJSON {
812                 kind: "v2".to_string(),
813                 named: true,
814                 subtypes: None,
815                 children: None,
816                 fields: None
817             }
818         );
819     }
820 
821     #[test]
test_node_types_simple_extras()822     fn test_node_types_simple_extras() {
823         let node_types = get_node_types(InputGrammar {
824             name: String::new(),
825             extra_symbols: vec![Rule::named("v3")],
826             word_token: None,
827             external_tokens: vec![],
828             supertype_symbols: vec![],
829             expected_conflicts: vec![],
830             variables_to_inline: vec![],
831             precedence_orderings: vec![],
832             variables: vec![
833                 Variable {
834                     name: "v1".to_string(),
835                     kind: VariableType::Named,
836                     rule: Rule::seq(vec![
837                         Rule::field("f1".to_string(), Rule::named("v2")),
838                         Rule::field("f2".to_string(), Rule::string(";")),
839                     ]),
840                 },
841                 Variable {
842                     name: "v2".to_string(),
843                     kind: VariableType::Named,
844                     rule: Rule::string("x"),
845                 },
846                 // This rule is not reachable from the start symbol, but
847                 // it is reachable from the 'extra_symbols' so it
848                 // should be present in the node_types
849                 Variable {
850                     name: "v3".to_string(),
851                     kind: VariableType::Named,
852                     rule: Rule::string("y"),
853                 },
854             ],
855         });
856 
857         assert_eq!(node_types.len(), 4);
858 
859         assert_eq!(
860             node_types[0],
861             NodeInfoJSON {
862                 kind: "v1".to_string(),
863                 named: true,
864                 subtypes: None,
865                 children: None,
866                 fields: Some(
867                     vec![
868                         (
869                             "f1".to_string(),
870                             FieldInfoJSON {
871                                 multiple: false,
872                                 required: true,
873                                 types: vec![NodeTypeJSON {
874                                     kind: "v2".to_string(),
875                                     named: true,
876                                 }]
877                             }
878                         ),
879                         (
880                             "f2".to_string(),
881                             FieldInfoJSON {
882                                 multiple: false,
883                                 required: true,
884                                 types: vec![NodeTypeJSON {
885                                     kind: ";".to_string(),
886                                     named: false,
887                                 }]
888                             }
889                         ),
890                     ]
891                     .into_iter()
892                     .collect()
893                 )
894             }
895         );
896         assert_eq!(
897             node_types[1],
898             NodeInfoJSON {
899                 kind: ";".to_string(),
900                 named: false,
901                 subtypes: None,
902                 children: None,
903                 fields: None
904             }
905         );
906         assert_eq!(
907             node_types[2],
908             NodeInfoJSON {
909                 kind: "v2".to_string(),
910                 named: true,
911                 subtypes: None,
912                 children: None,
913                 fields: None
914             }
915         );
916         assert_eq!(
917             node_types[3],
918             NodeInfoJSON {
919                 kind: "v3".to_string(),
920                 named: true,
921                 subtypes: None,
922                 children: None,
923                 fields: None
924             }
925         );
926     }
927 
928     #[test]
test_node_types_with_supertypes()929     fn test_node_types_with_supertypes() {
930         let node_types = get_node_types(InputGrammar {
931             name: String::new(),
932             word_token: None,
933             extra_symbols: vec![],
934             external_tokens: vec![],
935             expected_conflicts: vec![],
936             variables_to_inline: vec![],
937             precedence_orderings: vec![],
938             supertype_symbols: vec!["_v2".to_string()],
939             variables: vec![
940                 Variable {
941                     name: "v1".to_string(),
942                     kind: VariableType::Named,
943                     rule: Rule::field("f1".to_string(), Rule::named("_v2")),
944                 },
945                 Variable {
946                     name: "_v2".to_string(),
947                     kind: VariableType::Hidden,
948                     rule: Rule::choice(vec![
949                         Rule::named("v3"),
950                         Rule::named("v4"),
951                         Rule::string("*"),
952                     ]),
953                 },
954                 Variable {
955                     name: "v3".to_string(),
956                     kind: VariableType::Named,
957                     rule: Rule::string("x"),
958                 },
959                 Variable {
960                     name: "v4".to_string(),
961                     kind: VariableType::Named,
962                     rule: Rule::string("y"),
963                 },
964             ],
965         });
966 
967         assert_eq!(
968             node_types[0],
969             NodeInfoJSON {
970                 kind: "_v2".to_string(),
971                 named: true,
972                 fields: None,
973                 children: None,
974                 subtypes: Some(vec![
975                     NodeTypeJSON {
976                         kind: "*".to_string(),
977                         named: false,
978                     },
979                     NodeTypeJSON {
980                         kind: "v3".to_string(),
981                         named: true,
982                     },
983                     NodeTypeJSON {
984                         kind: "v4".to_string(),
985                         named: true,
986                     },
987                 ]),
988             }
989         );
990         assert_eq!(
991             node_types[1],
992             NodeInfoJSON {
993                 kind: "v1".to_string(),
994                 named: true,
995                 subtypes: None,
996                 children: None,
997                 fields: Some(
998                     vec![(
999                         "f1".to_string(),
1000                         FieldInfoJSON {
1001                             multiple: false,
1002                             required: true,
1003                             types: vec![NodeTypeJSON {
1004                                 kind: "_v2".to_string(),
1005                                 named: true,
1006                             }]
1007                         }
1008                     ),]
1009                     .into_iter()
1010                     .collect()
1011                 )
1012             }
1013         );
1014     }
1015 
1016     #[test]
test_node_types_for_children_without_fields()1017     fn test_node_types_for_children_without_fields() {
1018         let node_types = get_node_types(InputGrammar {
1019             name: String::new(),
1020             word_token: None,
1021             extra_symbols: vec![],
1022             external_tokens: vec![],
1023             supertype_symbols: vec![],
1024             expected_conflicts: vec![],
1025             variables_to_inline: vec![],
1026             precedence_orderings: vec![],
1027             variables: vec![
1028                 Variable {
1029                     name: "v1".to_string(),
1030                     kind: VariableType::Named,
1031                     rule: Rule::seq(vec![
1032                         Rule::named("v2"),
1033                         Rule::field("f1".to_string(), Rule::named("v3")),
1034                         Rule::named("v4"),
1035                     ]),
1036                 },
1037                 Variable {
1038                     name: "v2".to_string(),
1039                     kind: VariableType::Named,
1040                     rule: Rule::seq(vec![
1041                         Rule::string("{"),
1042                         Rule::choice(vec![Rule::named("v3"), Rule::Blank]),
1043                         Rule::string("}"),
1044                     ]),
1045                 },
1046                 Variable {
1047                     name: "v3".to_string(),
1048                     kind: VariableType::Named,
1049                     rule: Rule::string("x"),
1050                 },
1051                 Variable {
1052                     name: "v4".to_string(),
1053                     kind: VariableType::Named,
1054                     rule: Rule::string("y"),
1055                 },
1056             ],
1057         });
1058 
1059         assert_eq!(
1060             node_types[0],
1061             NodeInfoJSON {
1062                 kind: "v1".to_string(),
1063                 named: true,
1064                 subtypes: None,
1065                 children: Some(FieldInfoJSON {
1066                     multiple: true,
1067                     required: true,
1068                     types: vec![
1069                         NodeTypeJSON {
1070                             kind: "v2".to_string(),
1071                             named: true,
1072                         },
1073                         NodeTypeJSON {
1074                             kind: "v4".to_string(),
1075                             named: true,
1076                         },
1077                     ]
1078                 }),
1079                 fields: Some(
1080                     vec![(
1081                         "f1".to_string(),
1082                         FieldInfoJSON {
1083                             multiple: false,
1084                             required: true,
1085                             types: vec![NodeTypeJSON {
1086                                 kind: "v3".to_string(),
1087                                 named: true,
1088                             }]
1089                         }
1090                     ),]
1091                     .into_iter()
1092                     .collect()
1093                 )
1094             }
1095         );
1096         assert_eq!(
1097             node_types[1],
1098             NodeInfoJSON {
1099                 kind: "v2".to_string(),
1100                 named: true,
1101                 subtypes: None,
1102                 children: Some(FieldInfoJSON {
1103                     multiple: false,
1104                     required: false,
1105                     types: vec![NodeTypeJSON {
1106                         kind: "v3".to_string(),
1107                         named: true,
1108                     },]
1109                 }),
1110                 fields: Some(BTreeMap::new()),
1111             }
1112         );
1113     }
1114 
1115     #[test]
test_node_types_with_inlined_rules()1116     fn test_node_types_with_inlined_rules() {
1117         let node_types = get_node_types(InputGrammar {
1118             name: String::new(),
1119             word_token: None,
1120             extra_symbols: vec![],
1121             external_tokens: vec![],
1122             supertype_symbols: vec![],
1123             expected_conflicts: vec![],
1124             precedence_orderings: vec![],
1125             variables_to_inline: vec!["v2".to_string()],
1126             variables: vec![
1127                 Variable {
1128                     name: "v1".to_string(),
1129                     kind: VariableType::Named,
1130                     rule: Rule::seq(vec![Rule::named("v2"), Rule::named("v3")]),
1131                 },
1132                 // v2 should not appear in the node types, since it is inlined
1133                 Variable {
1134                     name: "v2".to_string(),
1135                     kind: VariableType::Named,
1136                     rule: Rule::alias(Rule::string("a"), "x".to_string(), true),
1137                 },
1138                 Variable {
1139                     name: "v3".to_string(),
1140                     kind: VariableType::Named,
1141                     rule: Rule::string("b"),
1142                 },
1143             ],
1144         });
1145 
1146         assert_eq!(
1147             node_types[0],
1148             NodeInfoJSON {
1149                 kind: "v1".to_string(),
1150                 named: true,
1151                 subtypes: None,
1152                 children: Some(FieldInfoJSON {
1153                     multiple: true,
1154                     required: true,
1155                     types: vec![
1156                         NodeTypeJSON {
1157                             kind: "v3".to_string(),
1158                             named: true,
1159                         },
1160                         NodeTypeJSON {
1161                             kind: "x".to_string(),
1162                             named: true,
1163                         },
1164                     ]
1165                 }),
1166                 fields: Some(BTreeMap::new()),
1167             }
1168         );
1169     }
1170 
1171     #[test]
test_node_types_for_aliased_nodes()1172     fn test_node_types_for_aliased_nodes() {
1173         let node_types = get_node_types(InputGrammar {
1174             name: String::new(),
1175             word_token: None,
1176             extra_symbols: vec![],
1177             external_tokens: vec![],
1178             supertype_symbols: vec![],
1179             expected_conflicts: vec![],
1180             variables_to_inline: vec![],
1181             precedence_orderings: vec![],
1182             variables: vec![
1183                 Variable {
1184                     name: "thing".to_string(),
1185                     kind: VariableType::Named,
1186                     rule: Rule::choice(vec![Rule::named("type"), Rule::named("expression")]),
1187                 },
1188                 Variable {
1189                     name: "type".to_string(),
1190                     kind: VariableType::Named,
1191                     rule: Rule::choice(vec![
1192                         Rule::alias(
1193                             Rule::named("identifier"),
1194                             "type_identifier".to_string(),
1195                             true,
1196                         ),
1197                         Rule::string("void"),
1198                     ]),
1199                 },
1200                 Variable {
1201                     name: "expression".to_string(),
1202                     kind: VariableType::Named,
1203                     rule: Rule::choice(vec![
1204                         Rule::named("identifier"),
1205                         Rule::alias(
1206                             Rule::named("foo_identifier"),
1207                             "identifier".to_string(),
1208                             true,
1209                         ),
1210                     ]),
1211                 },
1212                 Variable {
1213                     name: "identifier".to_string(),
1214                     kind: VariableType::Named,
1215                     rule: Rule::pattern("\\w+"),
1216                 },
1217                 Variable {
1218                     name: "foo_identifier".to_string(),
1219                     kind: VariableType::Named,
1220                     rule: Rule::pattern("[\\w-]+"),
1221                 },
1222             ],
1223         });
1224 
1225         assert_eq!(node_types.iter().find(|t| t.kind == "foo_identifier"), None);
1226         assert_eq!(
1227             node_types.iter().find(|t| t.kind == "identifier"),
1228             Some(&NodeInfoJSON {
1229                 kind: "identifier".to_string(),
1230                 named: true,
1231                 subtypes: None,
1232                 children: None,
1233                 fields: None,
1234             })
1235         );
1236         assert_eq!(
1237             node_types.iter().find(|t| t.kind == "type_identifier"),
1238             Some(&NodeInfoJSON {
1239                 kind: "type_identifier".to_string(),
1240                 named: true,
1241                 subtypes: None,
1242                 children: None,
1243                 fields: None,
1244             })
1245         );
1246     }
1247 
1248     #[test]
test_node_types_with_multiple_valued_fields()1249     fn test_node_types_with_multiple_valued_fields() {
1250         let node_types = get_node_types(InputGrammar {
1251             name: String::new(),
1252             word_token: None,
1253             extra_symbols: vec![],
1254             external_tokens: vec![],
1255             supertype_symbols: vec![],
1256             expected_conflicts: vec![],
1257             variables_to_inline: vec![],
1258             precedence_orderings: vec![],
1259             variables: vec![
1260                 Variable {
1261                     name: "a".to_string(),
1262                     kind: VariableType::Named,
1263                     rule: Rule::seq(vec![
1264                         Rule::choice(vec![
1265                             Rule::Blank,
1266                             Rule::repeat(Rule::field("f1".to_string(), Rule::named("b"))),
1267                         ]),
1268                         Rule::repeat(Rule::named("c")),
1269                     ]),
1270                 },
1271                 Variable {
1272                     name: "b".to_string(),
1273                     kind: VariableType::Named,
1274                     rule: Rule::string("b"),
1275                 },
1276                 Variable {
1277                     name: "c".to_string(),
1278                     kind: VariableType::Named,
1279                     rule: Rule::string("c"),
1280                 },
1281             ],
1282         });
1283 
1284         assert_eq!(
1285             node_types[0],
1286             NodeInfoJSON {
1287                 kind: "a".to_string(),
1288                 named: true,
1289                 subtypes: None,
1290                 children: Some(FieldInfoJSON {
1291                     multiple: true,
1292                     required: true,
1293                     types: vec![NodeTypeJSON {
1294                         kind: "c".to_string(),
1295                         named: true,
1296                     },]
1297                 }),
1298                 fields: Some(
1299                     vec![(
1300                         "f1".to_string(),
1301                         FieldInfoJSON {
1302                             multiple: true,
1303                             required: false,
1304                             types: vec![NodeTypeJSON {
1305                                 kind: "b".to_string(),
1306                                 named: true,
1307                             }]
1308                         }
1309                     )]
1310                     .into_iter()
1311                     .collect()
1312                 ),
1313             }
1314         );
1315     }
1316 
1317     #[test]
test_node_types_with_fields_on_hidden_tokens()1318     fn test_node_types_with_fields_on_hidden_tokens() {
1319         let node_types = get_node_types(InputGrammar {
1320             name: String::new(),
1321             word_token: None,
1322             extra_symbols: vec![],
1323             external_tokens: vec![],
1324             supertype_symbols: vec![],
1325             expected_conflicts: vec![],
1326             variables_to_inline: vec![],
1327             precedence_orderings: vec![],
1328             variables: vec![Variable {
1329                 name: "script".to_string(),
1330                 kind: VariableType::Named,
1331                 rule: Rule::seq(vec![
1332                     Rule::field("a".to_string(), Rule::pattern("hi")),
1333                     Rule::field("b".to_string(), Rule::pattern("bye")),
1334                 ]),
1335             }],
1336         });
1337 
1338         assert_eq!(
1339             node_types,
1340             [NodeInfoJSON {
1341                 kind: "script".to_string(),
1342                 named: true,
1343                 fields: Some(BTreeMap::new()),
1344                 children: None,
1345                 subtypes: None
1346             }]
1347         );
1348     }
1349 
1350     #[test]
test_node_types_with_multiple_rules_same_alias_name()1351     fn test_node_types_with_multiple_rules_same_alias_name() {
1352         let node_types = get_node_types(InputGrammar {
1353             name: String::new(),
1354             word_token: None,
1355             extra_symbols: vec![],
1356             external_tokens: vec![],
1357             supertype_symbols: vec![],
1358             expected_conflicts: vec![],
1359             variables_to_inline: vec![],
1360             precedence_orderings: vec![],
1361             variables: vec![
1362                 Variable {
1363                     name: "script".to_string(),
1364                     kind: VariableType::Named,
1365                     rule: Rule::choice(vec![
1366                         Rule::named("a"),
1367                         // Rule `b` is aliased as rule `a`
1368                         Rule::alias(Rule::named("b"), "a".to_string(), true),
1369                     ]),
1370                 },
1371                 Variable {
1372                     name: "a".to_string(),
1373                     kind: VariableType::Named,
1374                     rule: Rule::seq(vec![
1375                         Rule::field("f1".to_string(), Rule::string("1")),
1376                         Rule::field("f2".to_string(), Rule::string("2")),
1377                     ]),
1378                 },
1379                 Variable {
1380                     name: "b".to_string(),
1381                     kind: VariableType::Named,
1382                     rule: Rule::seq(vec![
1383                         Rule::field("f2".to_string(), Rule::string("22")),
1384                         Rule::field("f2".to_string(), Rule::string("222")),
1385                         Rule::field("f3".to_string(), Rule::string("3")),
1386                     ]),
1387                 },
1388             ],
1389         });
1390 
1391         assert_eq!(
1392             &node_types
1393                 .iter()
1394                 .map(|t| t.kind.as_str())
1395                 .collect::<Vec<_>>(),
1396             &["a", "script", "1", "2", "22", "222", "3"]
1397         );
1398 
1399         assert_eq!(
1400             &node_types[0..2],
1401             &[
1402                 // A combination of the types for `a` and `b`.
1403                 NodeInfoJSON {
1404                     kind: "a".to_string(),
1405                     named: true,
1406                     subtypes: None,
1407                     children: None,
1408                     fields: Some(
1409                         vec![
1410                             (
1411                                 "f1".to_string(),
1412                                 FieldInfoJSON {
1413                                     multiple: false,
1414                                     required: false,
1415                                     types: vec![NodeTypeJSON {
1416                                         kind: "1".to_string(),
1417                                         named: false,
1418                                     }]
1419                                 }
1420                             ),
1421                             (
1422                                 "f2".to_string(),
1423                                 FieldInfoJSON {
1424                                     multiple: true,
1425                                     required: true,
1426                                     types: vec![
1427                                         NodeTypeJSON {
1428                                             kind: "2".to_string(),
1429                                             named: false,
1430                                         },
1431                                         NodeTypeJSON {
1432                                             kind: "22".to_string(),
1433                                             named: false,
1434                                         },
1435                                         NodeTypeJSON {
1436                                             kind: "222".to_string(),
1437                                             named: false,
1438                                         }
1439                                     ]
1440                                 },
1441                             ),
1442                             (
1443                                 "f3".to_string(),
1444                                 FieldInfoJSON {
1445                                     multiple: false,
1446                                     required: false,
1447                                     types: vec![NodeTypeJSON {
1448                                         kind: "3".to_string(),
1449                                         named: false,
1450                                     }]
1451                                 }
1452                             ),
1453                         ]
1454                         .into_iter()
1455                         .collect()
1456                     ),
1457                 },
1458                 NodeInfoJSON {
1459                     kind: "script".to_string(),
1460                     named: true,
1461                     subtypes: None,
1462                     // Only one node
1463                     children: Some(FieldInfoJSON {
1464                         multiple: false,
1465                         required: true,
1466                         types: vec![NodeTypeJSON {
1467                             kind: "a".to_string(),
1468                             named: true,
1469                         }]
1470                     }),
1471                     fields: Some(BTreeMap::new()),
1472                 }
1473             ]
1474         );
1475     }
1476 
1477     #[test]
test_node_types_with_tokens_aliased_to_match_rules()1478     fn test_node_types_with_tokens_aliased_to_match_rules() {
1479         let node_types = get_node_types(InputGrammar {
1480             name: String::new(),
1481             word_token: None,
1482             extra_symbols: vec![],
1483             external_tokens: vec![],
1484             supertype_symbols: vec![],
1485             expected_conflicts: vec![],
1486             variables_to_inline: vec![],
1487             precedence_orderings: vec![],
1488             variables: vec![
1489                 Variable {
1490                     name: "a".to_string(),
1491                     kind: VariableType::Named,
1492                     rule: Rule::seq(vec![Rule::named("b"), Rule::named("c")]),
1493                 },
1494                 // Ordinarily, `b` nodes have two named `c` children.
1495                 Variable {
1496                     name: "b".to_string(),
1497                     kind: VariableType::Named,
1498                     rule: Rule::seq(vec![Rule::named("c"), Rule::string("B"), Rule::named("c")]),
1499                 },
1500                 Variable {
1501                     name: "c".to_string(),
1502                     kind: VariableType::Named,
1503                     rule: Rule::choice(vec![
1504                         Rule::string("C"),
1505                         // This token is aliased as a `b`, which will produce a `b` node
1506                         // with no children.
1507                         Rule::alias(Rule::string("D"), "b".to_string(), true),
1508                     ]),
1509                 },
1510             ],
1511         });
1512 
1513         assert_eq!(
1514             node_types.iter().map(|n| &n.kind).collect::<Vec<_>>(),
1515             &["a", "b", "c", "B", "C"]
1516         );
1517         assert_eq!(
1518             node_types[1],
1519             NodeInfoJSON {
1520                 kind: "b".to_string(),
1521                 named: true,
1522                 subtypes: None,
1523                 children: Some(FieldInfoJSON {
1524                     multiple: true,
1525                     required: false,
1526                     types: vec![NodeTypeJSON {
1527                         kind: "c".to_string(),
1528                         named: true,
1529                     }]
1530                 }),
1531                 fields: Some(BTreeMap::new()),
1532             }
1533         );
1534     }
1535 
1536     #[test]
test_get_variable_info()1537     fn test_get_variable_info() {
1538         let variable_info = get_variable_info(
1539             &build_syntax_grammar(
1540                 vec![
1541                     // Required field `field1` has only one node type.
1542                     SyntaxVariable {
1543                         name: "rule0".to_string(),
1544                         kind: VariableType::Named,
1545                         productions: vec![Production {
1546                             dynamic_precedence: 0,
1547                             steps: vec![
1548                                 ProductionStep::new(Symbol::terminal(0)),
1549                                 ProductionStep::new(Symbol::non_terminal(1))
1550                                     .with_field_name("field1"),
1551                             ],
1552                         }],
1553                     },
1554                     // Hidden node
1555                     SyntaxVariable {
1556                         name: "_rule1".to_string(),
1557                         kind: VariableType::Hidden,
1558                         productions: vec![Production {
1559                             dynamic_precedence: 0,
1560                             steps: vec![ProductionStep::new(Symbol::terminal(1))],
1561                         }],
1562                     },
1563                     // Optional field `field2` can have two possible node types.
1564                     SyntaxVariable {
1565                         name: "rule2".to_string(),
1566                         kind: VariableType::Named,
1567                         productions: vec![
1568                             Production {
1569                                 dynamic_precedence: 0,
1570                                 steps: vec![ProductionStep::new(Symbol::terminal(0))],
1571                             },
1572                             Production {
1573                                 dynamic_precedence: 0,
1574                                 steps: vec![
1575                                     ProductionStep::new(Symbol::terminal(0)),
1576                                     ProductionStep::new(Symbol::terminal(2))
1577                                         .with_field_name("field2"),
1578                                 ],
1579                             },
1580                             Production {
1581                                 dynamic_precedence: 0,
1582                                 steps: vec![
1583                                     ProductionStep::new(Symbol::terminal(0)),
1584                                     ProductionStep::new(Symbol::terminal(3))
1585                                         .with_field_name("field2"),
1586                                 ],
1587                             },
1588                         ],
1589                     },
1590                 ],
1591                 vec![],
1592             ),
1593             &build_lexical_grammar(),
1594             &AliasMap::new(),
1595         )
1596         .unwrap();
1597 
1598         assert_eq!(
1599             variable_info[0].fields,
1600             vec![(
1601                 "field1".to_string(),
1602                 FieldInfo {
1603                     quantity: ChildQuantity {
1604                         exists: true,
1605                         required: true,
1606                         multiple: false,
1607                     },
1608                     types: vec![ChildType::Normal(Symbol::terminal(1))],
1609                 }
1610             )]
1611             .into_iter()
1612             .collect::<HashMap<_, _>>()
1613         );
1614 
1615         assert_eq!(
1616             variable_info[2].fields,
1617             vec![(
1618                 "field2".to_string(),
1619                 FieldInfo {
1620                     quantity: ChildQuantity {
1621                         exists: true,
1622                         required: false,
1623                         multiple: false,
1624                     },
1625                     types: vec![
1626                         ChildType::Normal(Symbol::terminal(2)),
1627                         ChildType::Normal(Symbol::terminal(3)),
1628                     ],
1629                 }
1630             )]
1631             .into_iter()
1632             .collect::<HashMap<_, _>>()
1633         );
1634     }
1635 
1636     #[test]
test_get_variable_info_with_repetitions_inside_fields()1637     fn test_get_variable_info_with_repetitions_inside_fields() {
1638         let variable_info = get_variable_info(
1639             &build_syntax_grammar(
1640                 vec![
1641                     // Field associated with a repetition.
1642                     SyntaxVariable {
1643                         name: "rule0".to_string(),
1644                         kind: VariableType::Named,
1645                         productions: vec![
1646                             Production {
1647                                 dynamic_precedence: 0,
1648                                 steps: vec![ProductionStep::new(Symbol::non_terminal(1))
1649                                     .with_field_name("field1")],
1650                             },
1651                             Production {
1652                                 dynamic_precedence: 0,
1653                                 steps: vec![],
1654                             },
1655                         ],
1656                     },
1657                     // Repetition node
1658                     SyntaxVariable {
1659                         name: "_rule0_repeat".to_string(),
1660                         kind: VariableType::Hidden,
1661                         productions: vec![
1662                             Production {
1663                                 dynamic_precedence: 0,
1664                                 steps: vec![ProductionStep::new(Symbol::terminal(1))],
1665                             },
1666                             Production {
1667                                 dynamic_precedence: 0,
1668                                 steps: vec![
1669                                     ProductionStep::new(Symbol::non_terminal(1)),
1670                                     ProductionStep::new(Symbol::non_terminal(1)),
1671                                 ],
1672                             },
1673                         ],
1674                     },
1675                 ],
1676                 vec![],
1677             ),
1678             &build_lexical_grammar(),
1679             &AliasMap::new(),
1680         )
1681         .unwrap();
1682 
1683         assert_eq!(
1684             variable_info[0].fields,
1685             vec![(
1686                 "field1".to_string(),
1687                 FieldInfo {
1688                     quantity: ChildQuantity {
1689                         exists: true,
1690                         required: false,
1691                         multiple: true,
1692                     },
1693                     types: vec![ChildType::Normal(Symbol::terminal(1))],
1694                 }
1695             )]
1696             .into_iter()
1697             .collect::<HashMap<_, _>>()
1698         );
1699     }
1700 
1701     #[test]
test_get_variable_info_with_inherited_fields()1702     fn test_get_variable_info_with_inherited_fields() {
1703         let variable_info = get_variable_info(
1704             &build_syntax_grammar(
1705                 vec![
1706                     SyntaxVariable {
1707                         name: "rule0".to_string(),
1708                         kind: VariableType::Named,
1709                         productions: vec![
1710                             Production {
1711                                 dynamic_precedence: 0,
1712                                 steps: vec![
1713                                     ProductionStep::new(Symbol::terminal(0)),
1714                                     ProductionStep::new(Symbol::non_terminal(1)),
1715                                     ProductionStep::new(Symbol::terminal(1)),
1716                                 ],
1717                             },
1718                             Production {
1719                                 dynamic_precedence: 0,
1720                                 steps: vec![ProductionStep::new(Symbol::non_terminal(1))],
1721                             },
1722                         ],
1723                     },
1724                     // Hidden node with fields
1725                     SyntaxVariable {
1726                         name: "_rule1".to_string(),
1727                         kind: VariableType::Hidden,
1728                         productions: vec![Production {
1729                             dynamic_precedence: 0,
1730                             steps: vec![
1731                                 ProductionStep::new(Symbol::terminal(2)).with_alias(".", false),
1732                                 ProductionStep::new(Symbol::terminal(3)).with_field_name("field1"),
1733                             ],
1734                         }],
1735                     },
1736                 ],
1737                 vec![],
1738             ),
1739             &build_lexical_grammar(),
1740             &AliasMap::new(),
1741         )
1742         .unwrap();
1743 
1744         assert_eq!(
1745             variable_info[0].fields,
1746             vec![(
1747                 "field1".to_string(),
1748                 FieldInfo {
1749                     quantity: ChildQuantity {
1750                         exists: true,
1751                         required: true,
1752                         multiple: false,
1753                     },
1754                     types: vec![ChildType::Normal(Symbol::terminal(3))],
1755                 }
1756             )]
1757             .into_iter()
1758             .collect::<HashMap<_, _>>()
1759         );
1760 
1761         assert_eq!(
1762             variable_info[0].children_without_fields,
1763             FieldInfo {
1764                 quantity: ChildQuantity {
1765                     exists: true,
1766                     required: false,
1767                     multiple: true,
1768                 },
1769                 types: vec![
1770                     ChildType::Normal(Symbol::terminal(0)),
1771                     ChildType::Normal(Symbol::terminal(1)),
1772                 ],
1773             }
1774         );
1775     }
1776 
1777     #[test]
test_get_variable_info_with_supertypes()1778     fn test_get_variable_info_with_supertypes() {
1779         let variable_info = get_variable_info(
1780             &build_syntax_grammar(
1781                 vec![
1782                     SyntaxVariable {
1783                         name: "rule0".to_string(),
1784                         kind: VariableType::Named,
1785                         productions: vec![Production {
1786                             dynamic_precedence: 0,
1787                             steps: vec![
1788                                 ProductionStep::new(Symbol::terminal(0)),
1789                                 ProductionStep::new(Symbol::non_terminal(1))
1790                                     .with_field_name("field1"),
1791                                 ProductionStep::new(Symbol::terminal(1)),
1792                             ],
1793                         }],
1794                     },
1795                     SyntaxVariable {
1796                         name: "_rule1".to_string(),
1797                         kind: VariableType::Hidden,
1798                         productions: vec![
1799                             Production {
1800                                 dynamic_precedence: 0,
1801                                 steps: vec![ProductionStep::new(Symbol::terminal(2))],
1802                             },
1803                             Production {
1804                                 dynamic_precedence: 0,
1805                                 steps: vec![ProductionStep::new(Symbol::terminal(3))],
1806                             },
1807                         ],
1808                     },
1809                 ],
1810                 // _rule1 is a supertype
1811                 vec![Symbol::non_terminal(1)],
1812             ),
1813             &build_lexical_grammar(),
1814             &AliasMap::new(),
1815         )
1816         .unwrap();
1817 
1818         assert_eq!(
1819             variable_info[0].fields,
1820             vec![(
1821                 "field1".to_string(),
1822                 FieldInfo {
1823                     quantity: ChildQuantity {
1824                         exists: true,
1825                         required: true,
1826                         multiple: false,
1827                     },
1828                     types: vec![ChildType::Normal(Symbol::non_terminal(1))],
1829                 }
1830             )]
1831             .into_iter()
1832             .collect::<HashMap<_, _>>()
1833         );
1834     }
1835 
get_node_types(grammar: InputGrammar) -> Vec<NodeInfoJSON>1836     fn get_node_types(grammar: InputGrammar) -> Vec<NodeInfoJSON> {
1837         let (syntax_grammar, lexical_grammar, _, default_aliases) =
1838             prepare_grammar(&grammar).unwrap();
1839         let variable_info =
1840             get_variable_info(&syntax_grammar, &lexical_grammar, &default_aliases).unwrap();
1841         generate_node_types_json(
1842             &syntax_grammar,
1843             &lexical_grammar,
1844             &default_aliases,
1845             &variable_info,
1846         )
1847     }
1848 
build_syntax_grammar( variables: Vec<SyntaxVariable>, supertype_symbols: Vec<Symbol>, ) -> SyntaxGrammar1849     fn build_syntax_grammar(
1850         variables: Vec<SyntaxVariable>,
1851         supertype_symbols: Vec<Symbol>,
1852     ) -> SyntaxGrammar {
1853         let mut syntax_grammar = SyntaxGrammar::default();
1854         syntax_grammar.variables = variables;
1855         syntax_grammar.supertype_symbols = supertype_symbols;
1856         syntax_grammar
1857     }
1858 
build_lexical_grammar() -> LexicalGrammar1859     fn build_lexical_grammar() -> LexicalGrammar {
1860         let mut lexical_grammar = LexicalGrammar::default();
1861         for i in 0..10 {
1862             lexical_grammar.variables.push(LexicalVariable {
1863                 name: format!("token_{}", i),
1864                 kind: VariableType::Named,
1865                 implicit_precedence: 0,
1866                 start_state: 0,
1867             });
1868         }
1869         lexical_grammar
1870     }
1871 }
1872