cfg_grammar/
rule_builder.rs

1//! Plain grammar rules can be built with the builder pattern.
2
3use std::convert::AsRef;
4
5use crate::local_prelude::*;
6use cfg_history::{
7    LinkedHistoryNode, RootHistoryNode,
8    earley::{History, process_linked},
9};
10
11/// The rule builder.
12pub struct RuleBuilder<'a> {
13    lhs: Option<Symbol>,
14    history: Option<History>,
15    grammar: &'a mut Cfg,
16}
17
18impl<'a> RuleBuilder<'a> {
19    /// Creates a rule builder.
20    pub fn new(grammar: &'a mut Cfg) -> Self {
21        RuleBuilder {
22            lhs: None,
23            history: None,
24            grammar,
25        }
26    }
27}
28
29impl<'a> RuleBuilder<'a> {
30    /// Starts building a new rule with the given LHS.
31    pub fn rule(mut self, lhs: Symbol) -> Self {
32        self.lhs = Some(lhs);
33        self.history = None;
34        self
35    }
36
37    /// Assigns the rule history, which is used on the next call to `rhs`, or overwritten by a call
38    /// to `rhs_with_history`.
39    pub fn history(mut self, history: History) -> Self {
40        self.history = Some(history);
41        self
42    }
43
44    /// Adds a rule alternative to the grammar. If history wasn't provided, the rule has the
45    /// `Default` history.
46    pub fn rhs(mut self, syms: impl AsRef<[Symbol]>) -> Self {
47        let new_history = match self.history.take() {
48            Some(history) => history,
49            None => RootHistoryNode::Rule {
50                lhs: self.lhs.unwrap(),
51            }
52            .into(),
53        };
54        self.rhs_with_history(syms, new_history)
55    }
56
57    /// Adds a rule alternative with the given RHS and history to the grammar.
58    pub fn rhs_with_history(self, syms: impl AsRef<[Symbol]>, history: History) -> Self {
59        let lhs = self.lhs.unwrap();
60        let rhs = syms.as_ref().into();
61        self.grammar.add_rule(CfgRule { lhs, rhs, history });
62        self
63    }
64
65    /// Adds a rule alternative with the given RHS and history to the grammar.
66    pub fn rhs_with_linked_history(
67        self,
68        syms: impl AsRef<[Symbol]>,
69        linked_history: LinkedHistoryNode,
70    ) -> Self {
71        let history = process_linked(
72            &linked_history,
73            RootHistoryNode::Rule {
74                lhs: self.lhs.unwrap(),
75            }
76            .into(),
77        );
78        self.rhs_with_history(syms, history)
79    }
80
81    /// Starts building a new precedenced rule.
82    pub fn precedenced_rule(self, lhs: Symbol) -> PrecedencedRuleBuilder<'a> {
83        PrecedencedRuleBuilder::new(self.grammar, lhs)
84    }
85}