1#![allow(clippy::derive_partial_eq_without_eq)]
2use std::{cell::RefCell, collections::HashMap, fmt::Write, str::FromStr};
3
4use num_traits::{AsPrimitive, PrimInt, Unsigned};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use vob::Vob;
8#[cfg(feature = "wincode")]
9use wincode::{SchemaRead, SchemaWrite};
10
11use super::{
12 YaccKind, ast,
13 firsts::YaccFirsts,
14 follows::YaccFollows,
15 parser::{YaccGrammarError, YaccGrammarResult},
16};
17use crate::{PIdx, RIdx, SIdx, Span, Symbol, TIdx};
18
19const START_RULE: &str = "^";
20const IMPLICIT_RULE: &str = "~";
21const IMPLICIT_START_RULE: &str = "^~";
22
23pub type PrecedenceLevel = u64;
24#[derive(Clone, Copy, Debug, PartialEq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))]
27pub struct Precedence {
28 pub level: PrecedenceLevel,
29 pub kind: AssocKind,
30}
31
32#[derive(Clone, Copy, Debug, PartialEq)]
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))]
35pub enum AssocKind {
36 Left,
37 Right,
38 Nonassoc,
39}
40
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))]
45pub struct YaccGrammar<StorageT = u32> {
46 rules_len: RIdx<StorageT>,
48 rule_names: Box<[(String, Span)]>,
50 token_names: Box<[Option<(Span, String)>]>,
53 token_precs: Box<[Option<Precedence>]>,
55 token_epp: Box<[Option<String>]>,
61 tokens_len: TIdx<StorageT>,
63 eof_token_idx: TIdx<StorageT>,
65 prods_len: PIdx<StorageT>,
67 start_prod: PIdx<StorageT>,
69 prods: Box<[Box<[Symbol<StorageT>]>]>,
71 rules_prods: Box<[Box<[PIdx<StorageT>]>]>,
75 prods_rules: Box<[RIdx<StorageT>]>,
77 prod_precs: Box<[Option<Precedence>]>,
79 prod_spans: Box<[Span]>,
83 implicit_rule: Option<RIdx<StorageT>>,
86 actions: Box<[Option<String>]>,
88 action_spans: Box<[Option<Span>]>,
90 parse_param: Option<(String, String)>,
92 parse_generics: Option<String>,
94 programs: Option<String>,
96 actiontypes: Box<[Option<String>]>,
98 avoid_insert: Option<Vob>,
100 expect: Option<usize>,
102 expectrr: Option<usize>,
104}
105
106impl YaccGrammar<u32> {
109 pub fn new(yk: YaccKind, s: &str) -> YaccGrammarResult<Self> {
110 YaccGrammar::new_with_storaget(yk, s)
111 }
112}
113
114impl<StorageT: 'static + PrimInt + Unsigned> FromStr for YaccGrammar<StorageT>
115where
116 usize: AsPrimitive<StorageT>,
117{
118 type Err = Vec<YaccGrammarError>;
119 fn from_str(s: &str) -> YaccGrammarResult<Self> {
120 let ast_validation = ast::ASTWithValidityInfo::from_str(s)?;
121 Self::new_from_ast_with_validity_info(&ast_validation)
122 }
123}
124
125impl<StorageT: 'static + PrimInt + Unsigned> YaccGrammar<StorageT>
126where
127 usize: AsPrimitive<StorageT>,
128{
129 pub fn new_with_storaget(yk: YaccKind, s: &str) -> YaccGrammarResult<Self> {
137 let ast_validation = ast::ASTWithValidityInfo::new(yk, s);
138 Self::new_from_ast_with_validity_info(&ast_validation)
139 }
140
141 pub fn new_from_ast_with_validity_info(
142 ast_validation: &ast::ASTWithValidityInfo,
143 ) -> YaccGrammarResult<Self> {
144 if !ast_validation.is_valid() {
145 return Err(ast_validation.errors().to_owned());
146 }
147 let ast = ast_validation.ast();
148 if ast.rules.len() > num_traits::cast(StorageT::max_value()).unwrap() {
151 panic!("StorageT is not big enough to store this grammar's rules.");
152 }
153 if ast.tokens.len() > num_traits::cast(StorageT::max_value()).unwrap() {
154 panic!("StorageT is not big enough to store this grammar's tokens.");
155 }
156 if ast.prods.len() > num_traits::cast(StorageT::max_value()).unwrap() {
157 panic!("StorageT is not big enough to store this grammar's productions.");
158 }
159 for p in &ast.prods {
160 if p.symbols.len() > num_traits::cast(StorageT::max_value()).unwrap() {
161 panic!(
162 "StorageT is not big enough to store the symbols of at least one of this grammar's productions."
163 );
164 }
165 }
166
167 let mut rule_names: Vec<(String, Span)> = Vec::with_capacity(ast.rules.len() + 1);
168
169 let mut start_rule = START_RULE.to_string();
174 while ast.rules.get(&start_rule).is_some() {
175 start_rule += START_RULE;
176 }
177 rule_names.push((start_rule.clone(), Span::new(0, 0)));
178
179 let implicit_rule;
180 let implicit_start_rule;
181 match ast_validation.yacc_kind() {
182 YaccKind::Original(_) | YaccKind::Grmtools => {
183 implicit_rule = None;
184 implicit_start_rule = None;
185 }
186 YaccKind::Eco => {
187 if ast.implicit_tokens.is_some() {
188 let mut n1 = IMPLICIT_RULE.to_string();
189 while ast.rules.get(&n1).is_some() {
190 n1 += IMPLICIT_RULE;
191 }
192 rule_names.push((n1.clone(), Span::new(0, 0)));
193 implicit_rule = Some(n1);
194 let mut n2 = IMPLICIT_START_RULE.to_string();
195 while ast.rules.get(&n2).is_some() {
196 n2 += IMPLICIT_START_RULE;
197 }
198 rule_names.push((n2.clone(), Span::new(0, 0)));
199 implicit_start_rule = Some(n2);
200 } else {
201 implicit_rule = None;
202 implicit_start_rule = None;
203 }
204 }
205 };
206
207 for (
208 k,
209 ast::Rule {
210 name: (_, name_span),
211 ..
212 },
213 ) in &ast.rules
214 {
215 rule_names.push((k.clone(), *name_span));
216 }
217 let mut rules_prods: Vec<Vec<PIdx<StorageT>>> = Vec::with_capacity(rule_names.len());
218 let mut rule_map = HashMap::<String, RIdx<StorageT>>::new();
219 for (i, (v, _)) in rule_names.iter().enumerate() {
220 rules_prods.push(Vec::new());
221 rule_map.insert(v.clone(), RIdx(i.as_()));
222 }
223
224 let mut token_names: Vec<Option<(Span, String)>> = Vec::with_capacity(ast.tokens.len() + 1);
225 let mut token_precs: Vec<Option<Precedence>> = Vec::with_capacity(ast.tokens.len() + 1);
226 let mut token_epp: Vec<Option<String>> = Vec::with_capacity(ast.tokens.len() + 1);
227 for (i, k) in ast.tokens.iter().enumerate() {
228 token_names.push(Some((ast.spans[i], k.clone())));
229 token_precs.push(ast.precs.get(k).map(|(prec, _)| prec).cloned());
230 token_epp.push(Some(
231 ast.epp.get(k).map(|(_, (s, _))| s).unwrap_or(k).clone(),
232 ));
233 }
234 let eof_token_idx = TIdx(token_names.len().as_());
235 token_names.push(None);
236 token_precs.push(None);
237 token_epp.push(None);
238 let mut token_map = HashMap::<String, TIdx<StorageT>>::new();
239 for (i, v) in token_names.iter().enumerate() {
240 if let Some((_, n)) = v.as_ref() {
241 token_map.insert(n.clone(), TIdx(i.as_()));
242 }
243 }
244
245 let mut prods = vec![None; ast.prods.len()];
249 let mut prod_precs: Vec<Option<Option<Precedence>>> = vec![None; ast.prods.len()];
250 let mut prods_rules = vec![None; ast.prods.len()];
251 let mut actions = vec![None; ast.prods.len()];
252 let mut action_spans = vec![None; ast.prods.len()];
253 let mut actiontypes = vec![None; rule_names.len()];
254 let (start_name, _) = ast.start.as_ref().unwrap();
255 for (astrulename, _) in &rule_names {
256 let ridx = rule_map[astrulename];
257 if astrulename == &start_rule {
258 rules_prods[usize::from(ridx)].push(PIdx(prods.len().as_()));
261 let start_prod = match implicit_start_rule {
262 None => {
263 vec![Symbol::Rule(rule_map[start_name])]
265 }
266 Some(ref s) => {
267 vec![Symbol::Rule(rule_map[s])]
271 }
272 };
273 prods.push(Some(start_prod));
274 prod_precs.push(Some(None));
275 prods_rules.push(Some(ridx));
276 actions.push(None);
277 continue;
278 } else if implicit_start_rule.as_ref() == Some(astrulename) {
279 rules_prods[usize::from(rule_map[astrulename])].push(PIdx(prods.len().as_()));
283 prods.push(Some(vec![
284 Symbol::Rule(rule_map[implicit_rule.as_ref().unwrap()]),
285 Symbol::Rule(rule_map[start_name]),
286 ]));
287 prod_precs.push(Some(None));
288 prods_rules.push(Some(ridx));
289 continue;
290 } else if implicit_rule.as_ref() == Some(astrulename) {
291 let implicit_prods = &mut rules_prods[usize::from(rule_map[astrulename])];
293 for t in ast.implicit_tokens.as_ref().unwrap().keys() {
295 implicit_prods.push(PIdx(prods.len().as_()));
296 prods.push(Some(vec![Symbol::Token(token_map[t]), Symbol::Rule(ridx)]));
297 prod_precs.push(Some(None));
298 prods_rules.push(Some(ridx));
299 }
300 implicit_prods.push(PIdx(prods.len().as_()));
302 prods.push(Some(vec![]));
303 prod_precs.push(Some(None));
304 prods_rules.push(Some(ridx));
305 continue;
306 } else {
307 actiontypes[usize::from(ridx)] = ast.rules[astrulename].actiont.clone();
308 }
309
310 let rule = &mut rules_prods[usize::from(ridx)];
311 for &pidx in &ast.rules[astrulename].pidxs {
312 let astprod = &ast.prods[pidx];
313 let mut prod = Vec::with_capacity(astprod.symbols.len());
314 for astsym in &astprod.symbols {
315 match *astsym {
316 ast::Symbol::Rule(ref n, _) => {
317 prod.push(Symbol::Rule(rule_map[n]));
318 }
319 ast::Symbol::Token(ref n, _) => {
320 prod.push(Symbol::Token(token_map[n]));
321 if let Some(implicit_rule) = &implicit_rule {
322 prod.push(Symbol::Rule(rule_map[implicit_rule]));
323 }
324 }
325 };
326 }
327 let mut prec = None;
328 if let Some(ref n) = astprod.precedence {
329 prec = Some(ast.precs[n]);
330 } else {
331 for astsym in astprod.symbols.iter().rev() {
332 if let ast::Symbol::Token(ref n, _) = *astsym {
333 if let Some(p) = ast.precs.get(n) {
334 prec = Some(*p);
335 }
336 break;
337 }
338 }
339 }
340 (*rule).push(PIdx(pidx.as_()));
341 prods[pidx] = Some(prod);
342 prod_precs[pidx] = Some(prec.map(|(prec, _)| prec));
343 prods_rules[pidx] = Some(ridx);
344 if let Some((s, span)) = &astprod.action {
345 actions[pidx] = Some(s.clone());
346 action_spans[pidx] = Some(*span);
347 }
348 }
349 }
350
351 let avoid_insert = if let Some(ai) = &ast.avoid_insert {
352 let mut aiv = Vob::from_elem(false, token_names.len());
353 for n in ai.keys() {
354 aiv.set(usize::from(token_map[n]), true);
355 }
356 Some(aiv)
357 } else {
358 None
359 };
360
361 assert!(!token_names.is_empty());
362 assert!(!rule_names.is_empty());
363 Ok(YaccGrammar {
364 rules_len: RIdx(rule_names.len().as_()),
365 rule_names: rule_names.into_boxed_slice(),
366 tokens_len: TIdx(token_names.len().as_()),
367 eof_token_idx,
368 token_names: token_names.into_boxed_slice(),
369 token_precs: token_precs.into_boxed_slice(),
370 token_epp: token_epp.into_boxed_slice(),
371 prods_len: PIdx(prods.len().as_()),
372 start_prod: rules_prods[usize::from(rule_map[&start_rule])][0],
373 rules_prods: rules_prods
374 .iter()
375 .map(|x| x.iter().copied().collect())
376 .collect(),
377 prods_rules: prods_rules.into_iter().map(Option::unwrap).collect(),
378 prods: prods
379 .into_iter()
380 .map(|x| x.unwrap().into_boxed_slice())
381 .collect(),
382 prod_precs: prod_precs.into_iter().map(Option::unwrap).collect(),
383 prod_spans: ast.prods.iter().map(|prod| prod.prod_span).collect(),
384 implicit_rule: implicit_rule.map(|x| rule_map[&x]),
385 actions: actions.into_boxed_slice(),
386 action_spans: action_spans.into_boxed_slice(),
387 parse_param: ast.parse_param.clone(),
388 parse_generics: ast.parse_generics.clone(),
389 programs: ast.programs.clone(),
390 avoid_insert,
391 actiontypes: actiontypes.into_boxed_slice(),
392 expect: ast.expect.map(|(n, _)| n),
393 expectrr: ast.expectrr.map(|(n, _)| n),
394 })
395 }
396
397 pub fn prods_len(&self) -> PIdx<StorageT> {
399 self.prods_len
400 }
401
402 pub fn iter_pidxs(&self) -> impl Iterator<Item = PIdx<StorageT>> {
405 Box::new((0..usize::from(self.prods_len())).map(|x| PIdx(x.as_())))
409 }
410
411 pub fn prod(&self, pidx: PIdx<StorageT>) -> &[Symbol<StorageT>] {
413 &self.prods[usize::from(pidx)]
414 }
415
416 pub fn prod_len(&self, pidx: PIdx<StorageT>) -> SIdx<StorageT> {
418 SIdx(self.prods[usize::from(pidx)].len().as_())
421 }
422
423 pub fn prod_to_rule(&self, pidx: PIdx<StorageT>) -> RIdx<StorageT> {
425 self.prods_rules[usize::from(pidx)]
426 }
427
428 pub fn prod_precedence(&self, pidx: PIdx<StorageT>) -> Option<Precedence> {
431 self.prod_precs[usize::from(pidx)]
432 }
433
434 pub fn prod_span(&self, pidx: PIdx<StorageT>) -> Span {
438 self.prod_spans[usize::from(pidx)]
439 }
440
441 pub fn start_prod(&self) -> PIdx<StorageT> {
444 self.start_prod
445 }
446
447 pub fn rules_len(&self) -> RIdx<StorageT> {
449 self.rules_len
450 }
451
452 pub fn iter_rules(&self) -> impl Iterator<Item = RIdx<StorageT>> {
455 Box::new((0..usize::from(self.rules_len())).map(|x| RIdx(x.as_())))
459 }
460
461 pub fn rule_to_prods(&self, ridx: RIdx<StorageT>) -> &[PIdx<StorageT>] {
463 &self.rules_prods[usize::from(ridx)]
464 }
465
466 #[deprecated(since = "0.13.0", note = "Please use rule_name_str instead")]
468 pub fn rule_name(&self, ridx: RIdx<StorageT>) -> &str {
469 self.rule_name_str(ridx)
470 }
471
472 pub fn rule_name_str(&self, ridx: RIdx<StorageT>) -> &str {
474 let (name, _) = &self.rule_names[usize::from(ridx)];
475 name.as_str()
476 }
477
478 pub fn rule_name_span(&self, ridx: RIdx<StorageT>) -> Span {
480 let (_, span) = self.rule_names[usize::from(ridx)];
481 span
482 }
483
484 pub fn implicit_rule(&self) -> Option<RIdx<StorageT>> {
486 self.implicit_rule
487 }
488
489 pub fn rule_idx(&self, n: &str) -> Option<RIdx<StorageT>> {
491 self.rule_names
492 .iter()
493 .position(|(x, _)| x == n)
494 .map(|x| RIdx(x.as_()))
497 }
498
499 pub fn start_rule_idx(&self) -> RIdx<StorageT> {
502 self.prod_to_rule(self.start_prod)
503 }
504
505 pub fn tokens_len(&self) -> TIdx<StorageT> {
507 self.tokens_len
508 }
509
510 pub fn iter_tidxs(&self) -> impl Iterator<Item = TIdx<StorageT>> {
513 Box::new((0..usize::from(self.tokens_len())).map(|x| TIdx(x.as_())))
517 }
518
519 pub fn eof_token_idx(&self) -> TIdx<StorageT> {
521 self.eof_token_idx
522 }
523
524 pub fn token_name(&self, tidx: TIdx<StorageT>) -> Option<&str> {
527 self.token_names[usize::from(tidx)]
528 .as_ref()
529 .map(|(_, x)| x.as_str())
530 }
531
532 pub fn token_precedence(&self, tidx: TIdx<StorageT>) -> Option<Precedence> {
535 self.token_precs[usize::from(tidx)]
536 }
537
538 pub fn token_epp(&self, tidx: TIdx<StorageT>) -> Option<&str> {
541 self.token_epp[usize::from(tidx)].as_deref()
542 }
543
544 pub fn token_span(&self, tidx: TIdx<StorageT>) -> Option<Span> {
550 self.token_names[usize::from(tidx)]
551 .as_ref()
552 .map(|(span, _)| *span)
553 }
554
555 pub fn action(&self, pidx: PIdx<StorageT>) -> &Option<String> {
557 &self.actions[usize::from(pidx)]
558 }
559
560 pub fn action_span(&self, pidx: PIdx<StorageT>) -> Option<Span> {
561 self.action_spans[usize::from(pidx)]
562 }
563
564 pub fn actiontype(&self, ridx: RIdx<StorageT>) -> &Option<String> {
565 &self.actiontypes[usize::from(ridx)]
566 }
567
568 pub fn parse_param(&self) -> &Option<(String, String)> {
569 &self.parse_param
570 }
571
572 pub fn parse_generics(&self) -> &Option<String> {
573 &self.parse_generics
574 }
575
576 pub fn programs(&self) -> &Option<String> {
578 &self.programs
579 }
580
581 pub fn tokens_map(&self) -> HashMap<&str, TIdx<StorageT>> {
584 let mut m = HashMap::with_capacity(usize::from(self.tokens_len) - 1);
585 for tidx in self.iter_tidxs() {
586 if let Some((_, n)) = self.token_names[usize::from(tidx)].as_ref() {
587 m.insert(&**n, tidx);
588 }
589 }
590 m
591 }
592
593 pub fn token_idx(&self, n: &str) -> Option<TIdx<StorageT>> {
595 self.token_names
596 .iter()
597 .position(|x| x.as_ref().is_some_and(|(_, x)| x == n))
598 .map(|x| TIdx(x.as_()))
601 }
602
603 pub fn avoid_insert(&self, tidx: TIdx<StorageT>) -> bool {
605 if let Some(ai) = &self.avoid_insert {
606 ai.get(usize::from(tidx)).unwrap()
607 } else {
608 false
609 }
610 }
611
612 pub fn expect(&self) -> Option<usize> {
614 self.expect
615 }
616
617 pub fn expectrr(&self) -> Option<usize> {
619 self.expectrr
620 }
621
622 pub fn has_path(&self, from: RIdx<StorageT>, to: RIdx<StorageT>) -> bool {
625 let mut seen = vec![];
626 seen.resize(usize::from(self.rules_len()), false);
627 let mut todo = vec![];
628 todo.resize(usize::from(self.rules_len()), false);
629 todo[usize::from(from)] = true;
630 loop {
631 let mut empty = true;
632 for ridx in self.iter_rules() {
633 if !todo[usize::from(ridx)] {
634 continue;
635 }
636 seen[usize::from(ridx)] = true;
637 todo[usize::from(ridx)] = false;
638 empty = false;
639 for pidx in self.rule_to_prods(ridx).iter() {
640 for sym in self.prod(*pidx) {
641 if let Symbol::Rule(p_ridx) = *sym {
642 if p_ridx == to {
643 return true;
644 }
645 if !seen[usize::from(p_ridx)] {
646 todo[usize::from(p_ridx)] = true;
647 }
648 }
649 }
650 }
651 }
652 if empty {
653 return false;
654 }
655 }
656 }
657
658 pub fn pp_prod(&self, pidx: PIdx<StorageT>) -> String {
660 let mut sprod = String::new();
661 let ridx = self.prod_to_rule(pidx);
662 sprod.push_str(self.rule_name_str(ridx));
663 sprod.push(':');
664 for sym in self.prod(pidx) {
665 let s = match sym {
666 Symbol::Token(tidx) => self.token_name(*tidx).unwrap(),
667 Symbol::Rule(ridx) => self.rule_name_str(*ridx),
668 };
669 write!(sprod, " \"{}\"", s).ok();
670 }
671 sprod
672 }
673
674 pub fn sentence_generator<F>(&self, token_cost: F) -> SentenceGenerator<'_, StorageT>
679 where
680 F: Fn(TIdx<StorageT>) -> u8,
681 {
682 SentenceGenerator::new(self, token_cost)
683 }
684
685 pub fn firsts(&self) -> YaccFirsts<StorageT> {
687 YaccFirsts::new(self)
688 }
689
690 pub fn follows(&self) -> YaccFollows<StorageT> {
692 YaccFollows::new(self)
693 }
694}
695
696pub struct SentenceGenerator<'a, StorageT> {
717 grm: &'a YaccGrammar<StorageT>,
718 rule_min_costs: RefCell<Option<Vec<u16>>>,
719 rule_max_costs: RefCell<Option<Vec<u16>>>,
720 token_costs: Vec<u8>,
721}
722
723impl<'a, StorageT: 'static + PrimInt + Unsigned> SentenceGenerator<'a, StorageT>
724where
725 usize: AsPrimitive<StorageT>,
726{
727 fn new<F>(grm: &'a YaccGrammar<StorageT>, token_cost: F) -> Self
728 where
729 F: Fn(TIdx<StorageT>) -> u8,
730 {
731 let mut token_costs = Vec::with_capacity(usize::from(grm.tokens_len()));
732 for tidx in grm.iter_tidxs() {
733 token_costs.push(token_cost(tidx));
734 }
735 SentenceGenerator {
736 grm,
737 token_costs,
738 rule_min_costs: RefCell::new(None),
739 rule_max_costs: RefCell::new(None),
740 }
741 }
742
743 pub fn min_sentence_cost(&self, ridx: RIdx<StorageT>) -> u16 {
747 self.rule_min_costs
748 .borrow_mut()
749 .get_or_insert_with(|| rule_min_costs(self.grm, &self.token_costs))[usize::from(ridx)]
750 }
751
752 pub fn max_sentence_cost(&self, ridx: RIdx<StorageT>) -> Option<u16> {
756 let v = self
757 .rule_max_costs
758 .borrow_mut()
759 .get_or_insert_with(|| rule_max_costs(self.grm, &self.token_costs))[usize::from(ridx)];
760 if v == u16::MAX { None } else { Some(v) }
761 }
762
763 pub fn min_sentence(&self, ridx: RIdx<StorageT>) -> Vec<TIdx<StorageT>> {
766 let cheapest_prod = |p_ridx: RIdx<StorageT>| -> PIdx<StorageT> {
767 let mut low_sc = None;
768 let mut low_idx = None;
769 for &pidx in self.grm.rule_to_prods(p_ridx).iter() {
770 let mut sc = 0;
771 for sym in self.grm.prod(pidx).iter() {
772 sc += match *sym {
773 Symbol::Rule(i) => self.min_sentence_cost(i),
774 Symbol::Token(i) => u16::from(self.token_costs[usize::from(i)]),
775 };
776 }
777 if low_sc.is_none() || Some(sc) < low_sc {
778 low_sc = Some(sc);
779 low_idx = Some(pidx);
780 }
781 }
782 low_idx.unwrap()
783 };
784
785 let mut s = vec![];
786 let mut st = vec![(cheapest_prod(ridx), 0)];
787 while let Some((pidx, sym_idx)) = st.pop() {
788 let prod = self.grm.prod(pidx);
789 for (sidx, sym) in prod.iter().enumerate().skip(sym_idx) {
790 match sym {
791 Symbol::Rule(s_ridx) => {
792 st.push((pidx, sidx + 1));
793 st.push((cheapest_prod(*s_ridx), 0));
794 }
795 Symbol::Token(s_tidx) => {
796 s.push(*s_tidx);
797 }
798 }
799 }
800 }
801 s
802 }
803
804 pub fn min_sentences(&self, ridx: RIdx<StorageT>) -> Vec<Vec<TIdx<StorageT>>> {
806 let cheapest_prods = |p_ridx: RIdx<StorageT>| -> Vec<PIdx<StorageT>> {
807 let mut low_sc = None;
808 let mut low_idxs = vec![];
809 for &pidx in self.grm.rule_to_prods(p_ridx).iter() {
810 let mut sc = 0;
811 for sym in self.grm.prod(pidx).iter() {
812 sc += match *sym {
813 Symbol::Rule(s_ridx) => self.min_sentence_cost(s_ridx),
814 Symbol::Token(s_tidx) => u16::from(self.token_costs[usize::from(s_tidx)]),
815 };
816 }
817 if low_sc.is_none() || Some(sc) <= low_sc {
818 if Some(sc) < low_sc {
819 low_idxs.clear();
820 }
821 low_sc = Some(sc);
822 low_idxs.push(pidx);
823 }
824 }
825 low_idxs
826 };
827
828 let mut sts = Vec::new(); for pidx in cheapest_prods(ridx) {
830 let prod = self.grm.prod(pidx);
831 if prod.is_empty() {
832 sts.push(vec![]);
833 continue;
834 }
835
836 let mut ms = Vec::with_capacity(prod.len());
847 for sym in prod {
848 match *sym {
849 Symbol::Rule(s_ridx) => ms.push(self.min_sentences(s_ridx)),
850 Symbol::Token(s_tidx) => ms.push(vec![vec![s_tidx]]),
851 }
852 }
853
854 let mut todo = vec![0; prod.len()];
879 let mut cur = Vec::new();
880 'b: loop {
881 for i in 0..todo.len() {
882 cur.extend(&ms[i][todo[i]]);
883 }
884 sts.push(std::mem::take(&mut cur));
885
886 let mut j = todo.len() - 1;
887 loop {
888 if todo[j] + 1 == ms[j].len() {
889 if j == 0 {
890 break 'b;
891 }
892 todo[j] = 0;
893 j -= 1;
894 } else {
895 todo[j] += 1;
896 break;
897 }
898 }
899 }
900 }
901 sts
902 }
903}
904
905fn rule_min_costs<StorageT: 'static + PrimInt + Unsigned>(
908 grm: &YaccGrammar<StorageT>,
909 token_costs: &[u8],
910) -> Vec<u16>
911where
912 usize: AsPrimitive<StorageT>,
913{
914 let mut costs = vec![0; usize::from(grm.rules_len())];
937 let mut done = vec![false; usize::from(grm.rules_len())];
938 loop {
939 let mut all_done = true;
940 for i in 0..done.len() {
941 if done[i] {
942 continue;
943 }
944 all_done = false;
945 let mut ls_cmplt = None; let mut ls_noncmplt = None; for pidx in grm.rule_to_prods(RIdx(i.as_())).iter() {
951 let mut c: u16 = 0; let mut cmplt = true;
953 for sym in grm.prod(*pidx) {
954 let sc = match *sym {
955 Symbol::Token(tidx) => u16::from(token_costs[usize::from(tidx)]),
956 Symbol::Rule(ridx) => {
957 if !done[usize::from(ridx)] {
958 cmplt = false;
959 }
960 costs[usize::from(ridx)]
961 }
962 };
963 c = c
964 .checked_add(sc)
965 .expect("Overflow occurred when calculating rule costs");
966 }
967 if cmplt && (ls_cmplt.is_none() || Some(c) < ls_cmplt) {
968 ls_cmplt = Some(c);
969 } else if !cmplt && (ls_noncmplt.is_none() || Some(c) < ls_noncmplt) {
970 ls_noncmplt = Some(c);
971 }
972 }
973 if let Some(low_cmplt) = ls_cmplt
974 && (ls_noncmplt.is_none() || ls_cmplt < ls_noncmplt)
975 {
976 debug_assert!(low_cmplt >= costs[i]);
977 costs[i] = low_cmplt;
978 done[i] = true;
979 } else if let Some(ls_noncmplt) = ls_noncmplt {
980 debug_assert!(ls_noncmplt >= costs[i]);
981 costs[i] = ls_noncmplt;
982 }
983 }
984 if all_done {
985 debug_assert!(done.iter().all(|x| *x));
986 break;
987 }
988 }
989 costs
990}
991
992fn rule_max_costs<StorageT: 'static + PrimInt + Unsigned>(
996 grm: &YaccGrammar<StorageT>,
997 token_costs: &[u8],
998) -> Vec<u16>
999where
1000 usize: AsPrimitive<StorageT>,
1001{
1002 let mut done = vec![false; usize::from(grm.rules_len())];
1003 let mut costs = vec![0; usize::from(grm.rules_len())];
1004
1005 for ridx in grm.iter_rules() {
1007 if grm.has_path(ridx, ridx) {
1009 costs[usize::from(ridx)] = u16::MAX;
1010 done[usize::from(ridx)] = true;
1011 }
1012 }
1013
1014 loop {
1015 let mut all_done = true;
1016 for i in 0..done.len() {
1017 if done[i] {
1018 continue;
1019 }
1020 all_done = false;
1021 let mut hs_cmplt = None; let mut hs_noncmplt = None; 'a: for pidx in grm.rule_to_prods(RIdx(i.as_())).iter() {
1027 let mut c: u16 = 0; let mut cmplt = true;
1029 for sym in grm.prod(*pidx) {
1030 let sc = match *sym {
1031 Symbol::Token(s_tidx) => u16::from(token_costs[usize::from(s_tidx)]),
1032 Symbol::Rule(s_ridx) => {
1033 if costs[usize::from(s_ridx)] == u16::MAX {
1034 hs_cmplt = Some(u16::MAX);
1037 break 'a;
1038 }
1039 if !done[usize::from(s_ridx)] {
1040 cmplt = false;
1041 }
1042 costs[usize::from(s_ridx)]
1043 }
1044 };
1045 c = c
1046 .checked_add(sc)
1047 .expect("Overflow occurred when calculating rule costs");
1048 if c == u16::MAX {
1049 panic!("Unable to represent cost in 64 bits.");
1050 }
1051 }
1052 if cmplt && (hs_cmplt.is_none() || Some(c) > hs_cmplt) {
1053 hs_cmplt = Some(c);
1054 } else if !cmplt && (hs_noncmplt.is_none() || Some(c) > hs_noncmplt) {
1055 hs_noncmplt = Some(c);
1056 }
1057 }
1058 if let Some(high_cmplt) = hs_cmplt
1059 && (hs_noncmplt.is_none() || hs_cmplt > hs_noncmplt)
1060 {
1061 debug_assert!(high_cmplt >= costs[i]);
1062 costs[i] = high_cmplt;
1063 done[i] = true;
1064 } else if let Some(hs_noncmplt) = hs_noncmplt {
1065 debug_assert!(hs_noncmplt >= costs[i]);
1066 costs[i] = hs_noncmplt;
1067 }
1068 }
1069 if all_done {
1070 debug_assert!(done.iter().all(|x| *x));
1071 break;
1072 }
1073 }
1074 costs
1075}
1076
1077#[cfg(test)]
1078mod test {
1079 use super::{
1080 super::{AssocKind, Precedence, YaccGrammar, YaccKind, YaccOriginalActionKind},
1081 IMPLICIT_RULE, IMPLICIT_START_RULE, rule_max_costs, rule_min_costs,
1082 };
1083 use crate::{PIdx, RIdx, Span, Symbol, TIdx};
1084 use std::collections::HashMap;
1085 use std::str::FromStr;
1086
1087 macro_rules! bslice {
1088 () => (
1089 ::Vec::new().into_boxed_slice()
1090 );
1091 ($elem:expr; $n:expr) => (
1092 ::vec::from_elem($elem, $n).into_boxed_slice()
1093 );
1094 ($($x:expr),+ $(,)?) => (
1095 <[_]>::into_vec(
1096 Box::new([$($x),+])
1097 ).into_boxed_slice()
1098 );
1099 }
1100
1101 #[test]
1102 fn test_minimal() {
1103 let grm = YaccGrammar::new(
1104 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1105 "%start R %token T %% R: 'T';",
1106 )
1107 .unwrap();
1108
1109 assert_eq!(grm.start_prod, PIdx(1));
1110 assert_eq!(grm.implicit_rule(), None);
1111 grm.rule_idx("^").unwrap();
1112 grm.rule_idx("R").unwrap();
1113 grm.token_idx("T").unwrap();
1114
1115 assert_eq!(&*grm.rules_prods, &[bslice![PIdx(1)], bslice![PIdx(0)]]);
1116 let start_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("^").unwrap())][0]);
1117 assert_eq!(*start_prod, [Symbol::Rule(grm.rule_idx("R").unwrap())]);
1118 let r_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("R").unwrap())][0]);
1119 assert_eq!(*r_prod, [Symbol::Token(grm.token_idx("T").unwrap())]);
1120 assert_eq!(&*grm.prods_rules, &[RIdx(1), RIdx(0)]);
1121
1122 assert_eq!(
1123 grm.tokens_map(),
1124 [("T", TIdx(0))]
1125 .iter()
1126 .cloned()
1127 .collect::<HashMap<&str, TIdx<_>>>()
1128 );
1129 assert_eq!(grm.iter_rules().collect::<Vec<_>>(), vec![RIdx(0), RIdx(1)]);
1130 }
1131
1132 #[test]
1133 fn test_rule_ref() {
1134 let grm = YaccGrammar::new(
1135 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1136 "%start R %token T %% R : S; S: 'T';",
1137 )
1138 .unwrap();
1139
1140 grm.rule_idx("^").unwrap();
1141 grm.rule_idx("R").unwrap();
1142 grm.rule_idx("S").unwrap();
1143 grm.token_idx("T").unwrap();
1144 assert!(grm.token_name(grm.eof_token_idx()).is_none());
1145
1146 assert_eq!(
1147 &*grm.rules_prods,
1148 &[bslice![PIdx(2)], bslice![PIdx(0)], bslice![PIdx(1)]]
1149 );
1150 let start_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("^").unwrap())][0]);
1151 assert_eq!(*start_prod, [Symbol::Rule(grm.rule_idx("R").unwrap())]);
1152 let r_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("R").unwrap())][0]);
1153 assert_eq!(r_prod.len(), 1);
1154 assert_eq!(r_prod[0], Symbol::Rule(grm.rule_idx("S").unwrap()));
1155 let s_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("S").unwrap())][0]);
1156 assert_eq!(s_prod.len(), 1);
1157 assert_eq!(s_prod[0], Symbol::Token(grm.token_idx("T").unwrap()));
1158 }
1159
1160 #[test]
1161 #[rustfmt::skip]
1162 fn test_long_prod() {
1163 let grm = YaccGrammar::new(
1164 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1165 "%start R %token T1 T2 %% R : S 'T1' S; S: 'T2';"
1166 ).unwrap();
1167
1168 grm.rule_idx("^").unwrap();
1169 grm.rule_idx("R").unwrap();
1170 grm.rule_idx("S").unwrap();
1171 grm.token_idx("T1").unwrap();
1172 grm.token_idx("T2").unwrap();
1173
1174 assert_eq!(&*grm.rules_prods, &[bslice![PIdx(2)],
1175 bslice![PIdx(0)],
1176 bslice![PIdx(1)]]);
1177 assert_eq!(&*grm.prods_rules, &[RIdx(1),
1178 RIdx(2),
1179 RIdx(0)]);
1180 let start_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("^").unwrap())][0]);
1181 assert_eq!(*start_prod, [Symbol::Rule(grm.rule_idx("R").unwrap())]);
1182 let r_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("R").unwrap())][0]);
1183 assert_eq!(r_prod.len(), 3);
1184 assert_eq!(r_prod[0], Symbol::Rule(grm.rule_idx("S").unwrap()));
1185 assert_eq!(r_prod[1], Symbol::Token(grm.token_idx("T1").unwrap()));
1186 assert_eq!(r_prod[2], Symbol::Rule(grm.rule_idx("S").unwrap()));
1187 let s_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("S").unwrap())][0]);
1188 assert_eq!(s_prod.len(), 1);
1189 assert_eq!(s_prod[0], Symbol::Token(grm.token_idx("T2").unwrap()));
1190 }
1191
1192 #[test]
1193 fn test_prods_rules() {
1194 let grm = YaccGrammar::new(
1195 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1196 "
1197 %start A
1198 %%
1199 A: B
1200 | C;
1201 B: 'x';
1202 C: 'y'
1203 | 'z';
1204 ",
1205 )
1206 .unwrap();
1207
1208 assert_eq!(
1209 &*grm.prods_rules,
1210 &[RIdx(1), RIdx(1), RIdx(2), RIdx(3), RIdx(3), RIdx(0)]
1211 );
1212 }
1213
1214 #[test]
1215 #[rustfmt::skip]
1216 fn test_left_right_nonassoc_precs() {
1217 let grm = YaccGrammar::new(
1218 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1219 "
1220 %start Expr
1221 %right '='
1222 %left '+' '-'
1223 %left '/'
1224 %left '*'
1225 %nonassoc '~'
1226 %%
1227 Expr : Expr '=' Expr
1228 | Expr '+' Expr
1229 | Expr '-' Expr
1230 | Expr '/' Expr
1231 | Expr '*' Expr
1232 | Expr '~' Expr
1233 | 'id' ;
1234 ").unwrap();
1235
1236 assert_eq!(grm.prod_precs.len(), 8);
1237 assert_eq!(grm.prod_precs[0].unwrap(), Precedence{level: 0, kind: AssocKind::Right});
1238 assert_eq!(grm.prod_precs[1].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1239 assert_eq!(grm.prod_precs[2].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1240 assert_eq!(grm.prod_precs[3].unwrap(), Precedence{level: 2, kind: AssocKind::Left});
1241 assert_eq!(grm.prod_precs[4].unwrap(), Precedence{level: 3, kind: AssocKind::Left});
1242 assert_eq!(grm.prod_precs[5].unwrap(), Precedence{level: 4, kind: AssocKind::Nonassoc});
1243 assert!(grm.prod_precs[6].is_none());
1244 assert_eq!(grm.prod_precs[7], None);
1245 }
1246
1247 #[test]
1248 #[rustfmt::skip]
1249 fn test_prec_override() {
1250 let grm = YaccGrammar::new(
1251 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1252 "
1253 %start expr
1254 %left '+' '-'
1255 %left '*' '/'
1256 %%
1257 expr : expr '+' expr
1258 | expr '-' expr
1259 | expr '*' expr
1260 | expr '/' expr
1261 | '-' expr %prec '*'
1262 | 'id' ;
1263 "
1264 ).unwrap();
1265 assert_eq!(grm.prod_precs.len(), 7);
1266 assert_eq!(grm.prod_precs[0].unwrap(), Precedence{level: 0, kind: AssocKind::Left});
1267 assert_eq!(grm.prod_precs[1].unwrap(), Precedence{level: 0, kind: AssocKind::Left});
1268 assert_eq!(grm.prod_precs[2].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1269 assert_eq!(grm.prod_precs[3].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1270 assert_eq!(grm.prod_precs[4].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1271 assert!(grm.prod_precs[5].is_none());
1272 assert_eq!(grm.prod_precs[6], None);
1273 }
1274
1275 #[test]
1276 #[rustfmt::skip]
1277 fn test_implicit_tokens_rewrite() {
1278 let grm = YaccGrammar::new(
1279 YaccKind::Eco,
1280 "
1281 %implicit_tokens ws1 ws2
1282 %start S
1283 %%
1284 S: 'a' | T;
1285 T: 'c' |;
1286 "
1287 ).unwrap();
1288
1289 assert_eq!(grm.prod_precs.len(), 9);
1297
1298 let itfs_rule_idx = grm.rule_idx(IMPLICIT_START_RULE).unwrap();
1299 assert_eq!(grm.rules_prods[usize::from(itfs_rule_idx)].len(), 1);
1300
1301 let itfs_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(itfs_rule_idx)][0])];
1302 assert_eq!(itfs_prod1.len(), 2);
1303 assert_eq!(itfs_prod1[0], Symbol::Rule(grm.rule_idx(IMPLICIT_RULE).unwrap()));
1304 assert_eq!(itfs_prod1[1], Symbol::Rule(grm.rule_idx("S").unwrap()));
1305
1306 let s_rule_idx = grm.rule_idx("S").unwrap();
1307 assert_eq!(grm.rules_prods[usize::from(s_rule_idx)].len(), 2);
1308
1309 let s_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(s_rule_idx)][0])];
1310 assert_eq!(s_prod1.len(), 2);
1311 assert_eq!(s_prod1[0], Symbol::Token(grm.token_idx("a").unwrap()));
1312 assert_eq!(s_prod1[1], Symbol::Rule(grm.rule_idx(IMPLICIT_RULE).unwrap()));
1313
1314 let s_prod2 = &grm.prods[usize::from(grm.rules_prods[usize::from(s_rule_idx)][1])];
1315 assert_eq!(s_prod2.len(), 1);
1316 assert_eq!(s_prod2[0], Symbol::Rule(grm.rule_idx("T").unwrap()));
1317
1318 let t_rule_idx = grm.rule_idx("T").unwrap();
1319 assert_eq!(grm.rules_prods[usize::from(s_rule_idx)].len(), 2);
1320
1321 let t_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(t_rule_idx)][0])];
1322 assert_eq!(t_prod1.len(), 2);
1323 assert_eq!(t_prod1[0], Symbol::Token(grm.token_idx("c").unwrap()));
1324 assert_eq!(t_prod1[1], Symbol::Rule(grm.rule_idx(IMPLICIT_RULE).unwrap()));
1325
1326 let t_prod2 = &grm.prods[usize::from(grm.rules_prods[usize::from(t_rule_idx)][1])];
1327 assert_eq!(t_prod2.len(), 0);
1328
1329 assert_eq!(Some(grm.rule_idx(IMPLICIT_RULE).unwrap()), grm.implicit_rule());
1330 let i_rule_idx = grm.rule_idx(IMPLICIT_RULE).unwrap();
1331 assert_eq!(grm.rules_prods[usize::from(i_rule_idx)].len(), 3);
1332 let i_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(i_rule_idx)][0])];
1333 let i_prod2 = &grm.prods[usize::from(grm.rules_prods[usize::from(i_rule_idx)][1])];
1334 assert_eq!(i_prod1.len(), 2);
1335 assert_eq!(i_prod2.len(), 2);
1336 let cnd1 = bslice![
1339 Symbol::Token(grm.token_idx("ws1").unwrap()),
1340 Symbol::Rule(grm.implicit_rule().unwrap()),
1341 ];
1342 let cnd2 = bslice![
1343 Symbol::Token(grm.token_idx("ws2").unwrap()),
1344 Symbol::Rule(grm.implicit_rule().unwrap()),
1345 ];
1346 assert!((*i_prod1 == cnd1 && *i_prod2 == cnd2) || (*i_prod1 == cnd2 && *i_prod2 == cnd1));
1347 let i_prod3 = &grm.prods[usize::from(grm.rules_prods[usize::from(i_rule_idx)][2])];
1348 assert_eq!(i_prod3.len(), 0);
1349 }
1350
1351 #[test]
1352 #[rustfmt::skip]
1353 fn test_has_path() {
1354 let grm = YaccGrammar::new(
1355 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1356 "
1357 %start A
1358 %%
1359 A: B;
1360 B: B 'x' | C;
1361 C: C 'y' | ;
1362 "
1363 ).unwrap();
1364
1365 let a_ridx = grm.rule_idx("A").unwrap();
1366 let b_ridx = grm.rule_idx("B").unwrap();
1367 let c_ridx = grm.rule_idx("C").unwrap();
1368 assert!(grm.has_path(a_ridx, b_ridx));
1369 assert!(grm.has_path(a_ridx, c_ridx));
1370 assert!(grm.has_path(b_ridx, b_ridx));
1371 assert!(grm.has_path(b_ridx, c_ridx));
1372 assert!(grm.has_path(c_ridx, c_ridx));
1373 assert!(!grm.has_path(a_ridx, a_ridx));
1374 assert!(!grm.has_path(b_ridx, a_ridx));
1375 assert!(!grm.has_path(c_ridx, a_ridx));
1376 }
1377
1378 #[test]
1379 #[rustfmt::skip]
1380 fn test_rule_min_costs() {
1381 let grm = YaccGrammar::new(
1382 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1383 "
1384 %start A
1385 %%
1386 A: A B | ;
1387 B: C | D | E;
1388 C: 'x' B | 'x';
1389 D: 'y' B | 'y' 'z';
1390 E: 'x' A | 'x' 'y';
1391 "
1392 ).unwrap();
1393
1394 let scores = rule_min_costs(&grm, &[1, 1, 1]);
1395 assert_eq!(scores[usize::from(grm.rule_idx("A").unwrap())], 0);
1396 assert_eq!(scores[usize::from(grm.rule_idx("B").unwrap())], 1);
1397 assert_eq!(scores[usize::from(grm.rule_idx("C").unwrap())], 1);
1398 assert_eq!(scores[usize::from(grm.rule_idx("D").unwrap())], 2);
1399 assert_eq!(scores[usize::from(grm.rule_idx("E").unwrap())], 1);
1400 }
1401
1402 #[test]
1403 fn test_min_sentences() {
1404 let grm = YaccGrammar::new(
1405 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1406 "
1407 %start A
1408 %%
1409 A: A B | ;
1410 B: C | D;
1411 C: 'x' B | 'x';
1412 D: 'y' B | 'y' 'z';
1413 ",
1414 )
1415 .unwrap();
1416
1417 let sg = grm.sentence_generator(|_| 1);
1418
1419 let find = |nt_name: &str, str_cnds: Vec<Vec<&str>>| {
1420 let cnds = str_cnds
1421 .iter()
1422 .map(|x| {
1423 x.iter()
1424 .map(|y| grm.token_idx(y).unwrap())
1425 .collect::<Vec<_>>()
1426 })
1427 .collect::<Vec<_>>();
1428
1429 let ms = sg.min_sentence(grm.rule_idx(nt_name).unwrap());
1430 if !cnds.iter().any(|x| x == &ms) {
1431 panic!("{:?} doesn't have any matches in {:?}", ms, str_cnds);
1432 }
1433
1434 let min_sts = sg.min_sentences(grm.rule_idx(nt_name).unwrap());
1435 assert_eq!(cnds.len(), min_sts.len());
1436 for ms in min_sts {
1437 if !cnds.iter().any(|x| x == &ms) {
1438 panic!("{:?} doesn't have any matches in {:?}", ms, str_cnds);
1439 }
1440 }
1441 };
1442
1443 find("A", vec![vec![]]);
1444 find("B", vec![vec!["x"]]);
1445 find("C", vec![vec!["x"]]);
1446 find("D", vec![vec!["y", "x"], vec!["y", "z"]]);
1447 }
1448
1449 #[test]
1450 #[rustfmt::skip]
1451 fn test_rule_max_costs1() {
1452 let grm = YaccGrammar::new(
1453 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1454 "
1455 %start A
1456 %%
1457 A: A B | ;
1458 B: C | D | E;
1459 C: 'x' B | 'x';
1460 D: 'y' B | 'y' 'z';
1461 E: 'x' A | 'x' 'y';
1462 "
1463 ).unwrap();
1464
1465 let scores = rule_max_costs(&grm, &[1, 1, 1]);
1466 assert_eq!(scores[usize::from(grm.rule_idx("A").unwrap())], u16::MAX);
1467 assert_eq!(scores[usize::from(grm.rule_idx("B").unwrap())], u16::MAX);
1468 assert_eq!(scores[usize::from(grm.rule_idx("C").unwrap())], u16::MAX);
1469 assert_eq!(scores[usize::from(grm.rule_idx("D").unwrap())], u16::MAX);
1470 assert_eq!(scores[usize::from(grm.rule_idx("E").unwrap())], u16::MAX);
1471 }
1472
1473 #[test]
1474 #[rustfmt::skip]
1475 fn test_rule_max_costs2() {
1476 let grm = YaccGrammar::new(
1477 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1478 "
1479 %start A
1480 %%
1481 A: A B | B;
1482 B: C | D;
1483 C: 'x' 'y' | 'x';
1484 D: 'y' 'x' | 'y' 'x' 'z';
1485 "
1486 ).unwrap();
1487
1488 let scores = rule_max_costs(&grm, &[1, 1, 1]);
1489 assert_eq!(scores[usize::from(grm.rule_idx("A").unwrap())], u16::MAX);
1490 assert_eq!(scores[usize::from(grm.rule_idx("B").unwrap())], 3);
1491 assert_eq!(scores[usize::from(grm.rule_idx("C").unwrap())], 2);
1492 assert_eq!(scores[usize::from(grm.rule_idx("D").unwrap())], 3);
1493 }
1494
1495 #[test]
1496 fn test_out_of_order_productions() {
1497 let grm = YaccGrammar::new(
1499 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1500 "
1501 %start S
1502 %%
1503 S: A 'c' 'd'
1504 | B 'c' 'e';
1505 A: 'a';
1506 B: 'a'
1507 | 'b';
1508 A: 'b';
1509 ",
1510 )
1511 .unwrap();
1512
1513 assert_eq!(
1514 &*grm.prods_rules,
1515 &[
1516 RIdx(1),
1517 RIdx(1),
1518 RIdx(2),
1519 RIdx(3),
1520 RIdx(3),
1521 RIdx(2),
1522 RIdx(0)
1523 ]
1524 );
1525 }
1526
1527 #[test]
1528 fn test_token_spans() {
1529 let src = "%%\nAB: 'a' | 'foo';";
1530 let grm =
1531 YaccGrammar::new(YaccKind::Original(YaccOriginalActionKind::NoAction), src).unwrap();
1532 let token_map = grm.tokens_map();
1533 let a_tidx = token_map.get("a");
1534 let foo_tidx = token_map.get("foo");
1535 let a_span = grm.token_span(*a_tidx.unwrap()).unwrap();
1536 let foo_span = grm.token_span(*foo_tidx.unwrap()).unwrap();
1537 let ab_span = grm.rule_name_span(grm.rule_idx("AB").unwrap());
1538 assert_eq!(a_span, Span::new(8, 9));
1539 assert_eq!(foo_span, Span::new(14, 17));
1540 assert_eq!(ab_span, Span::new(3, 5));
1541 assert_eq!(&src[a_span.start()..a_span.end()], "a");
1542 assert_eq!(&src[foo_span.start()..foo_span.end()], "foo");
1543 assert_eq!(&src[ab_span.start()..ab_span.end()], "AB");
1544 }
1545
1546 #[test]
1547 fn token_span_issue296() {
1548 let src = "%%
1549 S: | AB;
1550 A: 'a' 'b';
1551 B: 'b' 'c';
1552 AB: A AB | B ';' AB;
1553 %%
1554 ";
1555 let grm =
1556 YaccGrammar::new(YaccKind::Original(YaccOriginalActionKind::NoAction), src).unwrap();
1557 let token_map = grm.tokens_map();
1558 let c_tidx = token_map.get("c").unwrap();
1559 assert_eq!(grm.token_name(*c_tidx), Some("c"));
1560 let c_span = grm.token_span(*c_tidx).unwrap();
1561 assert_eq!(&src[c_span.start()..c_span.end()], "c");
1562 }
1563
1564 #[test]
1565 fn test_grmtools_section_yacckinds() {
1566 let srcs = [
1567 "%grmtools{yacckind: Original(NoAction)}
1568 %%
1569 Start: ;",
1570 "%grmtools{yacckind: YaccKind::Original(GenericParseTree)}
1571 %%
1572 Start: ;",
1573 "%grmtools{yacckind: YaccKind::Original(yaccoriginalactionkind::useraction)}
1574 %actiontype ()
1575 %%
1576 Start: ;",
1577 "%grmtools{yacckind: Original(YACCOriginalActionKind::NoAction)}
1578 %%
1579 Start: ;",
1580 "%grmtools{yacckind: YaccKind::Grmtools}
1581 %%
1582 Start -> () : ;",
1583 ];
1584 for src in srcs {
1585 YaccGrammar::<u32>::from_str(src).unwrap();
1586 }
1587 }
1588
1589 #[test]
1590 fn test_grmtools_section_invalid_yacckinds() {
1591 let srcs = [
1592 "%grmtools{yacckind: Foo}",
1593 "%grmtools{yacckind: YaccKind::Foo}",
1594 "%grmtools{yacckindof: YaccKind::Grmtools}",
1595 "%grmtools{yacckindof: Grmtools}",
1596 "%grmtools{yacckindof: YaccKindFoo::Foo}",
1597 "%grmtools{yacckind: Foo::Grmtools}",
1598 "%grmtools{yacckind: YaccKind::Original}",
1599 "%grmtools{yacckind: YaccKind::OriginalFoo}",
1600 "%grmtools{yacckind: YaccKind::Original()}",
1601 "%grmtools{yacckind: YaccKind::Original(Foo)}",
1602 "%grmtools{yacckind: YaccKind::Original(YaccOriginalActionKind)}",
1603 "%grmtools{yacckind: YaccKind::Original(YaccOriginalActionKind::Foo)}",
1604 "%grmtools{yacckind: YaccKind::Original(Foo::NoActions)}",
1605 "%grmtools{yacckind: YaccKind::Original(Foo::NoActionsBar)}",
1606 ];
1607
1608 for src in srcs {
1609 let s = format!("{}\n%%\nStart();\n", src);
1610 assert!(YaccGrammar::<u32>::from_str(&s).is_err());
1611 }
1612 }
1613
1614 #[test]
1615 fn test_grmtools_section_commas() {
1616 let src = r#"
1622 %grmtools{
1623 yacckind: YaccKind::Grmtools,
1624 }
1625 %%
1626 Start -> () : ;
1627 "#;
1628 YaccGrammar::<u32>::from_str(src).unwrap();
1629 let src = r#"
1630 %grmtools{
1631 yacckind: YaccKind::Grmtools
1632 }
1633 %%
1634 Start -> () : ;
1635 "#;
1636 YaccGrammar::<u32>::from_str(src).unwrap();
1637 }
1638}