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