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