1use std::collections::{HashMap, HashSet, VecDeque};
8use std::fmt;
9use std::sync::Arc;
10
11use super::compile::Compiler;
12use super::forking::GrammarFacts;
13use super::program::{
14 Compiled, Expr, Program, Rule, Scanner, Settling, SettlingStep, Target, Trivia,
15};
16use super::token_ranks::token_ranks;
17use crate::grammar::interchange::render_native_expression;
18use crate::grammar::{
19 FeatureExpr, FeatureForm, FieldValue, Grammar, GrammarExpr, GrammarFormat, GrammarMacro,
20 GrammarScanner, Operation, PrecedenceEntry, RuleAttributes, RuleKind, default_settling,
21 settling_problem,
22};
23
24#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct GrammarRuntimeError {
29 pub reason: &'static str,
31 pub message: String,
33}
34
35impl fmt::Display for GrammarRuntimeError {
36 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(formatter, "{} ({})", self.message, self.reason)
38 }
39}
40
41impl std::error::Error for GrammarRuntimeError {}
42
43pub(super) type LoadResult<T> = Result<T, GrammarRuntimeError>;
44
45pub(super) fn refuse<T>(reason: &'static str, message: impl Into<String>) -> LoadResult<T> {
47 Err(GrammarRuntimeError {
48 reason,
49 message: message.into(),
50 })
51}
52
53pub(super) type Resolver<'a> = Option<&'a dyn Fn(&str) -> Option<Grammar>>;
55
56const INSTANCE_LIMIT: usize = 1000;
57
58struct Ordered<T> {
60 items: Vec<(String, T)>,
61 index: HashMap<String, usize>,
62}
63
64impl<T> Ordered<T> {
65 fn new() -> Self {
66 Self {
67 items: Vec::new(),
68 index: HashMap::new(),
69 }
70 }
71
72 fn set(&mut self, name: String, value: T) {
73 if let Some(&position) = self.index.get(&name) {
74 self.items[position].1 = value;
75 } else {
76 self.index.insert(name.clone(), self.items.len());
77 self.items.push((name, value));
78 }
79 }
80
81 fn get(&self, name: &str) -> Option<&T> {
82 self.index
83 .get(name)
84 .map(|&position| &self.items[position].1)
85 }
86
87 fn contains(&self, name: &str) -> bool {
88 self.index.contains_key(name)
89 }
90
91 const fn len(&self) -> usize {
92 self.items.len()
93 }
94}
95
96pub(super) fn form_of<'a>(expr: &'a GrammarExpr, head: &str) -> Option<&'a FeatureForm> {
98 match expr {
99 GrammarExpr::Feature(feature) => match &**feature {
100 FeatureExpr::Form(form) if form.head == head => Some(form),
101 _ => None,
102 },
103 _ => None,
104 }
105}
106
107fn map_children_mut(expr: &mut GrammarExpr, map: &mut impl FnMut(&mut GrammarExpr)) {
109 match expr {
110 GrammarExpr::Optional(inner)
111 | GrammarExpr::ZeroOrMore(inner)
112 | GrammarExpr::OneOrMore(inner)
113 | GrammarExpr::And(inner)
114 | GrammarExpr::Not(inner)
115 | GrammarExpr::Repeat { expr: inner, .. }
116 | GrammarExpr::Capture { expr: inner, .. } => map(inner),
117 GrammarExpr::Choice { alternatives, .. } => alternatives.iter_mut().for_each(map),
118 GrammarExpr::Sequence(items) => items.iter_mut().for_each(map),
119 GrammarExpr::Feature(feature) => feature.map_expressions(map),
120 GrammarExpr::Empty
121 | GrammarExpr::Terminal(_)
122 | GrammarExpr::TerminalInsensitive(_)
123 | GrammarExpr::CharRange(..)
124 | GrammarExpr::CharClass { .. }
125 | GrammarExpr::AnyChar
126 | GrammarExpr::NonTerminal(_) => {}
127 }
128}
129
130fn try_map_children(
132 expr: &GrammarExpr,
133 mut map: impl FnMut(&GrammarExpr) -> LoadResult<GrammarExpr>,
134) -> LoadResult<GrammarExpr> {
135 let mut copy = expr.clone();
136 let mut failure = None;
137 map_children_mut(&mut copy, &mut |child: &mut GrammarExpr| {
138 if failure.is_none() {
139 match map(child) {
140 Ok(mapped) => *child = mapped,
141 Err(error) => failure = Some(error),
142 }
143 }
144 });
145 failure.map_or(Ok(copy), Err)
146}
147
148fn try_map_operations(
150 operations: &[Operation],
151 mut map: impl FnMut(&GrammarExpr) -> LoadResult<GrammarExpr>,
152) -> LoadResult<Vec<Operation>> {
153 let mut copy = operations.to_vec();
154 let mut failure = None;
155 for operation in &mut copy {
156 operation.map_expressions(&mut |child: &mut GrammarExpr| {
157 if failure.is_none() {
158 match map(child) {
159 Ok(mapped) => *child = mapped,
160 Err(error) => failure = Some(error),
161 }
162 }
163 });
164 }
165 failure.map_or(Ok(copy), Err)
166}
167
168struct Context<'a> {
170 resolver: Resolver<'a>,
171 programs: Vec<Program>,
172 languages: HashMap<String, usize>,
173}
174
175impl Context<'_> {
176 fn resolve(&self, name: &str, purpose: &'static str) -> LoadResult<Grammar> {
177 let resolved = self.resolver.and_then(|resolve| resolve(name));
178 resolved.map_or_else(
179 || {
180 let what = if purpose == "import" {
181 "imported grammar"
182 } else {
183 "embedded language"
184 };
185 refuse(purpose, format!("{what} {name} cannot be resolved"))
186 },
187 Ok,
188 )
189 }
190}
191
192struct Resolved {
194 start: Option<String>,
195 peg_source: bool,
196 matching: Option<String>,
197 settling: Option<Vec<String>>,
198 rules: Ordered<(RuleKind, GrammarExpr, RuleAttributes)>,
199 modes: Vec<String>,
200 extras: Vec<GrammarExpr>,
201 conflicts: Vec<Vec<String>>,
202 precedences: Vec<Vec<PrecedenceEntry>>,
203 macros: Ordered<GrammarMacro>,
204 scanners: Vec<GrammarScanner>,
205}
206
207fn resolve_imports(
212 grammar: &Grammar,
213 context: &Context<'_>,
214 chain: &[String],
215) -> LoadResult<Resolved> {
216 let declarations = grammar.declarations();
217 let mut resolved = Resolved {
218 start: grammar
219 .start()
220 .map(str::to_owned)
221 .or_else(|| grammar.rules().first().map(|rule| rule.name.clone())),
222 peg_source: grammar.source_format() == Some(GrammarFormat::Peg),
223 matching: declarations.matching.clone(),
224 settling: declarations.settling.clone(),
225 rules: Ordered::new(),
226 modes: Vec::new(),
227 extras: Vec::new(),
228 conflicts: Vec::new(),
229 precedences: Vec::new(),
230 macros: Ordered::new(),
231 scanners: Vec::new(),
232 };
233 for name in &declarations.imports {
234 let mut next = chain.to_vec();
235 next.push(name.clone());
236 if chain.contains(name) {
237 return refuse("import", format!("import cycle {}", next.join(" -> ")));
238 }
239 let imported = context.resolve(name, "import")?;
240 let inner = resolve_imports(&imported, context, &next)?;
241 for (rule_name, rule) in inner.rules.items {
242 resolved.rules.set(rule_name, rule);
243 }
244 resolved.modes.extend(inner.modes);
245 resolved.extras.extend(inner.extras);
246 resolved.conflicts.extend(inner.conflicts);
247 resolved.precedences.extend(inner.precedences);
248 for (macro_name, item) in inner.macros.items {
249 resolved.macros.set(macro_name, item);
250 }
251 resolved.scanners.extend(inner.scanners);
252 }
253 for rule in grammar.rules() {
254 resolved.rules.set(
255 rule.name.clone(),
256 (rule.kind, rule.expr.clone(), rule.attributes.clone()),
257 );
258 }
259 resolved.modes.extend(declarations.modes.iter().cloned());
260 resolved.extras.extend(declarations.extras.iter().cloned());
261 resolved
262 .conflicts
263 .extend(declarations.conflicts.iter().cloned());
264 resolved
265 .precedences
266 .extend(declarations.precedences.iter().cloned());
267 for item in &declarations.macros {
268 resolved.macros.set(item.name.clone(), item.clone());
269 }
270 resolved
271 .scanners
272 .extend(declarations.scanners.iter().cloned());
273 Ok(resolved)
274}
275
276fn substitute(expr: &GrammarExpr, bindings: &HashMap<String, GrammarExpr>) -> GrammarExpr {
277 if let Some(bound) = form_of(expr, "parameter")
278 .and_then(|form| form.text("name"))
279 .and_then(|name| bindings.get(name))
280 {
281 return bound.clone();
282 }
283 let mut copy = expr.clone();
284 map_children_mut(&mut copy, &mut |child: &mut GrammarExpr| {
285 *child = substitute(child, bindings);
286 });
287 copy
288}
289
290fn expand_macros(
293 expr: &GrammarExpr,
294 macros: &Ordered<GrammarMacro>,
295 active: &mut Vec<String>,
296) -> LoadResult<GrammarExpr> {
297 let Some(form) = form_of(expr, "expand") else {
298 return try_map_children(expr, |child| expand_macros(child, macros, active));
299 };
300 let name = form.text("name").unwrap_or_default();
301 let arguments = form.expressions("arguments");
302 let Some(definition) = macros.get(name) else {
303 return refuse("macro", format!("undefined macro {name}"));
304 };
305 if active.iter().any(|item| item == name) {
306 return refuse(
307 "macro",
308 format!("recursive macro {} -> {name}", active.join(" -> ")),
309 );
310 }
311 if definition.parameters.len() != arguments.len() {
312 return refuse(
313 "macro",
314 format!(
315 "macro {name} takes {} arguments, not {}",
316 definition.parameters.len(),
317 arguments.len()
318 ),
319 );
320 }
321 let mut bindings = HashMap::new();
322 for (parameter, argument) in definition.parameters.iter().zip(arguments) {
323 bindings.insert(parameter.clone(), expand_macros(argument, macros, active)?);
324 }
325 active.push(name.to_owned());
326 let expanded = expand_macros(
327 &substitute(&definition.expression, &bindings),
328 macros,
329 active,
330 );
331 active.pop();
332 expanded
333}
334
335struct Source {
337 kind: RuleKind,
338 expression: GrammarExpr,
339 action: Option<Vec<Operation>>,
340 attributes: RuleAttributes,
341}
342
343struct Instance {
345 node_kind: String,
346 source: String,
347 expression: GrammarExpr,
348 action: Option<Vec<Operation>>,
349}
350
351struct Pending {
352 name: String,
353 target: String,
354 bindings: HashMap<String, GrammarExpr>,
355}
356
357struct Instantiator<'a> {
360 sources: &'a Ordered<Source>,
361 external: &'a HashMap<String, usize>,
362 rules: Ordered<Instance>,
363 pending: VecDeque<Pending>,
364 queued: HashSet<String>,
365}
366
367impl Instantiator<'_> {
368 fn instantiate(
369 &mut self,
370 expr: &GrammarExpr,
371 bindings: Option<&HashMap<String, GrammarExpr>>,
372 owner: &str,
373 ) -> LoadResult<GrammarExpr> {
374 if let Some(form) = form_of(expr, "parameter") {
375 let name = form.text("name").unwrap_or_default();
376 return bindings.and_then(|bound| bound.get(name)).map_or_else(
377 || {
378 refuse(
379 "parameter",
380 format!("parameter {name} is not a parameter of {owner}"),
381 )
382 },
383 |bound| Ok(bound.clone()),
384 );
385 }
386 let (name, arguments): (&str, &[GrammarExpr]) = match expr {
387 GrammarExpr::NonTerminal(name) => (name, &[]),
388 GrammarExpr::Feature(feature) => match &**feature {
389 FeatureExpr::Call { name, arguments } => (name, arguments),
390 _ => {
391 return try_map_children(expr, |child| {
392 self.instantiate(child, bindings, owner)
393 });
394 }
395 },
396 _ => return try_map_children(expr, |child| self.instantiate(child, bindings, owner)),
397 };
398 if self.external.contains_key(name) {
399 if !arguments.is_empty() {
400 return refuse(
401 "parameter",
402 format!("external token {name} takes no arguments"),
403 );
404 }
405 return Ok(GrammarExpr::NonTerminal(name.to_owned()));
406 }
407 let Some(target) = self.sources.get(name) else {
408 return refuse("reference", format!("undefined rule {name} in {owner}"));
409 };
410 let parameters = &target.attributes.parameters;
411 if arguments.len() != parameters.len() {
412 return refuse(
413 "parameter",
414 format!(
415 "rule {name} takes {} arguments, not {}",
416 parameters.len(),
417 arguments.len()
418 ),
419 );
420 }
421 if parameters.is_empty() {
422 return Ok(GrammarExpr::NonTerminal(name.to_owned()));
423 }
424 let concrete = arguments
425 .iter()
426 .map(|argument| self.instantiate(argument, bindings, owner))
427 .collect::<LoadResult<Vec<_>>>()?;
428 let rendered = concrete
429 .iter()
430 .map(render_native_expression)
431 .collect::<Vec<_>>();
432 let instance = format!("{name}({})", rendered.join(", "));
433 if !self.rules.contains(&instance) && !self.queued.contains(&instance) {
434 if self.rules.len() + self.pending.len() >= INSTANCE_LIMIT + self.sources.len() {
435 return refuse(
436 "parameter",
437 format!("parameterized rule {name} needs more than {INSTANCE_LIMIT} instances"),
438 );
439 }
440 self.queued.insert(instance.clone());
441 self.pending.push_back(Pending {
442 name: instance.clone(),
443 target: name.to_owned(),
444 bindings: parameters.iter().cloned().zip(concrete).collect(),
445 });
446 }
447 Ok(GrammarExpr::NonTerminal(instance))
448 }
449
450 fn instantiate_operations(
451 &mut self,
452 operations: &[Operation],
453 bindings: Option<&HashMap<String, GrammarExpr>>,
454 owner: &str,
455 ) -> LoadResult<Vec<Operation>> {
456 try_map_operations(operations, |expr| self.instantiate(expr, bindings, owner))
457 }
458
459 fn drain(&mut self) -> LoadResult<()> {
460 while let Some(Pending {
461 name,
462 target,
463 bindings,
464 }) = self.pending.pop_front()
465 {
466 let source = self
467 .sources
468 .get(&target)
469 .expect("a pending instance names a rule");
470 let owner = format!("rule {target}");
471 let expression = self.instantiate(&source.expression, Some(&bindings), &owner)?;
472 let action = match &source.action {
473 Some(action) => {
474 Some(self.instantiate_operations(action, Some(&bindings), &owner)?)
475 }
476 None => None,
477 };
478 self.rules.set(
479 name,
480 Instance {
481 node_kind: target.clone(),
482 source: target,
483 expression,
484 action,
485 },
486 );
487 }
488 Ok(())
489 }
490}
491
492pub(super) fn load(grammar: &Grammar, resolver: Resolver<'_>) -> LoadResult<Compiled> {
494 let mut context = Context {
495 resolver,
496 programs: Vec::new(),
497 languages: HashMap::new(),
498 };
499 let main = load_in_context(grammar, &mut context)?;
500 Ok(Compiled {
501 programs: context.programs,
502 languages: context.languages,
503 main,
504 })
505}
506
507fn nesting_extras(
515 trivia: &[Trivia],
516 rules: &[Rule],
517 rule_index: &HashMap<String, usize>,
518) -> HashSet<Arc<str>> {
519 fn targets<'e>(expr: &'e Expr, found: &mut Vec<&'e Target>) {
520 match expr {
521 Expr::Ref(target) => found.push(target),
522 Expr::Seq(items) | Expr::Choice { items, .. } | Expr::Longest(items) => {
523 for item in items {
524 targets(item, found);
525 }
526 }
527 Expr::Repeat { item, .. }
528 | Expr::Capture { item, .. }
529 | Expr::Alias { item, .. }
530 | Expr::Precedence { item, .. }
531 | Expr::DynamicPrecedence { item, .. }
532 | Expr::LexicalPrecedence { item, .. }
533 | Expr::Predicate { item, .. }
534 | Expr::Missing { item, .. }
535 | Expr::Embed { item, .. } => targets(item, found),
536 Expr::And(item) | Expr::Not(item) | Expr::Token(item) | Expr::ImmediateToken(item) => {
537 targets(item, found);
538 }
539 Expr::Recover { item, synchronize } => {
540 targets(item, found);
541 targets(synchronize, found);
542 }
543 Expr::Empty | Expr::Terminal { .. } => {}
544 }
545 }
546 let mut nesting = HashSet::new();
547 for kind in trivia.iter().filter_map(|item| item.kind.as_ref()) {
548 let Some(&index) = rule_index.get(&**kind) else {
549 continue;
550 };
551 if !matches!(rules[index].kind, RuleKind::Normal) {
552 continue;
553 }
554 let mut seen = HashSet::from([index]);
555 let mut pending = vec![index];
556 let mut scanned = false;
557 while let Some(at) = pending.pop() {
558 let mut found = Vec::new();
559 targets(&rules[at].expression, &mut found);
560 for target in found {
561 match target {
562 Target::External(_) => scanned = true,
563 Target::Rule(next) => {
564 if seen.insert(*next) {
565 pending.push(*next);
566 }
567 }
568 }
569 }
570 if scanned {
571 break;
572 }
573 }
574 if !scanned {
575 nesting.insert(kind.clone());
576 }
577 }
578 nesting
579}
580
581fn load_in_context(grammar: &Grammar, context: &mut Context<'_>) -> LoadResult<usize> {
582 let resolved = resolve_imports(grammar, context, &[])?;
583 let macros = &resolved.macros;
584 let expand = |expr: &GrammarExpr| expand_macros(expr, macros, &mut Vec::new());
585
586 let mut external = HashMap::new();
587 for (index, scanner) in resolved.scanners.iter().enumerate() {
588 for token in &scanner.tokens {
589 if external.contains_key(token) {
590 return refuse(
591 "declaration",
592 format!("external token {token} is declared twice"),
593 );
594 }
595 if resolved.rules.contains(token) {
596 return refuse(
597 "declaration",
598 format!("external token {token} is also a rule"),
599 );
600 }
601 external.insert(token.clone(), index);
602 }
603 }
604 let mut modes: HashSet<String> = HashSet::from(["default".to_owned()]);
605 modes.extend(resolved.modes.iter().cloned());
606
607 let mut sources = Ordered::new();
608 for (name, (kind, expression, attributes)) in &resolved.rules.items {
609 let action = match &attributes.action {
610 Some(action) => Some(try_map_operations(action, expand)?),
611 None => None,
612 };
613 sources.set(
614 name.clone(),
615 Source {
616 kind: *kind,
617 expression: expand(expression)?,
618 action,
619 attributes: attributes.clone(),
620 },
621 );
622 }
623
624 let mut instantiator = Instantiator {
625 sources: &sources,
626 external: &external,
627 rules: Ordered::new(),
628 pending: VecDeque::new(),
629 queued: HashSet::new(),
630 };
631 for (name, source) in &sources.items {
632 if !source.attributes.parameters.is_empty() {
633 continue;
634 }
635 let owner = format!("rule {name}");
636 let expression = instantiator.instantiate(&source.expression, None, &owner)?;
637 let action = match &source.action {
638 Some(action) => Some(instantiator.instantiate_operations(action, None, &owner)?),
639 None => None,
640 };
641 instantiator.rules.set(
642 name.clone(),
643 Instance {
644 node_kind: name.clone(),
645 source: name.clone(),
646 expression,
647 action,
648 },
649 );
650 }
651 instantiator.drain()?;
652
653 let start = resolved.start.clone();
654 let Some(start_source) = start.as_deref().and_then(|name| sources.get(name)) else {
655 return refuse(
656 "reference",
657 format!(
658 "undefined start rule {}",
659 start.as_deref().unwrap_or("null")
660 ),
661 );
662 };
663 if !start_source.attributes.parameters.is_empty() {
664 return refuse(
665 "parameter",
666 format!(
667 "start rule {} is parameterized",
668 start.as_deref().unwrap_or_default()
669 ),
670 );
671 }
672
673 let mut extras = Vec::new();
674 for extra in &resolved.extras {
675 extras.push(instantiator.instantiate(&expand(extra)?, None, "an extra")?);
676 }
677 let mut scanner_operations = Vec::new();
678 for scanner in &resolved.scanners {
679 let expanded = try_map_operations(&scanner.operations, expand)?;
680 let owner = format!("scanner {}", scanner.name);
681 scanner_operations.push(instantiator.instantiate_operations(&expanded, None, &owner)?);
682 }
683 instantiator.drain()?;
684
685 let mut conflicts = HashSet::new();
686 for group in &resolved.conflicts {
687 for name in group {
688 if !sources.contains(name) {
689 return refuse(
690 "declaration",
691 format!("conflict names undefined rule {name}"),
692 );
693 }
694 conflicts.insert(name.clone());
695 }
696 }
697 for order in &resolved.precedences {
699 for entry in order {
700 if let PrecedenceEntry::Rule(name) = entry
701 && !sources.contains(name)
702 {
703 return refuse(
704 "declaration",
705 format!("precedences names undefined rule {name}"),
706 );
707 }
708 }
709 }
710
711 let peg = resolved
712 .matching
713 .as_deref()
714 .map_or(resolved.peg_source, |matching| matching == "peg");
715 let matching = resolved
716 .matching
717 .as_deref()
718 .unwrap_or(if peg { "peg" } else { "generalized" });
719 let settling = match &resolved.settling {
722 Some(steps) => {
723 if let Some(problem) = settling_problem(steps) {
724 return refuse("declaration", problem);
725 }
726 Settling::new(steps)
727 }
728 None => Settling::new(default_settling(matching)),
729 };
730 let instances = instantiator.rules;
731 let rule_index: HashMap<String, usize> = instances
732 .items
733 .iter()
734 .enumerate()
735 .map(|(index, (name, _))| (name.clone(), index))
736 .collect();
737 let node_kinds = instances
738 .items
739 .iter()
740 .map(|(name, instance)| (name.clone(), Arc::from(instance.node_kind.as_str())))
741 .collect();
742 let mut compiler = Compiler::new(&rule_index, &external, &modes, node_kinds);
743 let mut consults = Vec::new();
747 for (scanner, operations) in resolved.scanners.iter().zip(&scanner_operations) {
748 let mut items = Vec::new();
749 if !scanner.tokens.is_empty() {
750 expected_items(operations, &mut items);
751 }
752 consults.push(!items.is_empty());
753 for item in items {
754 if let Some(key) = compiler.expectation(item) {
755 let id = compiler.expectations.len();
756 compiler.expectations.entry(key).or_insert(id);
757 }
758 }
759 }
760 let expected_references = compiler
761 .expectations
762 .iter()
763 .filter_map(|(key, &id)| Some((key.strip_prefix("ref ")?.to_owned(), id)))
764 .collect();
765
766 let mut trivia = Vec::new();
769 for extra in &extras {
770 let expression = compiler.expression(extra, "an extra")?;
771 let kind = match extra {
772 GrammarExpr::NonTerminal(name) => Some(Arc::from(name.as_str())),
773 _ => None,
774 };
775 trivia.push(Trivia {
776 expression,
777 kind,
778 modes: None,
779 });
780 }
781 let mut rules = Vec::new();
782 for (index, (name, instance)) in instances.items.iter().enumerate() {
783 let source = sources
784 .get(&instance.source)
785 .expect("an instance has a source");
786 let owner = format!("rule {}", instance.node_kind);
787 compiler.requesting = true;
788 let expression = compiler.expression(&instance.expression, &owner);
789 compiler.requesting = false;
790 let expression = expression?;
791 let action = match &instance.action {
792 Some(action) => {
793 if source.kind == RuleKind::Silent && action.iter().any(builds_node) {
794 return refuse(
795 "operation",
796 format!("silent {owner} has no node for its action"),
797 );
798 }
799 Some(compiler.statements(action, "action", &owner, None)?)
800 }
801 None => None,
802 };
803 let rule_modes = match &source.attributes.modes {
804 Some(rule_modes) => {
805 for mode in rule_modes {
806 compiler.check_mode(mode, &owner)?;
807 }
808 Some(
809 rule_modes
810 .iter()
811 .map(|mode| Arc::from(mode.as_str()))
812 .collect(),
813 )
814 }
815 None => None,
816 };
817 let lexical_priority = form_of(&instance.expression, "lexicalPrecedence")
818 .and_then(|form| form.integer("level"))
819 .unwrap_or(0);
820 let node_kind: Arc<str> = Arc::from(instance.node_kind.as_str());
821 if source
822 .attributes
823 .channel
824 .as_deref()
825 .is_some_and(|channel| channel != "default")
826 {
827 trivia.push(Trivia {
828 expression: super::program::Expr::Ref(Target::Rule(index)),
829 kind: Some(node_kind.clone()),
830 modes: rule_modes.clone(),
831 });
832 }
833 rules.push(Rule {
834 name: Arc::from(name.as_str()),
835 node_kind,
836 kind: source.kind,
837 expression,
838 action,
839 modes: rule_modes,
840 lexical_priority,
841 });
842 }
843 let mut scanners = Vec::new();
844 for ((scanner, operations), consults) in resolved
845 .scanners
846 .iter()
847 .zip(&scanner_operations)
848 .zip(consults)
849 {
850 let owner = format!("scanner {}", scanner.name);
851 let operations = if scanner.tokens.is_empty() {
852 Vec::new()
853 } else {
854 compiler.statements(
855 operations,
856 "scanner",
857 &owner,
858 Some(scanner.tokens.as_slice()),
859 )?
860 };
861 scanners.push(Scanner {
862 operations,
863 consults,
864 });
865 }
866 let embedded = compiler.into_embedded();
867
868 let index = context.programs.len();
869 let token_ranks = (settling.has(SettlingStep::Tokens)
870 || settling.has(SettlingStep::Precedence))
871 .then(|| token_ranks(&rules));
872 let ranked_silent = resolved
873 .precedences
874 .iter()
875 .flatten()
876 .filter_map(|entry| match entry {
877 PrecedenceEntry::Rule(name)
878 if rule_index
879 .get(name)
880 .is_some_and(|&at| matches!(rules[at].kind, RuleKind::Silent)) =>
881 {
882 Some(name.clone())
883 }
884 _ => None,
885 })
886 .collect();
887 let grammar = GrammarFacts::new(
888 &rules,
889 &resolved.conflicts,
890 settling.has(SettlingStep::Precedence),
891 );
892 let nesting_extras = nesting_extras(&trivia, &rules, &rule_index);
893 context.programs.push(Program {
894 peg,
895 settling,
896 token_ranks,
897 start,
898 rules,
899 rule_index,
900 external,
901 scanners,
902 conflicts,
903 precedence_orders: resolved.precedences.clone(),
904 ranked_silent,
905 trivia,
906 nesting_extras,
907 expected_references,
908 grammar,
909 });
910 for language in embedded {
911 if context.languages.contains_key(&language) {
912 continue;
913 }
914 context.languages.insert(language.clone(), usize::MAX);
915 let grammar = context.resolve(&language, "embed")?;
916 let loaded = load_in_context(&grammar, context)?;
917 context.languages.insert(language, loaded);
918 }
919 Ok(index)
920}
921
922fn expected_items<'a>(operations: &'a [Operation], items: &mut Vec<&'a GrammarExpr>) {
924 for operation in operations {
925 if operation.head == "expected"
926 && let Some(item) = operation.expression("item")
927 {
928 items.push(item);
929 }
930 for value in &operation.fields {
931 match value {
932 FieldValue::Operation(operation) => {
933 expected_items(std::slice::from_ref(operation), items);
934 }
935 FieldValue::Operations(block) | FieldValue::Block(Some(block)) => {
936 expected_items(block, items);
937 }
938 _ => {}
939 }
940 }
941 }
942}
943
944fn builds_node(operation: &Operation) -> bool {
945 if operation.head == "setAttribute" || operation.head == "buildNode" {
946 return true;
947 }
948 ["consequent", "alternative", "body"].iter().any(|key| {
949 operation
950 .operations(key)
951 .is_some_and(|block| block.iter().any(builds_node))
952 })
953}