1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
// // Interface traits // // // NonterminalValue: Clone + PartialEq // /// Describes requirements for types of non-terminal symbol values. /// /// Any type that is cloneable and comparable by `==` automatically satisfies `NonterminalValue`. pub trait NonterminalValue: Clone + PartialEq { // Empty } impl<Nt> NonterminalValue for Nt where Nt: Clone + PartialEq { // Empty } // // TerminalValue: Clone // /// Describes requirements for types of terminal symbol values. /// /// Any cloneable type automatically satisfies `TerminalValue`. pub trait TerminalValue: Clone { // Empty } impl<T> TerminalValue for T where T: Clone { // Empty } // // Interface types // // // enum Symbol<Nt, T>: Debug + Clone + Copy + PartialEq // /// Used to describe non-terminal and terminal symbols in [`Rule`](struct.Rule.html)s /// and grammar input sequences for [`Expander::expand()`](struct.Expander.html#method.expand). #[derive(Debug, Clone, Copy, PartialEq)] pub enum Symbol<Nt, T> { /// Variant for non-terminal symbols - ones which can be further expanded, /// can appear on left-hand side of rules and cannot appear in a successful expansion result. Nonterminal(Nt), /// Variant for terminal symbols - ones which will not be replaced during expansion, /// cannot appear on left-hand side of rules and will be the only ones in a successful expansion result. Terminal(T) } impl<Nt, T> Symbol<Nt, T> { /// Returns `true` if the [`Symbol`](enum.Symbol.html) /// is [`Terminal`](enum.Symbol.html#variant.Terminal). pub fn is_terminal(&self) -> bool { matches!(self, Self::Terminal(_)) } /// Returns `true` if the [`Symbol`](enum.Symbol.html) /// is [`Nonterminal`](enum.Symbol.html#variant.Nonterminal). pub fn is_nonterminal(&self) -> bool { !self.is_terminal() } /// Returns the contained [`Nonterminal`](enum.Symbol.html#variant.Nonterminal) value, /// consuming the `self` value. /// /// # Panics /// Panics if the `self` value is actually [`Terminal`](enum.Symbol.html#variant.Terminal). pub fn unwrap_nonterm(self) -> Nt { self.expect_nonterm( "unwrap_nonterm() must be used only on non-terminal symbols" ) } /// Returns the contained [`Nonterminal`](enum.Symbol.html#variant.Nonterminal) value, /// consuming the `self` value. /// /// # Panics /// Panics with a custom `message` if the `self` value is actually [`Terminal`](enum.Symbol.html#variant.Terminal). pub fn expect_nonterm(self, message: &'static str) -> Nt { if let Self::Nonterminal(value) = self { value } else { panic!("{}", message); } } /// Returns the contained [`Terminal`](enum.Symbol.html#variant.Terminal) value, /// consuming the `self` value. /// /// # Panics /// Panics if the `self` value is actually [`Nonterminal`](enum.Symbol.html#variant.Nonterminal). pub fn unwrap_term(self) -> T { self.expect_term( "unwrap_term() must be used only on terminal symbols" ) } /// Returns the contained [`Terminal`](enum.Symbol.html#variant.Terminal) value, /// consuming the `self` value. /// /// # Panics /// Panics with a custom `message` if the `self` value is actually [`Nonterminal`](enum.Symbol.html#variant.Nonterminal). pub fn expect_term(self, message: &'static str) -> T { if let Self::Terminal(value) = self { value } else { panic!("{}", message); } } } // // struct Rule<Nt, T>: Debug + Clone + PartialEq // /// Describes a rule (or production) of a context-free grammar. #[derive(Debug, Clone, PartialEq)] pub struct Rule<Nt, T> { /// Left-hand side of the rule (a single non-terminal symbol value). pub pattern: Nt, /// Right-hand side of the rule (any sequence of symbols, /// with which to replace the encountered `pattern`). pub replacement: Vec<Symbol<Nt, T>> } impl<Nt, T> Rule<Nt, T> { pub fn new(pattern: Nt, replacement: Vec<Symbol<Nt, T>>) -> Self { Self{ pattern, replacement } } }