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