cfg_classify/
lib.rs

1//! Classification of rules and grammars.
2
3#![deny(unsafe_code)]
4#![deny(missing_docs)]
5
6use cfg_grammar::Cfg;
7use cfg_symbol::Symbol;
8
9pub mod cyclical;
10// pub mod linear;
11#[cfg(feature = "ll")]
12pub mod ll;
13#[cfg(feature = "lr")]
14pub mod lr;
15pub mod recursive;
16// pub mod regular;
17pub mod useful;
18
19/// Extension trait for assigning categories to context-free
20/// grammar rules, and related operations.
21pub trait CfgClassifyExt {
22    /// Computes the LL(1) parse table.
23    #[cfg(feature = "ll")]
24    fn ll_parse_table(&self) -> ll::LlParseTable<'_>;
25    /// Allows you to build the LR(0) fsm.
26    #[cfg(feature = "lr")]
27    fn lr0_fsm_builder(&mut self) -> lr::Lr0FsmBuilder<'_>;
28    /// Allows you to build the LR(0) closure.
29    #[cfg(feature = "lr")]
30    fn lr0_closure_builder(&mut self) -> lr::Lr0ClosureBuilder<'_>;
31    /// Allows you to access information on rule recursiveness.
32    fn recursion(&self) -> recursive::Recursion<'_>;
33    /// Modifies this grammar in-place to remove useless
34    /// rules.
35    fn make_proper(&mut self) -> bool;
36    /// Determines usefulness of rules with the grammar's roots.
37    ///
38    /// A rule is useful if it is reachable from the grammar's roots,
39    /// and productive.
40    fn usefulness(&mut self) -> useful::Usefulness;
41    /// Determines usefulness of rules with the given roots.
42    ///
43    /// A rule is useful if it is reachable from these roots, and
44    /// productive.
45    fn usefulness_with_roots(&mut self, roots: &[Symbol]) -> useful::Usefulness;
46}
47
48impl CfgClassifyExt for Cfg {
49    #[cfg(feature = "ll")]
50    fn ll_parse_table(&self) -> ll::LlParseTable<'_> {
51        ll::LlParseTable::new(self)
52    }
53
54    fn recursion(&self) -> recursive::Recursion<'_> {
55        recursive::Recursion::new(self)
56    }
57
58    #[cfg(feature = "lr")]
59    fn lr0_fsm_builder(&mut self) -> lr::Lr0FsmBuilder<'_> {
60        lr::Lr0FsmBuilder::new(self)
61    }
62
63    #[cfg(feature = "lr")]
64    fn lr0_closure_builder(&mut self) -> lr::Lr0ClosureBuilder<'_> {
65        lr::Lr0ClosureBuilder::new(self)
66    }
67
68    fn usefulness(&mut self) -> useful::Usefulness {
69        let mut usefulness = useful::Usefulness::new(self);
70        let roots = self.roots();
71        usefulness.reachable(roots);
72        usefulness
73    }
74
75    fn usefulness_with_roots(&mut self, roots: &[Symbol]) -> useful::Usefulness {
76        let mut usefulness = useful::Usefulness::new(self);
77        usefulness.reachable(roots);
78        usefulness
79    }
80
81    fn make_proper(&mut self) -> bool {
82        let usefulness = self.usefulness();
83        let contains_useless_rules = !usefulness.all_useful();
84        if contains_useless_rules {
85            // for useless in usefulness.useless_rules() {
86            //     let rhs: Vec<_> = useless.rule.rhs().iter().map(|t| tok.get(t.usize())).collect();
87            //     println!("lhs:{:?} rhs:{:?} unreachable:{} unproductive:{}", tok.get(useless.rule.lhs().usize()), rhs, useless.unreachable, useless.unproductive);
88            // }
89            // println!("warning: grammar has useless rules");
90            usefulness.remove_useless_rules(self);
91        }
92        !contains_useless_rules
93    }
94}