Skip to main content

cfgrammar/yacc/
grammar.rs

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/// Representation of a `YaccGrammar`. See the [top-level documentation](../../index.html) for the
42/// guarantees this struct makes about rules, tokens, productions, and symbols.
43#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))]
45pub struct YaccGrammar<StorageT = u32> {
46    /// How many rules does this grammar have?
47    rules_len: RIdx<StorageT>,
48    /// A mapping from `RIdx` -> `(Span, String)`.
49    rule_names: Box<[(String, Span)]>,
50    /// A mapping from `TIdx` -> `Option<(Span, String)>`. Every user-specified token will have a name,
51    /// but tokens inserted by cfgrammar (e.g. the EOF token) won't.
52    token_names: Box<[Option<(Span, String)>]>,
53    /// A mapping from `TIdx` -> `Option<Precedence>`
54    token_precs: Box<[Option<Precedence>]>,
55    /// A mapping from `TIdx` -> `Option<String>` for the %epp declaration, giving pretty-printed
56    /// versions of token names that can be presented to the user in case of an error. Every
57    /// user-specified token will have a name that can be presented to the user (if a token doesn't
58    /// have an %epp entry, the token name will be used in lieu), but tokens inserted by cfgrammar
59    /// (e.g. the EOF token) won't.
60    token_epp: Box<[Option<String>]>,
61    /// How many tokens does this grammar have?
62    tokens_len: TIdx<StorageT>,
63    /// The offset of the EOF token.
64    eof_token_idx: TIdx<StorageT>,
65    /// How many productions does this grammar have?
66    prods_len: PIdx<StorageT>,
67    /// Which production is the sole production of the start rule?
68    start_prod: PIdx<StorageT>,
69    /// A list of all productions.
70    prods: Box<[Box<[Symbol<StorageT>]>]>,
71    /// A mapping from rules to their productions. Note that 1) the order of rules is identical to
72    /// that of `rule_names` 2) every rule will have at least 1 production 3) productions
73    /// are not necessarily stored sequentially.
74    rules_prods: Box<[Box<[PIdx<StorageT>]>]>,
75    /// A mapping from productions to their corresponding rule indexes.
76    prods_rules: Box<[RIdx<StorageT>]>,
77    /// The precedence of each production.
78    prod_precs: Box<[Option<Precedence>]>,
79    /// The span for each production.
80    ///
81    /// In the case of an empty span this may be a zero length span.
82    prod_spans: Box<[Span]>,
83    /// The index of the rule added for implicit tokens, if they were specified; otherwise
84    /// `None`.
85    implicit_rule: Option<RIdx<StorageT>>,
86    /// User defined Rust programs which can be called within actions
87    actions: Box<[Option<String>]>,
88    /// Spans for each action.
89    action_spans: Box<[Option<Span>]>,
90    /// A `(name, type)` pair defining an extra parameter to pass to action functions.
91    parse_param: Option<(String, String)>,
92    /// Generic parameters (types and lifetimes) to pass to action functions.
93    parse_generics: Option<String>,
94    /// Lifetimes for `param_args`
95    programs: Option<String>,
96    /// The actiontypes of rules (one per rule).
97    actiontypes: Box<[Option<String>]>,
98    /// Tokens marked as %avoid_insert (if any).
99    avoid_insert: Option<Vob>,
100    /// How many shift/reduce conflicts the grammar author expected (if any).
101    expect: Option<usize>,
102    /// How many reduce/reduce conflicts the grammar author expected (if any).
103    expectrr: Option<usize>,
104}
105
106// Internally, we assume that a grammar's start rule has a single production. Since we manually
107// create the start rule ourselves (without relying on user input), this is a safe assumption.
108impl 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    /// Takes as input a Yacc grammar of [`YaccKind`](enum.YaccKind.html) as a `String` `s` and returns a
130    /// [`YaccGrammar`](grammar/struct.YaccGrammar.html) (or
131    /// ([`YaccGrammarError`](grammar/enum.YaccGrammarError.html) on error).
132    ///
133    /// As we're compiling the `YaccGrammar`, we add a new start rule (which we'll refer to as `^`,
134    /// though the actual name is a fresh name that is guaranteed to be unique) that references the
135    /// user defined start rule.
136    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        // Check that StorageT is big enough to hold RIdx/PIdx/SIdx/TIdx values; after these
149        // checks we can guarantee that things like RIdx(ast.rules.len().as_()) are safe.
150        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        // Generate a guaranteed unique start rule name. We simply keep making the string longer
170        // until we've hit something unique (at the very worst, this will require looping for as
171        // many times as there are rules). We use the same technique later for unique end
172        // token and whitespace names.
173        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        // In order to avoid fiddling about with production indices from the AST, we simply map
246        // tem 1:1 to grammar indices. That means that any new productions are added to the *end*
247        // of the list of productions.
248        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                // Add the special start rule which has a single production which references a
259                // single rule.
260                rules_prods[usize::from(ridx)].push(PIdx(prods.len().as_()));
261                let start_prod = match implicit_start_rule {
262                    None => {
263                        // Add ^: S;
264                        vec![Symbol::Rule(rule_map[start_name])]
265                    }
266                    Some(ref s) => {
267                        // An implicit rule has been specified, so the special start rule
268                        // needs to reference the intermediate start rule required. Therefore add:
269                        //   ^: ^~;
270                        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                // Add the intermediate start rule (handling implicit tokens at the beginning of
280                // the file):
281                //   ^~: ~ S;
282                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                // Add the implicit rule: ~: "IMPLICIT_TOKEN_1" ~ | ... | "IMPLICIT_TOKEN_N" ~ | ;
292                let implicit_prods = &mut rules_prods[usize::from(rule_map[astrulename])];
293                // Add a production for each implicit token
294                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                // Add an empty production
301                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    /// How many productions does this grammar have?
398    pub fn prods_len(&self) -> PIdx<StorageT> {
399        self.prods_len
400    }
401
402    /// Return an iterator which produces (in order from `0..self.prods_len()`) all this
403    /// grammar's valid `PIdx`s.
404    pub fn iter_pidxs(&self) -> impl Iterator<Item = PIdx<StorageT>> {
405        // We can use as_ safely, because we know that we're only generating integers from
406        // 0..self.rules_len() and, since rules_len() returns an RIdx<StorageT>, then by
407        // definition the integers we're creating fit within StorageT.
408        Box::new((0..usize::from(self.prods_len())).map(|x| PIdx(x.as_())))
409    }
410
411    /// Get the sequence of symbols for production `pidx`. Panics if `pidx` doesn't exist.
412    pub fn prod(&self, pidx: PIdx<StorageT>) -> &[Symbol<StorageT>] {
413        &self.prods[usize::from(pidx)]
414    }
415
416    /// How many symbols does production `pidx` have? Panics if `pidx` doesn't exist.
417    pub fn prod_len(&self, pidx: PIdx<StorageT>) -> SIdx<StorageT> {
418        // Since we've already checked that StorageT can store all the symbols for every production
419        // in the grammar, the call to as_ is safe.
420        SIdx(self.prods[usize::from(pidx)].len().as_())
421    }
422
423    /// Return the rule index of the production `pidx`. Panics if `pidx` doesn't exist.
424    pub fn prod_to_rule(&self, pidx: PIdx<StorageT>) -> RIdx<StorageT> {
425        self.prods_rules[usize::from(pidx)]
426    }
427
428    /// Return the precedence of production `pidx` (where `None` indicates "no precedence specified").
429    /// Panics if `pidx` doesn't exist.
430    pub fn prod_precedence(&self, pidx: PIdx<StorageT>) -> Option<Precedence> {
431        self.prod_precs[usize::from(pidx)]
432    }
433
434    /// Return the span for a production `pidx`
435    ///
436    /// May return a zero length span such as when there is an empty production.
437    pub fn prod_span(&self, pidx: PIdx<StorageT>) -> Span {
438        self.prod_spans[usize::from(pidx)]
439    }
440
441    /// Return the production index of the start rule's sole production (for Yacc grammars the
442    /// start rule is defined to have precisely one production).
443    pub fn start_prod(&self) -> PIdx<StorageT> {
444        self.start_prod
445    }
446
447    /// How many rules does this grammar have?
448    pub fn rules_len(&self) -> RIdx<StorageT> {
449        self.rules_len
450    }
451
452    /// Return an iterator which produces (in order from `0..self.rules_len()`) all this
453    /// grammar's valid `RIdx`s.
454    pub fn iter_rules(&self) -> impl Iterator<Item = RIdx<StorageT>> {
455        // We can use as_ safely, because we know that we're only generating integers from
456        // 0..self.rules_len() and, since rules_len() returns an RIdx<StorageT>, then by
457        // definition the integers we're creating fit within StorageT.
458        Box::new((0..usize::from(self.rules_len())).map(|x| RIdx(x.as_())))
459    }
460
461    /// Return the productions for rule `ridx`. Panics if `ridx` doesn't exist.
462    pub fn rule_to_prods(&self, ridx: RIdx<StorageT>) -> &[PIdx<StorageT>] {
463        &self.rules_prods[usize::from(ridx)]
464    }
465
466    /// Return the name of rule `ridx`. Panics if `ridx` doesn't exist.
467    #[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    /// Return the name of rule `ridx`. Panics if `ridx` doesn't exist.
473    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    /// Return the span of rule `ridx`. Panics if `ridx` doesn't exist.
479    pub fn rule_name_span(&self, ridx: RIdx<StorageT>) -> Span {
480        let (_, span) = self.rule_names[usize::from(ridx)];
481        span
482    }
483
484    /// Return the `RIdx` of the implict rule if it exists, or `None` otherwise.
485    pub fn implicit_rule(&self) -> Option<RIdx<StorageT>> {
486        self.implicit_rule
487    }
488
489    /// Return the index of the rule named `n` or `None` if it doesn't exist.
490    pub fn rule_idx(&self, n: &str) -> Option<RIdx<StorageT>> {
491        self.rule_names
492            .iter()
493            .position(|(x, _)| x == n)
494            // The call to as_() is safe because rule_names is guaranteed to be
495            // small enough to fit into StorageT
496            .map(|x| RIdx(x.as_()))
497    }
498
499    /// What is the index of the start rule? Note that cfgrammar will have inserted at least one
500    /// rule "above" the user's start rule.
501    pub fn start_rule_idx(&self) -> RIdx<StorageT> {
502        self.prod_to_rule(self.start_prod)
503    }
504
505    /// How many tokens does this grammar have?
506    pub fn tokens_len(&self) -> TIdx<StorageT> {
507        self.tokens_len
508    }
509
510    /// Return an iterator which produces (in order from `0..self.tokens_len()`) all this
511    /// grammar's valid `TIdx`s.
512    pub fn iter_tidxs(&self) -> impl Iterator<Item = TIdx<StorageT>> {
513        // We can use as_ safely, because we know that we're only generating integers from
514        // 0..self.rules_len() and, since rules_len() returns an TIdx<StorageT>, then by
515        // definition the integers we're creating fit within StorageT.
516        Box::new((0..usize::from(self.tokens_len())).map(|x| TIdx(x.as_())))
517    }
518
519    /// Return the index of the end token.
520    pub fn eof_token_idx(&self) -> TIdx<StorageT> {
521        self.eof_token_idx
522    }
523
524    /// Return the name of token `tidx` (where `None` indicates "the rule has no name"). Panics if
525    /// `tidx` doesn't exist.
526    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    /// Return the precedence of token `tidx` (where `None` indicates "no precedence specified").
533    /// Panics if `tidx` doesn't exist.
534    pub fn token_precedence(&self, tidx: TIdx<StorageT>) -> Option<Precedence> {
535        self.token_precs[usize::from(tidx)]
536    }
537
538    /// Return the %epp entry for token `tidx` (where `None` indicates "the token has no
539    /// pretty-printed value"). Panics if `tidx` doesn't exist.
540    pub fn token_epp(&self, tidx: TIdx<StorageT>) -> Option<&str> {
541        self.token_epp[usize::from(tidx)].as_deref()
542    }
543
544    /// Return the span for token given by `tidx` if one exists.
545    /// If `None`, the token is either implicit and not derived from a token
546    /// in the source, otherwise the `YaccGrammar` itself may not derived from a
547    /// textual source in which case the token may be explicit but still lack spans
548    /// from its construction.
549    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    /// Get the action for production `pidx`. Panics if `pidx` doesn't exist.
556    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    /// Get the programs part of the grammar
577    pub fn programs(&self) -> &Option<String> {
578        &self.programs
579    }
580
581    /// Returns a map from names to `TIdx`s of all tokens that a lexer will need to generate valid
582    /// inputs from this grammar.
583    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    /// Return the index of the token named `n` or `None` if it doesn't exist.
594    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            // The call to as_() is safe because token_names is guaranteed to be small
599            // enough to fit into StorageT
600            .map(|x| TIdx(x.as_()))
601    }
602
603    /// Is the token `tidx` marked as `%avoid_insert`?
604    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    // How many shift/reduce conflicts were expected?
613    pub fn expect(&self) -> Option<usize> {
614        self.expect
615    }
616
617    // How many reduce/reduce conflicts were expected?
618    pub fn expectrr(&self) -> Option<usize> {
619        self.expectrr
620    }
621
622    /// Is there a path from the `from` rule to the `to` rule? Note that recursive rules
623    /// return `true` for a path from themselves to themselves.
624    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    /// Returns the string representation of a given production `pidx`.
659    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    /// Return a `SentenceGenerator` which can then generate minimal sentences for any rule
675    /// based on the user-defined `token_cost` function which gives the associated cost for
676    /// generating each token (where the cost must be greater than 0). Note that multiple
677    /// tokens can have the same score. The simplest cost function is thus `|_| 1`.
678    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    /// Return a `YaccFirsts` struct for this grammar.
686    pub fn firsts(&self) -> YaccFirsts<StorageT> {
687        YaccFirsts::new(self)
688    }
689
690    /// Return a `YaccFirsts` struct for this grammar.
691    pub fn follows(&self) -> YaccFollows<StorageT> {
692        YaccFollows::new(self)
693    }
694}
695
696/// A `SentenceGenerator` can generate minimal sentences for any given rule. e.g. for the
697/// grammar:
698///
699/// ```text
700/// %start A
701/// %%
702/// A: A B | ;
703/// B: C | D;
704/// C: 'x' B | 'x';
705/// D: 'y' B | 'y' 'z';
706/// ```
707///
708/// the following are valid minimal sentences:
709///
710/// ```text
711/// A: []
712/// B: [x]
713/// C: [x]
714/// D: [y, x] or [y, z]
715/// ```
716pub 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    /// What is the cost of a minimal sentence for the rule `ridx`? Note that, unlike
744    /// `min_sentence`, this function does not actually *build* a sentence and it is thus much
745    /// faster.
746    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    /// What is the cost of a maximal sentence for the rule `ridx`? Rules which can generate
753    /// sentences of unbounded length return None; rules which can only generate maximal strings of
754    /// a finite length return a `Some(u16)`.
755    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    /// Non-deterministically return a minimal sentence from the set of minimal sentences for the
764    /// rule `ridx`.
765    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    /// Return (in arbitrary order) all the minimal sentences for the rule `ridx`.
805    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(); // Output sentences
829        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            // We construct the minimal sentences in two phases.
837            //
838            // First, for each symbol in the production, we gather all the possible minimal
839            // sentences for it. If, for the grammar:
840            //   X: 'a' Y
841            //   Y: 'b' | 'c'
842            // we ask for the minimal sentences of X's only production we'll end up with a vec of
843            // vecs as follows:
844            //   [[['a']], [['b'], ['c']]]
845
846            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            // Second, we need to generate all combinations of the gathered sentences. We do this
855            // by writing our own simple numeric incrementing scheme. If we rewrite the list from
856            // above as follows:
857            //
858            //      0 1 <- call this axis "i"
859            //   0: a b
860            //   1:   c
861            //   ^
862            //   |
863            //   call this axis "todo"
864            //
865            // this hopefully becomes easier to see. Let's call the list "ms": the combinations we
866            // need to generate are thus:
867            //
868            //   ms[0][0] + ms[1][0]  (i.e. 'ab')
869            //   ms[0][0] + ms[1][1]  (i.e. 'ac')
870            //
871            // The easiest way to model this is to have a list (todo) with each entry starting at
872            // 0. After each iteration around the loop (i) we add 1 to the last todo column's
873            // entry: if that spills over the length of the corresponding ms entry, then we reset
874            // that column to zero, and try adding 1 to the previous column (as many times as
875            // needed). If the first column spills, then we're done. This is basically normal
876            // arithmetic but with each digit having an arbitrary base.
877
878            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
905/// Return the cost of a minimal string for each rule in this grammar. The cost of a
906/// token is specified by the user-defined `token_cost` function.
907fn 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    // We use a simple(ish) fixed-point algorithm to determine costs. We maintain two lists
915    // "costs" and "done". An integer costs[i] starts at 0 and monotonically increments
916    // until done[i] is true, at which point costs[i] value is fixed. We also use the done
917    // list as a simple "todo" list: whilst there is at least one false value in done, there is
918    // still work to do.
919    //
920    // On each iteration of the loop, we examine each rule in the todo list to see if
921    // we can get a better idea of its true cost. Some are trivial:
922    //   * A rule with an empty production immediately has a cost of 0.
923    //   * Rules whose productions don't reference any rules (i.e. only contain tokens) can be
924    //     immediately given a cost by calculating the lowest-cost production.
925    // However if a rule A references another rule B, we may need to wait until
926    // we've fully analysed B before we can cost A. This might seem to cause problems with
927    // recursive rules, so we introduce the concept of "incomplete costs" i.e. if a production
928    // references a rule we can work out its minimum possible cost simply by counting
929    // the production's token costs. Since rules can have a mix of complete and
930    // incomplete productions, this is sometimes enough to allow us to assign a final cost to
931    // a rule (if the lowest complete production's cost is lower than or equal to all
932    // the lowest incomplete production's cost). This allows us to make progress, since it
933    // means that we can iteratively improve our knowledge of a token's minimum cost:
934    // eventually we will reach a point where we can determine it definitively.
935
936    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; // lowest completed cost
946            let mut ls_noncmplt = None; // lowest non-completed cost
947
948            // The call to as_() is guaranteed safe because done.len() == grm.rules_len(), and
949            // we guarantee that grm.rules_len() can fit in StorageT.
950            for pidx in grm.rule_to_prods(RIdx(i.as_())).iter() {
951                let mut c: u16 = 0; // production cost
952                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
992/// Return the cost of the maximal string for each rule in this grammar (u32::max_val()
993/// representing "this rule can generate strings of infinite length"). The cost of a
994/// token is specified by the user-defined `token_cost` function.
995fn 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    // First mark all recursive rules.
1006    for ridx in grm.iter_rules() {
1007        // Calling has_path so frequently is not exactly efficient...
1008        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; // highest completed cost
1022            let mut hs_noncmplt = None; // highest non-completed cost
1023
1024            // The call to as_() is guaranteed safe because done.len() == grm.rules_len(), and
1025            // we guarantee that grm.rules_len() can fit in StorageT.
1026            'a: for pidx in grm.rule_to_prods(RIdx(i.as_())).iter() {
1027                let mut c: u16 = 0; // production cost
1028                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                                // As soon as we find reference to an infinite rule, we
1035                                // can stop looking.
1036                                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        // Check that the above grammar has been rewritten to:
1290        //   ^ : ^~;
1291        //   ^~: ~ S;
1292        //   ~ : ws1 | ws2 | ;
1293        //   S : 'a' ~ | T;
1294        //   T : 'c' ~ | ;
1295
1296        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        // We don't know what order the implicit rule will contain our tokens in,
1337        // hence the awkward dance below.
1338        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        // Example taken from p54 of Locally least-cost error repair in LR parsers, Carl Cerecke
1498        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        // We can't actually test much here, because
1617        // We don't have a second value to test.
1618        //
1619        // `RecoveryKind` seemed like an option for an additional value to allow,
1620        // but that is part of `lrpar` which cfgrammar doesn't depend upon.
1621        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}