1#![allow(clippy::derive_partial_eq_without_eq)]
2use std::{cell::RefCell, collections::HashMap, fmt::Write, str::FromStr};
3
4#[cfg(feature = "bincode")]
5use bincode::{Decode, Encode};
6use num_traits::{AsPrimitive, PrimInt, Unsigned};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9use vob::Vob;
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 = "bincode", derive(Encode, Decode))]
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 = "bincode", derive(Encode, Decode))]
35pub enum AssocKind {
36 Left,
37 Right,
38 Nonassoc,
39}
40
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44#[cfg_attr(feature = "bincode", derive(Encode))]
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
106#[cfg(feature = "bincode")]
117impl<StorageT, __Context> Decode<__Context> for YaccGrammar<StorageT>
118where
119 StorageT: Decode<__Context> + 'static,
120{
121 fn decode<__D: bincode::de::Decoder<Context = __Context>>(
122 decoder: &mut __D,
123 ) -> Result<Self, bincode::error::DecodeError> {
124 Ok(Self {
125 rules_len: Decode::decode(decoder)?,
126 rule_names: Decode::decode(decoder)?,
127 token_names: Decode::decode(decoder)?,
128 token_precs: Decode::decode(decoder)?,
129 token_epp: Decode::decode(decoder)?,
130 tokens_len: Decode::decode(decoder)?,
131 eof_token_idx: Decode::decode(decoder)?,
132 prods_len: Decode::decode(decoder)?,
133 start_prod: Decode::decode(decoder)?,
134 prods: Decode::decode(decoder)?,
135 rules_prods: Decode::decode(decoder)?,
136 prods_rules: Decode::decode(decoder)?,
137 prod_precs: Decode::decode(decoder)?,
138 prod_spans: Decode::decode(decoder)?,
139 implicit_rule: Decode::decode(decoder)?,
140 actions: Decode::decode(decoder)?,
141 action_spans: Decode::decode(decoder)?,
142 parse_param: Decode::decode(decoder)?,
143 parse_generics: Decode::decode(decoder)?,
144 programs: Decode::decode(decoder)?,
145 actiontypes: Decode::decode(decoder)?,
146 avoid_insert: Decode::decode(decoder)?,
147 expect: Decode::decode(decoder)?,
148 expectrr: Decode::decode(decoder)?,
149 })
150 }
151}
152
153#[cfg(feature = "bincode")]
158impl<'__de, StorageT, __Context> bincode::BorrowDecode<'__de, __Context> for YaccGrammar<StorageT>
159where
160 StorageT: bincode::de::BorrowDecode<'__de, __Context> + '__de,
161{
162 fn borrow_decode<__D: ::bincode::de::BorrowDecoder<'__de, Context = __Context>>(
163 decoder: &mut __D,
164 ) -> Result<Self, bincode::error::DecodeError> {
165 Ok(Self {
166 rules_len: bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
167 rule_names: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
168 token_names: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
169 token_precs: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
170 token_epp: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
171 tokens_len: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
172 eof_token_idx: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
173 prods_len: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
174 start_prod: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
175 prods: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
176 rules_prods: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
177 prods_rules: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
178 prod_precs: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
179 prod_spans: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
180 implicit_rule: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
181 actions: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
182 action_spans: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
183 parse_param: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
184 parse_generics: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
185 programs: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
186 actiontypes: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
187 avoid_insert: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
188 expect: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
189 expectrr: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
190 })
191 }
192}
193
194impl YaccGrammar<u32> {
198 pub fn new(yk: YaccKind, s: &str) -> YaccGrammarResult<Self> {
199 YaccGrammar::new_with_storaget(yk, s)
200 }
201}
202
203impl<StorageT: 'static + PrimInt + Unsigned> FromStr for YaccGrammar<StorageT>
204where
205 usize: AsPrimitive<StorageT>,
206{
207 type Err = Vec<YaccGrammarError>;
208 fn from_str(s: &str) -> YaccGrammarResult<Self> {
209 let ast_validation = ast::ASTWithValidityInfo::from_str(s)?;
210 Self::new_from_ast_with_validity_info(&ast_validation)
211 }
212}
213
214impl<StorageT: 'static + PrimInt + Unsigned> YaccGrammar<StorageT>
215where
216 usize: AsPrimitive<StorageT>,
217{
218 pub fn new_with_storaget(yk: YaccKind, s: &str) -> YaccGrammarResult<Self> {
226 let ast_validation = ast::ASTWithValidityInfo::new(yk, s);
227 Self::new_from_ast_with_validity_info(&ast_validation)
228 }
229
230 pub fn new_from_ast_with_validity_info(
231 ast_validation: &ast::ASTWithValidityInfo,
232 ) -> YaccGrammarResult<Self> {
233 if !ast_validation.is_valid() {
234 return Err(ast_validation.errors().to_owned());
235 }
236 let ast = ast_validation.ast();
237 if ast.rules.len() > num_traits::cast(StorageT::max_value()).unwrap() {
240 panic!("StorageT is not big enough to store this grammar's rules.");
241 }
242 if ast.tokens.len() > num_traits::cast(StorageT::max_value()).unwrap() {
243 panic!("StorageT is not big enough to store this grammar's tokens.");
244 }
245 if ast.prods.len() > num_traits::cast(StorageT::max_value()).unwrap() {
246 panic!("StorageT is not big enough to store this grammar's productions.");
247 }
248 for p in &ast.prods {
249 if p.symbols.len() > num_traits::cast(StorageT::max_value()).unwrap() {
250 panic!(
251 "StorageT is not big enough to store the symbols of at least one of this grammar's productions."
252 );
253 }
254 }
255
256 let mut rule_names: Vec<(String, Span)> = Vec::with_capacity(ast.rules.len() + 1);
257
258 let mut start_rule = START_RULE.to_string();
263 while ast.rules.get(&start_rule).is_some() {
264 start_rule += START_RULE;
265 }
266 rule_names.push((start_rule.clone(), Span::new(0, 0)));
267
268 let implicit_rule;
269 let implicit_start_rule;
270 match ast_validation.yacc_kind() {
271 YaccKind::Original(_) | YaccKind::Grmtools => {
272 implicit_rule = None;
273 implicit_start_rule = None;
274 }
275 YaccKind::Eco => {
276 if ast.implicit_tokens.is_some() {
277 let mut n1 = IMPLICIT_RULE.to_string();
278 while ast.rules.get(&n1).is_some() {
279 n1 += IMPLICIT_RULE;
280 }
281 rule_names.push((n1.clone(), Span::new(0, 0)));
282 implicit_rule = Some(n1);
283 let mut n2 = IMPLICIT_START_RULE.to_string();
284 while ast.rules.get(&n2).is_some() {
285 n2 += IMPLICIT_START_RULE;
286 }
287 rule_names.push((n2.clone(), Span::new(0, 0)));
288 implicit_start_rule = Some(n2);
289 } else {
290 implicit_rule = None;
291 implicit_start_rule = None;
292 }
293 }
294 };
295
296 for (
297 k,
298 ast::Rule {
299 name: (_, name_span),
300 ..
301 },
302 ) in &ast.rules
303 {
304 rule_names.push((k.clone(), *name_span));
305 }
306 let mut rules_prods: Vec<Vec<PIdx<StorageT>>> = Vec::with_capacity(rule_names.len());
307 let mut rule_map = HashMap::<String, RIdx<StorageT>>::new();
308 for (i, (v, _)) in rule_names.iter().enumerate() {
309 rules_prods.push(Vec::new());
310 rule_map.insert(v.clone(), RIdx(i.as_()));
311 }
312
313 let mut token_names: Vec<Option<(Span, String)>> = Vec::with_capacity(ast.tokens.len() + 1);
314 let mut token_precs: Vec<Option<Precedence>> = Vec::with_capacity(ast.tokens.len() + 1);
315 let mut token_epp: Vec<Option<String>> = Vec::with_capacity(ast.tokens.len() + 1);
316 for (i, k) in ast.tokens.iter().enumerate() {
317 token_names.push(Some((ast.spans[i], k.clone())));
318 token_precs.push(ast.precs.get(k).map(|(prec, _)| prec).cloned());
319 token_epp.push(Some(
320 ast.epp.get(k).map(|(_, (s, _))| s).unwrap_or(k).clone(),
321 ));
322 }
323 let eof_token_idx = TIdx(token_names.len().as_());
324 token_names.push(None);
325 token_precs.push(None);
326 token_epp.push(None);
327 let mut token_map = HashMap::<String, TIdx<StorageT>>::new();
328 for (i, v) in token_names.iter().enumerate() {
329 if let Some((_, n)) = v.as_ref() {
330 token_map.insert(n.clone(), TIdx(i.as_()));
331 }
332 }
333
334 let mut prods = vec![None; ast.prods.len()];
338 let mut prod_precs: Vec<Option<Option<Precedence>>> = vec![None; ast.prods.len()];
339 let mut prods_rules = vec![None; ast.prods.len()];
340 let mut actions = vec![None; ast.prods.len()];
341 let mut action_spans = vec![None; ast.prods.len()];
342 let mut actiontypes = vec![None; rule_names.len()];
343 let (start_name, _) = ast.start.as_ref().unwrap();
344 for (astrulename, _) in &rule_names {
345 let ridx = rule_map[astrulename];
346 if astrulename == &start_rule {
347 rules_prods[usize::from(ridx)].push(PIdx(prods.len().as_()));
350 let start_prod = match implicit_start_rule {
351 None => {
352 vec![Symbol::Rule(rule_map[start_name])]
354 }
355 Some(ref s) => {
356 vec![Symbol::Rule(rule_map[s])]
360 }
361 };
362 prods.push(Some(start_prod));
363 prod_precs.push(Some(None));
364 prods_rules.push(Some(ridx));
365 actions.push(None);
366 continue;
367 } else if implicit_start_rule.as_ref() == Some(astrulename) {
368 rules_prods[usize::from(rule_map[astrulename])].push(PIdx(prods.len().as_()));
372 prods.push(Some(vec![
373 Symbol::Rule(rule_map[implicit_rule.as_ref().unwrap()]),
374 Symbol::Rule(rule_map[start_name]),
375 ]));
376 prod_precs.push(Some(None));
377 prods_rules.push(Some(ridx));
378 continue;
379 } else if implicit_rule.as_ref() == Some(astrulename) {
380 let implicit_prods = &mut rules_prods[usize::from(rule_map[astrulename])];
382 for (t, _) in ast.implicit_tokens.as_ref().unwrap().iter() {
384 implicit_prods.push(PIdx(prods.len().as_()));
385 prods.push(Some(vec![Symbol::Token(token_map[t]), Symbol::Rule(ridx)]));
386 prod_precs.push(Some(None));
387 prods_rules.push(Some(ridx));
388 }
389 implicit_prods.push(PIdx(prods.len().as_()));
391 prods.push(Some(vec![]));
392 prod_precs.push(Some(None));
393 prods_rules.push(Some(ridx));
394 continue;
395 } else {
396 actiontypes[usize::from(ridx)] = ast.rules[astrulename].actiont.clone();
397 }
398
399 let rule = &mut rules_prods[usize::from(ridx)];
400 for &pidx in &ast.rules[astrulename].pidxs {
401 let astprod = &ast.prods[pidx];
402 let mut prod = Vec::with_capacity(astprod.symbols.len());
403 for astsym in &astprod.symbols {
404 match *astsym {
405 ast::Symbol::Rule(ref n, _) => {
406 prod.push(Symbol::Rule(rule_map[n]));
407 }
408 ast::Symbol::Token(ref n, _) => {
409 prod.push(Symbol::Token(token_map[n]));
410 if let Some(implicit_rule) = &implicit_rule {
411 prod.push(Symbol::Rule(rule_map[implicit_rule]));
412 }
413 }
414 };
415 }
416 let mut prec = None;
417 if let Some(ref n) = astprod.precedence {
418 prec = Some(ast.precs[n]);
419 } else {
420 for astsym in astprod.symbols.iter().rev() {
421 if let ast::Symbol::Token(ref n, _) = *astsym {
422 if let Some(p) = ast.precs.get(n) {
423 prec = Some(*p);
424 }
425 break;
426 }
427 }
428 }
429 (*rule).push(PIdx(pidx.as_()));
430 prods[pidx] = Some(prod);
431 prod_precs[pidx] = Some(prec.map(|(prec, _)| prec));
432 prods_rules[pidx] = Some(ridx);
433 if let Some((s, span)) = &astprod.action {
434 actions[pidx] = Some(s.clone());
435 action_spans[pidx] = Some(*span);
436 }
437 }
438 }
439
440 let avoid_insert = if let Some(ai) = &ast.avoid_insert {
441 let mut aiv = Vob::from_elem(false, token_names.len());
442 for n in ai.keys() {
443 aiv.set(usize::from(token_map[n]), true);
444 }
445 Some(aiv)
446 } else {
447 None
448 };
449
450 assert!(!token_names.is_empty());
451 assert!(!rule_names.is_empty());
452 Ok(YaccGrammar {
453 rules_len: RIdx(rule_names.len().as_()),
454 rule_names: rule_names.into_boxed_slice(),
455 tokens_len: TIdx(token_names.len().as_()),
456 eof_token_idx,
457 token_names: token_names.into_boxed_slice(),
458 token_precs: token_precs.into_boxed_slice(),
459 token_epp: token_epp.into_boxed_slice(),
460 prods_len: PIdx(prods.len().as_()),
461 start_prod: rules_prods[usize::from(rule_map[&start_rule])][0],
462 rules_prods: rules_prods
463 .iter()
464 .map(|x| x.iter().copied().collect())
465 .collect(),
466 prods_rules: prods_rules.into_iter().map(Option::unwrap).collect(),
467 prods: prods
468 .into_iter()
469 .map(|x| x.unwrap().into_boxed_slice())
470 .collect(),
471 prod_precs: prod_precs.into_iter().map(Option::unwrap).collect(),
472 prod_spans: ast.prods.iter().map(|prod| prod.prod_span).collect(),
473 implicit_rule: implicit_rule.map(|x| rule_map[&x]),
474 actions: actions.into_boxed_slice(),
475 action_spans: action_spans.into_boxed_slice(),
476 parse_param: ast.parse_param.clone(),
477 parse_generics: ast.parse_generics.clone(),
478 programs: ast.programs.clone(),
479 avoid_insert,
480 actiontypes: actiontypes.into_boxed_slice(),
481 expect: ast.expect.map(|(n, _)| n),
482 expectrr: ast.expectrr.map(|(n, _)| n),
483 })
484 }
485
486 pub fn prods_len(&self) -> PIdx<StorageT> {
488 self.prods_len
489 }
490
491 pub fn iter_pidxs(&self) -> impl Iterator<Item = PIdx<StorageT>> {
494 Box::new((0..usize::from(self.prods_len())).map(|x| PIdx(x.as_())))
498 }
499
500 pub fn prod(&self, pidx: PIdx<StorageT>) -> &[Symbol<StorageT>] {
502 &self.prods[usize::from(pidx)]
503 }
504
505 pub fn prod_len(&self, pidx: PIdx<StorageT>) -> SIdx<StorageT> {
507 SIdx(self.prods[usize::from(pidx)].len().as_())
510 }
511
512 pub fn prod_to_rule(&self, pidx: PIdx<StorageT>) -> RIdx<StorageT> {
514 self.prods_rules[usize::from(pidx)]
515 }
516
517 pub fn prod_precedence(&self, pidx: PIdx<StorageT>) -> Option<Precedence> {
520 self.prod_precs[usize::from(pidx)]
521 }
522
523 pub fn prod_span(&self, pidx: PIdx<StorageT>) -> Span {
527 self.prod_spans[usize::from(pidx)]
528 }
529
530 pub fn start_prod(&self) -> PIdx<StorageT> {
533 self.start_prod
534 }
535
536 pub fn rules_len(&self) -> RIdx<StorageT> {
538 self.rules_len
539 }
540
541 pub fn iter_rules(&self) -> impl Iterator<Item = RIdx<StorageT>> {
544 Box::new((0..usize::from(self.rules_len())).map(|x| RIdx(x.as_())))
548 }
549
550 pub fn rule_to_prods(&self, ridx: RIdx<StorageT>) -> &[PIdx<StorageT>] {
552 &self.rules_prods[usize::from(ridx)]
553 }
554
555 #[deprecated(since = "0.13.0", note = "Please use rule_name_str instead")]
557 pub fn rule_name(&self, ridx: RIdx<StorageT>) -> &str {
558 self.rule_name_str(ridx)
559 }
560
561 pub fn rule_name_str(&self, ridx: RIdx<StorageT>) -> &str {
563 let (name, _) = &self.rule_names[usize::from(ridx)];
564 name.as_str()
565 }
566
567 pub fn rule_name_span(&self, ridx: RIdx<StorageT>) -> Span {
569 let (_, span) = self.rule_names[usize::from(ridx)];
570 span
571 }
572
573 pub fn implicit_rule(&self) -> Option<RIdx<StorageT>> {
575 self.implicit_rule
576 }
577
578 pub fn rule_idx(&self, n: &str) -> Option<RIdx<StorageT>> {
580 self.rule_names
581 .iter()
582 .position(|(x, _)| x == n)
583 .map(|x| RIdx(x.as_()))
586 }
587
588 pub fn start_rule_idx(&self) -> RIdx<StorageT> {
591 self.prod_to_rule(self.start_prod)
592 }
593
594 pub fn tokens_len(&self) -> TIdx<StorageT> {
596 self.tokens_len
597 }
598
599 pub fn iter_tidxs(&self) -> impl Iterator<Item = TIdx<StorageT>> {
602 Box::new((0..usize::from(self.tokens_len())).map(|x| TIdx(x.as_())))
606 }
607
608 pub fn eof_token_idx(&self) -> TIdx<StorageT> {
610 self.eof_token_idx
611 }
612
613 pub fn token_name(&self, tidx: TIdx<StorageT>) -> Option<&str> {
616 self.token_names[usize::from(tidx)]
617 .as_ref()
618 .map(|(_, x)| x.as_str())
619 }
620
621 pub fn token_precedence(&self, tidx: TIdx<StorageT>) -> Option<Precedence> {
624 self.token_precs[usize::from(tidx)]
625 }
626
627 pub fn token_epp(&self, tidx: TIdx<StorageT>) -> Option<&str> {
630 self.token_epp[usize::from(tidx)].as_deref()
631 }
632
633 pub fn token_span(&self, tidx: TIdx<StorageT>) -> Option<Span> {
639 self.token_names[usize::from(tidx)]
640 .as_ref()
641 .map(|(span, _)| *span)
642 }
643
644 pub fn action(&self, pidx: PIdx<StorageT>) -> &Option<String> {
646 &self.actions[usize::from(pidx)]
647 }
648
649 pub fn action_span(&self, pidx: PIdx<StorageT>) -> Option<Span> {
650 self.action_spans[usize::from(pidx)]
651 }
652
653 pub fn actiontype(&self, ridx: RIdx<StorageT>) -> &Option<String> {
654 &self.actiontypes[usize::from(ridx)]
655 }
656
657 pub fn parse_param(&self) -> &Option<(String, String)> {
658 &self.parse_param
659 }
660
661 pub fn parse_generics(&self) -> &Option<String> {
662 &self.parse_generics
663 }
664
665 pub fn programs(&self) -> &Option<String> {
667 &self.programs
668 }
669
670 pub fn tokens_map(&self) -> HashMap<&str, TIdx<StorageT>> {
673 let mut m = HashMap::with_capacity(usize::from(self.tokens_len) - 1);
674 for tidx in self.iter_tidxs() {
675 if let Some((_, n)) = self.token_names[usize::from(tidx)].as_ref() {
676 m.insert(&**n, tidx);
677 }
678 }
679 m
680 }
681
682 pub fn token_idx(&self, n: &str) -> Option<TIdx<StorageT>> {
684 self.token_names
685 .iter()
686 .position(|x| x.as_ref().is_some_and(|(_, x)| x == n))
687 .map(|x| TIdx(x.as_()))
690 }
691
692 pub fn avoid_insert(&self, tidx: TIdx<StorageT>) -> bool {
694 if let Some(ai) = &self.avoid_insert {
695 ai.get(usize::from(tidx)).unwrap()
696 } else {
697 false
698 }
699 }
700
701 pub fn expect(&self) -> Option<usize> {
703 self.expect
704 }
705
706 pub fn expectrr(&self) -> Option<usize> {
708 self.expectrr
709 }
710
711 pub fn has_path(&self, from: RIdx<StorageT>, to: RIdx<StorageT>) -> bool {
714 let mut seen = vec![];
715 seen.resize(usize::from(self.rules_len()), false);
716 let mut todo = vec![];
717 todo.resize(usize::from(self.rules_len()), false);
718 todo[usize::from(from)] = true;
719 loop {
720 let mut empty = true;
721 for ridx in self.iter_rules() {
722 if !todo[usize::from(ridx)] {
723 continue;
724 }
725 seen[usize::from(ridx)] = true;
726 todo[usize::from(ridx)] = false;
727 empty = false;
728 for pidx in self.rule_to_prods(ridx).iter() {
729 for sym in self.prod(*pidx) {
730 if let Symbol::Rule(p_ridx) = *sym {
731 if p_ridx == to {
732 return true;
733 }
734 if !seen[usize::from(p_ridx)] {
735 todo[usize::from(p_ridx)] = true;
736 }
737 }
738 }
739 }
740 }
741 if empty {
742 return false;
743 }
744 }
745 }
746
747 pub fn pp_prod(&self, pidx: PIdx<StorageT>) -> String {
749 let mut sprod = String::new();
750 let ridx = self.prod_to_rule(pidx);
751 sprod.push_str(self.rule_name_str(ridx));
752 sprod.push(':');
753 for sym in self.prod(pidx) {
754 let s = match sym {
755 Symbol::Token(tidx) => self.token_name(*tidx).unwrap(),
756 Symbol::Rule(ridx) => self.rule_name_str(*ridx),
757 };
758 write!(sprod, " \"{}\"", s).ok();
759 }
760 sprod
761 }
762
763 pub fn sentence_generator<F>(&self, token_cost: F) -> SentenceGenerator<'_, StorageT>
768 where
769 F: Fn(TIdx<StorageT>) -> u8,
770 {
771 SentenceGenerator::new(self, token_cost)
772 }
773
774 pub fn firsts(&self) -> YaccFirsts<StorageT> {
776 YaccFirsts::new(self)
777 }
778
779 pub fn follows(&self) -> YaccFollows<StorageT> {
781 YaccFollows::new(self)
782 }
783}
784
785pub struct SentenceGenerator<'a, StorageT> {
806 grm: &'a YaccGrammar<StorageT>,
807 rule_min_costs: RefCell<Option<Vec<u16>>>,
808 rule_max_costs: RefCell<Option<Vec<u16>>>,
809 token_costs: Vec<u8>,
810}
811
812impl<'a, StorageT: 'static + PrimInt + Unsigned> SentenceGenerator<'a, StorageT>
813where
814 usize: AsPrimitive<StorageT>,
815{
816 fn new<F>(grm: &'a YaccGrammar<StorageT>, token_cost: F) -> Self
817 where
818 F: Fn(TIdx<StorageT>) -> u8,
819 {
820 let mut token_costs = Vec::with_capacity(usize::from(grm.tokens_len()));
821 for tidx in grm.iter_tidxs() {
822 token_costs.push(token_cost(tidx));
823 }
824 SentenceGenerator {
825 grm,
826 token_costs,
827 rule_min_costs: RefCell::new(None),
828 rule_max_costs: RefCell::new(None),
829 }
830 }
831
832 pub fn min_sentence_cost(&self, ridx: RIdx<StorageT>) -> u16 {
836 self.rule_min_costs
837 .borrow_mut()
838 .get_or_insert_with(|| rule_min_costs(self.grm, &self.token_costs))[usize::from(ridx)]
839 }
840
841 pub fn max_sentence_cost(&self, ridx: RIdx<StorageT>) -> Option<u16> {
845 let v = self
846 .rule_max_costs
847 .borrow_mut()
848 .get_or_insert_with(|| rule_max_costs(self.grm, &self.token_costs))[usize::from(ridx)];
849 if v == u16::MAX { None } else { Some(v) }
850 }
851
852 pub fn min_sentence(&self, ridx: RIdx<StorageT>) -> Vec<TIdx<StorageT>> {
855 let cheapest_prod = |p_ridx: RIdx<StorageT>| -> PIdx<StorageT> {
856 let mut low_sc = None;
857 let mut low_idx = None;
858 for &pidx in self.grm.rule_to_prods(p_ridx).iter() {
859 let mut sc = 0;
860 for sym in self.grm.prod(pidx).iter() {
861 sc += match *sym {
862 Symbol::Rule(i) => self.min_sentence_cost(i),
863 Symbol::Token(i) => u16::from(self.token_costs[usize::from(i)]),
864 };
865 }
866 if low_sc.is_none() || Some(sc) < low_sc {
867 low_sc = Some(sc);
868 low_idx = Some(pidx);
869 }
870 }
871 low_idx.unwrap()
872 };
873
874 let mut s = vec![];
875 let mut st = vec![(cheapest_prod(ridx), 0)];
876 while let Some((pidx, sym_idx)) = st.pop() {
877 let prod = self.grm.prod(pidx);
878 for (sidx, sym) in prod.iter().enumerate().skip(sym_idx) {
879 match sym {
880 Symbol::Rule(s_ridx) => {
881 st.push((pidx, sidx + 1));
882 st.push((cheapest_prod(*s_ridx), 0));
883 }
884 Symbol::Token(s_tidx) => {
885 s.push(*s_tidx);
886 }
887 }
888 }
889 }
890 s
891 }
892
893 pub fn min_sentences(&self, ridx: RIdx<StorageT>) -> Vec<Vec<TIdx<StorageT>>> {
895 let cheapest_prods = |p_ridx: RIdx<StorageT>| -> Vec<PIdx<StorageT>> {
896 let mut low_sc = None;
897 let mut low_idxs = vec![];
898 for &pidx in self.grm.rule_to_prods(p_ridx).iter() {
899 let mut sc = 0;
900 for sym in self.grm.prod(pidx).iter() {
901 sc += match *sym {
902 Symbol::Rule(s_ridx) => self.min_sentence_cost(s_ridx),
903 Symbol::Token(s_tidx) => u16::from(self.token_costs[usize::from(s_tidx)]),
904 };
905 }
906 if low_sc.is_none() || Some(sc) <= low_sc {
907 if Some(sc) < low_sc {
908 low_idxs.clear();
909 }
910 low_sc = Some(sc);
911 low_idxs.push(pidx);
912 }
913 }
914 low_idxs
915 };
916
917 let mut sts = Vec::new(); for pidx in cheapest_prods(ridx) {
919 let prod = self.grm.prod(pidx);
920 if prod.is_empty() {
921 sts.push(vec![]);
922 continue;
923 }
924
925 let mut ms = Vec::with_capacity(prod.len());
936 for sym in prod {
937 match *sym {
938 Symbol::Rule(s_ridx) => ms.push(self.min_sentences(s_ridx)),
939 Symbol::Token(s_tidx) => ms.push(vec![vec![s_tidx]]),
940 }
941 }
942
943 let mut todo = vec![0; prod.len()];
968 let mut cur = Vec::new();
969 'b: loop {
970 for i in 0..todo.len() {
971 cur.extend(&ms[i][todo[i]]);
972 }
973 sts.push(std::mem::take(&mut cur));
974
975 let mut j = todo.len() - 1;
976 loop {
977 if todo[j] + 1 == ms[j].len() {
978 if j == 0 {
979 break 'b;
980 }
981 todo[j] = 0;
982 j -= 1;
983 } else {
984 todo[j] += 1;
985 break;
986 }
987 }
988 }
989 }
990 sts
991 }
992}
993
994#[allow(clippy::unnecessary_unwrap)]
997fn rule_min_costs<StorageT: 'static + PrimInt + Unsigned>(
998 grm: &YaccGrammar<StorageT>,
999 token_costs: &[u8],
1000) -> Vec<u16>
1001where
1002 usize: AsPrimitive<StorageT>,
1003{
1004 let mut costs = vec![0; usize::from(grm.rules_len())];
1027 let mut done = vec![false; usize::from(grm.rules_len())];
1028 loop {
1029 let mut all_done = true;
1030 for i in 0..done.len() {
1031 if done[i] {
1032 continue;
1033 }
1034 all_done = false;
1035 let mut ls_cmplt = None; let mut ls_noncmplt = None; for pidx in grm.rule_to_prods(RIdx(i.as_())).iter() {
1041 let mut c: u16 = 0; let mut cmplt = true;
1043 for sym in grm.prod(*pidx) {
1044 let sc = match *sym {
1045 Symbol::Token(tidx) => u16::from(token_costs[usize::from(tidx)]),
1046 Symbol::Rule(ridx) => {
1047 if !done[usize::from(ridx)] {
1048 cmplt = false;
1049 }
1050 costs[usize::from(ridx)]
1051 }
1052 };
1053 c = c
1054 .checked_add(sc)
1055 .expect("Overflow occurred when calculating rule costs");
1056 }
1057 if cmplt && (ls_cmplt.is_none() || Some(c) < ls_cmplt) {
1058 ls_cmplt = Some(c);
1059 } else if !cmplt && (ls_noncmplt.is_none() || Some(c) < ls_noncmplt) {
1060 ls_noncmplt = Some(c);
1061 }
1062 }
1063 if ls_cmplt.is_some() && (ls_noncmplt.is_none() || ls_cmplt < ls_noncmplt) {
1064 debug_assert!(ls_cmplt.unwrap() >= costs[i]);
1065 costs[i] = ls_cmplt.unwrap();
1066 done[i] = true;
1067 } else if let Some(ls_noncmplt) = ls_noncmplt {
1068 debug_assert!(ls_noncmplt >= costs[i]);
1069 costs[i] = ls_noncmplt;
1070 }
1071 }
1072 if all_done {
1073 debug_assert!(done.iter().all(|x| *x));
1074 break;
1075 }
1076 }
1077 costs
1078}
1079
1080#[allow(clippy::unnecessary_unwrap)]
1084fn rule_max_costs<StorageT: 'static + PrimInt + Unsigned>(
1085 grm: &YaccGrammar<StorageT>,
1086 token_costs: &[u8],
1087) -> Vec<u16>
1088where
1089 usize: AsPrimitive<StorageT>,
1090{
1091 let mut done = vec![false; usize::from(grm.rules_len())];
1092 let mut costs = vec![0; usize::from(grm.rules_len())];
1093
1094 for ridx in grm.iter_rules() {
1096 if grm.has_path(ridx, ridx) {
1098 costs[usize::from(ridx)] = u16::MAX;
1099 done[usize::from(ridx)] = true;
1100 }
1101 }
1102
1103 loop {
1104 let mut all_done = true;
1105 for i in 0..done.len() {
1106 if done[i] {
1107 continue;
1108 }
1109 all_done = false;
1110 let mut hs_cmplt = None; let mut hs_noncmplt = None; 'a: for pidx in grm.rule_to_prods(RIdx(i.as_())).iter() {
1116 let mut c: u16 = 0; let mut cmplt = true;
1118 for sym in grm.prod(*pidx) {
1119 let sc = match *sym {
1120 Symbol::Token(s_tidx) => u16::from(token_costs[usize::from(s_tidx)]),
1121 Symbol::Rule(s_ridx) => {
1122 if costs[usize::from(s_ridx)] == u16::MAX {
1123 hs_cmplt = Some(u16::MAX);
1126 break 'a;
1127 }
1128 if !done[usize::from(s_ridx)] {
1129 cmplt = false;
1130 }
1131 costs[usize::from(s_ridx)]
1132 }
1133 };
1134 c = c
1135 .checked_add(sc)
1136 .expect("Overflow occurred when calculating rule costs");
1137 if c == u16::MAX {
1138 panic!("Unable to represent cost in 64 bits.");
1139 }
1140 }
1141 if cmplt && (hs_cmplt.is_none() || Some(c) > hs_cmplt) {
1142 hs_cmplt = Some(c);
1143 } else if !cmplt && (hs_noncmplt.is_none() || Some(c) > hs_noncmplt) {
1144 hs_noncmplt = Some(c);
1145 }
1146 }
1147 if hs_cmplt.is_some() && (hs_noncmplt.is_none() || hs_cmplt > hs_noncmplt) {
1148 debug_assert!(hs_cmplt.unwrap() >= costs[i]);
1149 costs[i] = hs_cmplt.unwrap();
1150 done[i] = true;
1151 } else if let Some(hs_noncmplt) = hs_noncmplt {
1152 debug_assert!(hs_noncmplt >= costs[i]);
1153 costs[i] = hs_noncmplt;
1154 }
1155 }
1156 if all_done {
1157 debug_assert!(done.iter().all(|x| *x));
1158 break;
1159 }
1160 }
1161 costs
1162}
1163
1164#[cfg(test)]
1165mod test {
1166 use super::{
1167 super::{AssocKind, Precedence, YaccGrammar, YaccKind, YaccOriginalActionKind},
1168 IMPLICIT_RULE, IMPLICIT_START_RULE, rule_max_costs, rule_min_costs,
1169 };
1170 use crate::{PIdx, RIdx, Span, Symbol, TIdx};
1171 use std::collections::HashMap;
1172 use std::str::FromStr;
1173
1174 macro_rules! bslice {
1175 () => (
1176 ::Vec::new().into_boxed_slice()
1177 );
1178 ($elem:expr; $n:expr) => (
1179 ::vec::from_elem($elem, $n).into_boxed_slice()
1180 );
1181 ($($x:expr),+ $(,)?) => (
1182 <[_]>::into_vec(
1183 Box::new([$($x),+])
1184 ).into_boxed_slice()
1185 );
1186 }
1187
1188 #[test]
1189 fn test_minimal() {
1190 let grm = YaccGrammar::new(
1191 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1192 "%start R %token T %% R: 'T';",
1193 )
1194 .unwrap();
1195
1196 assert_eq!(grm.start_prod, PIdx(1));
1197 assert_eq!(grm.implicit_rule(), None);
1198 grm.rule_idx("^").unwrap();
1199 grm.rule_idx("R").unwrap();
1200 grm.token_idx("T").unwrap();
1201
1202 assert_eq!(&*grm.rules_prods, &[bslice![PIdx(1)], bslice![PIdx(0)]]);
1203 let start_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("^").unwrap())][0]);
1204 assert_eq!(*start_prod, [Symbol::Rule(grm.rule_idx("R").unwrap())]);
1205 let r_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("R").unwrap())][0]);
1206 assert_eq!(*r_prod, [Symbol::Token(grm.token_idx("T").unwrap())]);
1207 assert_eq!(&*grm.prods_rules, &[RIdx(1), RIdx(0)]);
1208
1209 assert_eq!(
1210 grm.tokens_map(),
1211 [("T", TIdx(0))]
1212 .iter()
1213 .cloned()
1214 .collect::<HashMap<&str, TIdx<_>>>()
1215 );
1216 assert_eq!(grm.iter_rules().collect::<Vec<_>>(), vec![RIdx(0), RIdx(1)]);
1217 }
1218
1219 #[test]
1220 fn test_rule_ref() {
1221 let grm = YaccGrammar::new(
1222 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1223 "%start R %token T %% R : S; S: 'T';",
1224 )
1225 .unwrap();
1226
1227 grm.rule_idx("^").unwrap();
1228 grm.rule_idx("R").unwrap();
1229 grm.rule_idx("S").unwrap();
1230 grm.token_idx("T").unwrap();
1231 assert!(grm.token_name(grm.eof_token_idx()).is_none());
1232
1233 assert_eq!(
1234 &*grm.rules_prods,
1235 &[bslice![PIdx(2)], bslice![PIdx(0)], bslice![PIdx(1)]]
1236 );
1237 let start_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("^").unwrap())][0]);
1238 assert_eq!(*start_prod, [Symbol::Rule(grm.rule_idx("R").unwrap())]);
1239 let r_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("R").unwrap())][0]);
1240 assert_eq!(r_prod.len(), 1);
1241 assert_eq!(r_prod[0], Symbol::Rule(grm.rule_idx("S").unwrap()));
1242 let s_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("S").unwrap())][0]);
1243 assert_eq!(s_prod.len(), 1);
1244 assert_eq!(s_prod[0], Symbol::Token(grm.token_idx("T").unwrap()));
1245 }
1246
1247 #[test]
1248 #[rustfmt::skip]
1249 fn test_long_prod() {
1250 let grm = YaccGrammar::new(
1251 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1252 "%start R %token T1 T2 %% R : S 'T1' S; S: 'T2';"
1253 ).unwrap();
1254
1255 grm.rule_idx("^").unwrap();
1256 grm.rule_idx("R").unwrap();
1257 grm.rule_idx("S").unwrap();
1258 grm.token_idx("T1").unwrap();
1259 grm.token_idx("T2").unwrap();
1260
1261 assert_eq!(&*grm.rules_prods, &[bslice![PIdx(2)],
1262 bslice![PIdx(0)],
1263 bslice![PIdx(1)]]);
1264 assert_eq!(&*grm.prods_rules, &[RIdx(1),
1265 RIdx(2),
1266 RIdx(0)]);
1267 let start_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("^").unwrap())][0]);
1268 assert_eq!(*start_prod, [Symbol::Rule(grm.rule_idx("R").unwrap())]);
1269 let r_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("R").unwrap())][0]);
1270 assert_eq!(r_prod.len(), 3);
1271 assert_eq!(r_prod[0], Symbol::Rule(grm.rule_idx("S").unwrap()));
1272 assert_eq!(r_prod[1], Symbol::Token(grm.token_idx("T1").unwrap()));
1273 assert_eq!(r_prod[2], Symbol::Rule(grm.rule_idx("S").unwrap()));
1274 let s_prod = grm.prod(grm.rules_prods[usize::from(grm.rule_idx("S").unwrap())][0]);
1275 assert_eq!(s_prod.len(), 1);
1276 assert_eq!(s_prod[0], Symbol::Token(grm.token_idx("T2").unwrap()));
1277 }
1278
1279 #[test]
1280 fn test_prods_rules() {
1281 let grm = YaccGrammar::new(
1282 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1283 "
1284 %start A
1285 %%
1286 A: B
1287 | C;
1288 B: 'x';
1289 C: 'y'
1290 | 'z';
1291 ",
1292 )
1293 .unwrap();
1294
1295 assert_eq!(
1296 &*grm.prods_rules,
1297 &[RIdx(1), RIdx(1), RIdx(2), RIdx(3), RIdx(3), RIdx(0)]
1298 );
1299 }
1300
1301 #[test]
1302 #[rustfmt::skip]
1303 fn test_left_right_nonassoc_precs() {
1304 let grm = YaccGrammar::new(
1305 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1306 "
1307 %start Expr
1308 %right '='
1309 %left '+' '-'
1310 %left '/'
1311 %left '*'
1312 %nonassoc '~'
1313 %%
1314 Expr : Expr '=' Expr
1315 | Expr '+' Expr
1316 | Expr '-' Expr
1317 | Expr '/' Expr
1318 | Expr '*' Expr
1319 | Expr '~' Expr
1320 | 'id' ;
1321 ").unwrap();
1322
1323 assert_eq!(grm.prod_precs.len(), 8);
1324 assert_eq!(grm.prod_precs[0].unwrap(), Precedence{level: 0, kind: AssocKind::Right});
1325 assert_eq!(grm.prod_precs[1].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1326 assert_eq!(grm.prod_precs[2].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1327 assert_eq!(grm.prod_precs[3].unwrap(), Precedence{level: 2, kind: AssocKind::Left});
1328 assert_eq!(grm.prod_precs[4].unwrap(), Precedence{level: 3, kind: AssocKind::Left});
1329 assert_eq!(grm.prod_precs[5].unwrap(), Precedence{level: 4, kind: AssocKind::Nonassoc});
1330 assert!(grm.prod_precs[6].is_none());
1331 assert_eq!(grm.prod_precs[7], None);
1332 }
1333
1334 #[test]
1335 #[rustfmt::skip]
1336 fn test_prec_override() {
1337 let grm = YaccGrammar::new(
1338 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1339 "
1340 %start expr
1341 %left '+' '-'
1342 %left '*' '/'
1343 %%
1344 expr : expr '+' expr
1345 | expr '-' expr
1346 | expr '*' expr
1347 | expr '/' expr
1348 | '-' expr %prec '*'
1349 | 'id' ;
1350 "
1351 ).unwrap();
1352 assert_eq!(grm.prod_precs.len(), 7);
1353 assert_eq!(grm.prod_precs[0].unwrap(), Precedence{level: 0, kind: AssocKind::Left});
1354 assert_eq!(grm.prod_precs[1].unwrap(), Precedence{level: 0, kind: AssocKind::Left});
1355 assert_eq!(grm.prod_precs[2].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1356 assert_eq!(grm.prod_precs[3].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1357 assert_eq!(grm.prod_precs[4].unwrap(), Precedence{level: 1, kind: AssocKind::Left});
1358 assert!(grm.prod_precs[5].is_none());
1359 assert_eq!(grm.prod_precs[6], None);
1360 }
1361
1362 #[test]
1363 #[rustfmt::skip]
1364 fn test_implicit_tokens_rewrite() {
1365 let grm = YaccGrammar::new(
1366 YaccKind::Eco,
1367 "
1368 %implicit_tokens ws1 ws2
1369 %start S
1370 %%
1371 S: 'a' | T;
1372 T: 'c' |;
1373 "
1374 ).unwrap();
1375
1376 assert_eq!(grm.prod_precs.len(), 9);
1384
1385 let itfs_rule_idx = grm.rule_idx(IMPLICIT_START_RULE).unwrap();
1386 assert_eq!(grm.rules_prods[usize::from(itfs_rule_idx)].len(), 1);
1387
1388 let itfs_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(itfs_rule_idx)][0])];
1389 assert_eq!(itfs_prod1.len(), 2);
1390 assert_eq!(itfs_prod1[0], Symbol::Rule(grm.rule_idx(IMPLICIT_RULE).unwrap()));
1391 assert_eq!(itfs_prod1[1], Symbol::Rule(grm.rule_idx("S").unwrap()));
1392
1393 let s_rule_idx = grm.rule_idx("S").unwrap();
1394 assert_eq!(grm.rules_prods[usize::from(s_rule_idx)].len(), 2);
1395
1396 let s_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(s_rule_idx)][0])];
1397 assert_eq!(s_prod1.len(), 2);
1398 assert_eq!(s_prod1[0], Symbol::Token(grm.token_idx("a").unwrap()));
1399 assert_eq!(s_prod1[1], Symbol::Rule(grm.rule_idx(IMPLICIT_RULE).unwrap()));
1400
1401 let s_prod2 = &grm.prods[usize::from(grm.rules_prods[usize::from(s_rule_idx)][1])];
1402 assert_eq!(s_prod2.len(), 1);
1403 assert_eq!(s_prod2[0], Symbol::Rule(grm.rule_idx("T").unwrap()));
1404
1405 let t_rule_idx = grm.rule_idx("T").unwrap();
1406 assert_eq!(grm.rules_prods[usize::from(s_rule_idx)].len(), 2);
1407
1408 let t_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(t_rule_idx)][0])];
1409 assert_eq!(t_prod1.len(), 2);
1410 assert_eq!(t_prod1[0], Symbol::Token(grm.token_idx("c").unwrap()));
1411 assert_eq!(t_prod1[1], Symbol::Rule(grm.rule_idx(IMPLICIT_RULE).unwrap()));
1412
1413 let t_prod2 = &grm.prods[usize::from(grm.rules_prods[usize::from(t_rule_idx)][1])];
1414 assert_eq!(t_prod2.len(), 0);
1415
1416 assert_eq!(Some(grm.rule_idx(IMPLICIT_RULE).unwrap()), grm.implicit_rule());
1417 let i_rule_idx = grm.rule_idx(IMPLICIT_RULE).unwrap();
1418 assert_eq!(grm.rules_prods[usize::from(i_rule_idx)].len(), 3);
1419 let i_prod1 = &grm.prods[usize::from(grm.rules_prods[usize::from(i_rule_idx)][0])];
1420 let i_prod2 = &grm.prods[usize::from(grm.rules_prods[usize::from(i_rule_idx)][1])];
1421 assert_eq!(i_prod1.len(), 2);
1422 assert_eq!(i_prod2.len(), 2);
1423 let cnd1 = bslice![
1426 Symbol::Token(grm.token_idx("ws1").unwrap()),
1427 Symbol::Rule(grm.implicit_rule().unwrap()),
1428 ];
1429 let cnd2 = bslice![
1430 Symbol::Token(grm.token_idx("ws2").unwrap()),
1431 Symbol::Rule(grm.implicit_rule().unwrap()),
1432 ];
1433 assert!((*i_prod1 == cnd1 && *i_prod2 == cnd2) || (*i_prod1 == cnd2 && *i_prod2 == cnd1));
1434 let i_prod3 = &grm.prods[usize::from(grm.rules_prods[usize::from(i_rule_idx)][2])];
1435 assert_eq!(i_prod3.len(), 0);
1436 }
1437
1438 #[test]
1439 #[rustfmt::skip]
1440 fn test_has_path() {
1441 let grm = YaccGrammar::new(
1442 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1443 "
1444 %start A
1445 %%
1446 A: B;
1447 B: B 'x' | C;
1448 C: C 'y' | ;
1449 "
1450 ).unwrap();
1451
1452 let a_ridx = grm.rule_idx("A").unwrap();
1453 let b_ridx = grm.rule_idx("B").unwrap();
1454 let c_ridx = grm.rule_idx("C").unwrap();
1455 assert!(grm.has_path(a_ridx, b_ridx));
1456 assert!(grm.has_path(a_ridx, c_ridx));
1457 assert!(grm.has_path(b_ridx, b_ridx));
1458 assert!(grm.has_path(b_ridx, c_ridx));
1459 assert!(grm.has_path(c_ridx, c_ridx));
1460 assert!(!grm.has_path(a_ridx, a_ridx));
1461 assert!(!grm.has_path(b_ridx, a_ridx));
1462 assert!(!grm.has_path(c_ridx, a_ridx));
1463 }
1464
1465 #[test]
1466 #[rustfmt::skip]
1467 fn test_rule_min_costs() {
1468 let grm = YaccGrammar::new(
1469 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1470 "
1471 %start A
1472 %%
1473 A: A B | ;
1474 B: C | D | E;
1475 C: 'x' B | 'x';
1476 D: 'y' B | 'y' 'z';
1477 E: 'x' A | 'x' 'y';
1478 "
1479 ).unwrap();
1480
1481 let scores = rule_min_costs(&grm, &[1, 1, 1]);
1482 assert_eq!(scores[usize::from(grm.rule_idx("A").unwrap())], 0);
1483 assert_eq!(scores[usize::from(grm.rule_idx("B").unwrap())], 1);
1484 assert_eq!(scores[usize::from(grm.rule_idx("C").unwrap())], 1);
1485 assert_eq!(scores[usize::from(grm.rule_idx("D").unwrap())], 2);
1486 assert_eq!(scores[usize::from(grm.rule_idx("E").unwrap())], 1);
1487 }
1488
1489 #[test]
1490 fn test_min_sentences() {
1491 let grm = YaccGrammar::new(
1492 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1493 "
1494 %start A
1495 %%
1496 A: A B | ;
1497 B: C | D;
1498 C: 'x' B | 'x';
1499 D: 'y' B | 'y' 'z';
1500 ",
1501 )
1502 .unwrap();
1503
1504 let sg = grm.sentence_generator(|_| 1);
1505
1506 let find = |nt_name: &str, str_cnds: Vec<Vec<&str>>| {
1507 let cnds = str_cnds
1508 .iter()
1509 .map(|x| {
1510 x.iter()
1511 .map(|y| grm.token_idx(y).unwrap())
1512 .collect::<Vec<_>>()
1513 })
1514 .collect::<Vec<_>>();
1515
1516 let ms = sg.min_sentence(grm.rule_idx(nt_name).unwrap());
1517 if !cnds.iter().any(|x| x == &ms) {
1518 panic!("{:?} doesn't have any matches in {:?}", ms, str_cnds);
1519 }
1520
1521 let min_sts = sg.min_sentences(grm.rule_idx(nt_name).unwrap());
1522 assert_eq!(cnds.len(), min_sts.len());
1523 for ms in min_sts {
1524 if !cnds.iter().any(|x| x == &ms) {
1525 panic!("{:?} doesn't have any matches in {:?}", ms, str_cnds);
1526 }
1527 }
1528 };
1529
1530 find("A", vec![vec![]]);
1531 find("B", vec![vec!["x"]]);
1532 find("C", vec![vec!["x"]]);
1533 find("D", vec![vec!["y", "x"], vec!["y", "z"]]);
1534 }
1535
1536 #[test]
1537 #[rustfmt::skip]
1538 fn test_rule_max_costs1() {
1539 let grm = YaccGrammar::new(
1540 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1541 "
1542 %start A
1543 %%
1544 A: A B | ;
1545 B: C | D | E;
1546 C: 'x' B | 'x';
1547 D: 'y' B | 'y' 'z';
1548 E: 'x' A | 'x' 'y';
1549 "
1550 ).unwrap();
1551
1552 let scores = rule_max_costs(&grm, &[1, 1, 1]);
1553 assert_eq!(scores[usize::from(grm.rule_idx("A").unwrap())], u16::MAX);
1554 assert_eq!(scores[usize::from(grm.rule_idx("B").unwrap())], u16::MAX);
1555 assert_eq!(scores[usize::from(grm.rule_idx("C").unwrap())], u16::MAX);
1556 assert_eq!(scores[usize::from(grm.rule_idx("D").unwrap())], u16::MAX);
1557 assert_eq!(scores[usize::from(grm.rule_idx("E").unwrap())], u16::MAX);
1558 }
1559
1560 #[test]
1561 #[rustfmt::skip]
1562 fn test_rule_max_costs2() {
1563 let grm = YaccGrammar::new(
1564 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1565 "
1566 %start A
1567 %%
1568 A: A B | B;
1569 B: C | D;
1570 C: 'x' 'y' | 'x';
1571 D: 'y' 'x' | 'y' 'x' 'z';
1572 "
1573 ).unwrap();
1574
1575 let scores = rule_max_costs(&grm, &[1, 1, 1]);
1576 assert_eq!(scores[usize::from(grm.rule_idx("A").unwrap())], u16::MAX);
1577 assert_eq!(scores[usize::from(grm.rule_idx("B").unwrap())], 3);
1578 assert_eq!(scores[usize::from(grm.rule_idx("C").unwrap())], 2);
1579 assert_eq!(scores[usize::from(grm.rule_idx("D").unwrap())], 3);
1580 }
1581
1582 #[test]
1583 fn test_out_of_order_productions() {
1584 let grm = YaccGrammar::new(
1586 YaccKind::Original(YaccOriginalActionKind::GenericParseTree),
1587 "
1588 %start S
1589 %%
1590 S: A 'c' 'd'
1591 | B 'c' 'e';
1592 A: 'a';
1593 B: 'a'
1594 | 'b';
1595 A: 'b';
1596 ",
1597 )
1598 .unwrap();
1599
1600 assert_eq!(
1601 &*grm.prods_rules,
1602 &[
1603 RIdx(1),
1604 RIdx(1),
1605 RIdx(2),
1606 RIdx(3),
1607 RIdx(3),
1608 RIdx(2),
1609 RIdx(0)
1610 ]
1611 );
1612 }
1613
1614 #[test]
1615 fn test_token_spans() {
1616 let src = "%%\nAB: 'a' | 'foo';";
1617 let grm =
1618 YaccGrammar::new(YaccKind::Original(YaccOriginalActionKind::NoAction), src).unwrap();
1619 let token_map = grm.tokens_map();
1620 let a_tidx = token_map.get("a");
1621 let foo_tidx = token_map.get("foo");
1622 let a_span = grm.token_span(*a_tidx.unwrap()).unwrap();
1623 let foo_span = grm.token_span(*foo_tidx.unwrap()).unwrap();
1624 let ab_span = grm.rule_name_span(grm.rule_idx("AB").unwrap());
1625 assert_eq!(a_span, Span::new(8, 9));
1626 assert_eq!(foo_span, Span::new(14, 17));
1627 assert_eq!(ab_span, Span::new(3, 5));
1628 assert_eq!(&src[a_span.start()..a_span.end()], "a");
1629 assert_eq!(&src[foo_span.start()..foo_span.end()], "foo");
1630 assert_eq!(&src[ab_span.start()..ab_span.end()], "AB");
1631 }
1632
1633 #[test]
1634 fn token_span_issue296() {
1635 let src = "%%
1636 S: | AB;
1637 A: 'a' 'b';
1638 B: 'b' 'c';
1639 AB: A AB | B ';' AB;
1640 %%
1641 ";
1642 let grm =
1643 YaccGrammar::new(YaccKind::Original(YaccOriginalActionKind::NoAction), src).unwrap();
1644 let token_map = grm.tokens_map();
1645 let c_tidx = token_map.get("c").unwrap();
1646 assert_eq!(grm.token_name(*c_tidx), Some("c"));
1647 let c_span = grm.token_span(*c_tidx).unwrap();
1648 assert_eq!(&src[c_span.start()..c_span.end()], "c");
1649 }
1650
1651 #[test]
1652 fn test_grmtools_section_yacckinds() {
1653 let srcs = [
1654 "%grmtools{yacckind: Original(NoAction)}
1655 %%
1656 Start: ;",
1657 "%grmtools{yacckind: YaccKind::Original(GenericParseTree)}
1658 %%
1659 Start: ;",
1660 "%grmtools{yacckind: YaccKind::Original(yaccoriginalactionkind::useraction)}
1661 %actiontype ()
1662 %%
1663 Start: ;",
1664 "%grmtools{yacckind: Original(YACCOriginalActionKind::NoAction)}
1665 %%
1666 Start: ;",
1667 "%grmtools{yacckind: YaccKind::Grmtools}
1668 %%
1669 Start -> () : ;",
1670 ];
1671 for src in srcs {
1672 YaccGrammar::<u32>::from_str(src).unwrap();
1673 }
1674 }
1675
1676 #[test]
1677 fn test_grmtools_section_invalid_yacckinds() {
1678 let srcs = [
1679 "%grmtools{yacckind: Foo}",
1680 "%grmtools{yacckind: YaccKind::Foo}",
1681 "%grmtools{yacckindof: YaccKind::Grmtools}",
1682 "%grmtools{yacckindof: Grmtools}",
1683 "%grmtools{yacckindof: YaccKindFoo::Foo}",
1684 "%grmtools{yacckind: Foo::Grmtools}",
1685 "%grmtools{yacckind: YaccKind::Original}",
1686 "%grmtools{yacckind: YaccKind::OriginalFoo}",
1687 "%grmtools{yacckind: YaccKind::Original()}",
1688 "%grmtools{yacckind: YaccKind::Original(Foo)}",
1689 "%grmtools{yacckind: YaccKind::Original(YaccOriginalActionKind)}",
1690 "%grmtools{yacckind: YaccKind::Original(YaccOriginalActionKind::Foo)}",
1691 "%grmtools{yacckind: YaccKind::Original(Foo::NoActions)}",
1692 "%grmtools{yacckind: YaccKind::Original(Foo::NoActionsBar)}",
1693 ];
1694
1695 for src in srcs {
1696 let s = format!("{}\n%%\nStart();\n", src);
1697 assert!(YaccGrammar::<u32>::from_str(&s).is_err());
1698 }
1699 }
1700
1701 #[test]
1702 fn test_grmtools_section_commas() {
1703 let src = r#"
1709 %grmtools{
1710 yacckind: YaccKind::Grmtools,
1711 }
1712 %%
1713 Start -> () : ;
1714 "#;
1715 YaccGrammar::<u32>::from_str(src).unwrap();
1716 let src = r#"
1717 %grmtools{
1718 yacckind: YaccKind::Grmtools
1719 }
1720 %%
1721 Start -> () : ;
1722 "#;
1723 YaccGrammar::<u32>::from_str(src).unwrap();
1724 }
1725}