mpl/
parser.rs

1//! Parse
2
3use crate::input::Input;
4use crate::output::Output;
5use crate::position::Position;
6use crate::rules::Rules;
7use crate::span::Span;
8use crate::symbols::{Equivalence, Metasymbol, Terminal, TerminalSymbol, Variable, E};
9use crate::trees::{AST, CST};
10
11/// Types that can be parsed.
12///
13/// I is Input.
14/// T is terminal symbols.
15/// V is (enum of) Variables.
16/// S is Span.
17/// P is position.
18/// R is Rules.
19/// O is output type.
20// TODO: Create Error types
21pub trait Parser<'i, I, T, V, S, P, R, O = ()>
22where
23    I: Input + ?Sized,
24    T: Terminal<'i, I, V, S, P, O>,
25    V: Variable,
26    S: Span<I, P>,
27    P: Position,
28    R: Rules<T, V>,
29    O: Output<'i, I, V, S>,
30{
31    /// Minimal parse.
32    ///
33    /// # Warning
34    ///
35    /// `all_of_the_span.hi(self)` must be smaller than its length.
36    fn parse(
37        &self,
38        input: &'i I,
39        rules: &R,
40        start_variable: &V,
41        all_of_the_span: &S,
42    ) -> Result<AST<V, S, O>, AST<V, S, O>> {
43        let ast = self.eval(
44            input,
45            &all_of_the_span.lo(input),
46            rules,
47            start_variable,
48            &all_of_the_span.hi(input),
49        )?;
50
51        if &ast.span == all_of_the_span {
52            Ok(ast)
53        } else {
54            Err(ast)
55        }
56    }
57
58    fn to_empty_ast(&self, input: &'i I, pos: P) -> Result<AST<V, S, O>, AST<V, S, O>> {
59        Ok(AST::from_leaf(
60            Metasymbol::Empty.into(),
61            Span::from_lo_hi(pos.clone(), pos, input),
62        ))
63    }
64
65    fn to_failure_ast(&self, input: &'i I, pos: P) -> Result<AST<V, S, O>, AST<V, S, O>> {
66        Err(AST::from_leaf(
67            Metasymbol::Failure.into(),
68            Span::from_lo_hi(pos.clone(), pos, input),
69        ))
70    }
71
72    // TODO: Decide return Any or Failure
73    fn to_any_ast(
74        &self,
75        input: &'i I,
76        pos: P,
77        max_pos: &P,
78        n: usize,
79    ) -> Result<AST<V, S, O>, AST<V, S, O>> {
80        let span_with_len_added = S::from_lo_len(pos, n, input);
81        let hi = span_with_len_added.hi(input);
82        let ast = AST::from_leaf(Metasymbol::Any(n).into(), span_with_len_added);
83        if &hi <= max_pos {
84            Ok(ast)
85        } else {
86            Err(ast)
87        }
88    }
89
90    fn to_all_ast(&self, input: &'i I, pos: P, max_pos: P) -> Result<AST<V, S, O>, AST<V, S, O>> {
91        Ok(AST::from_leaf(
92            Metasymbol::All.into(),
93            Span::from_lo_hi(pos, max_pos, input),
94        ))
95    }
96
97    fn eval_terminal_symbol(
98        &self,
99        input: &'i I,
100        terminal_symbol: &TerminalSymbol<T>,
101        pos: P,
102        max_pos: &P,
103    ) -> Result<AST<V, S, O>, AST<V, S, O>> {
104        match terminal_symbol {
105            TerminalSymbol::Original(t) => t.eval(input, pos, max_pos),
106            TerminalSymbol::Metasymbol(metasymbol) => match metasymbol {
107                Metasymbol::Empty => self.to_empty_ast(input, pos),
108                Metasymbol::Failure => self.to_failure_ast(input, pos),
109                Metasymbol::Any(n) => self.to_any_ast(input, pos, max_pos, *n),
110                Metasymbol::All => self.to_all_ast(input, pos, max_pos.clone()),
111                Metasymbol::Omit => unimplemented!(),
112            },
113        }
114    }
115
116    fn eval(
117        &self,
118        input: &'i I,
119        pos: &P,
120        rules: &R,
121        variable: &V,
122        max_pos: &P,
123    ) -> Result<AST<V, S, O>, AST<V, S, O>> {
124        let right_rule = rules.get(variable).expect("right_rule from a variable");
125
126        // First choice
127        // left-hand side of first choice
128        let left_ast: Result<AST<V, S, O>, AST<V, S, O>> = match &right_rule.first.lhs {
129            E::T(terminal_symbol) => {
130                self.eval_terminal_symbol(input, terminal_symbol, pos.clone(), max_pos)
131            }
132            E::V(lhs_of_fc_v) => self.eval(input, pos, rules, lhs_of_fc_v, max_pos),
133        };
134
135        if let Ok(left_ast) = left_ast {
136            // right-hand side of first choice
137            let right_ast: Result<AST<V, S, O>, AST<V, S, O>> = match &right_rule.first.rhs {
138                E::T(terminal_symbol) => self.eval_terminal_symbol(
139                    input,
140                    terminal_symbol,
141                    left_ast.span.hi(input),
142                    max_pos,
143                ),
144                E::V(rhs_of_fc_v) => {
145                    self.eval(input, &left_ast.span.hi(input), rules, rhs_of_fc_v, max_pos)
146                }
147            };
148
149            if let Ok(right_ast) = right_ast {
150                let merged_span = Span::merge_lhs_and_rhs(&left_ast.span, &right_ast.span, input);
151
152                let variable_and_choice =
153                    Equivalence::new(variable.clone(), (left_ast, right_ast).into());
154
155                let cst = CST::new(variable_and_choice, merged_span);
156
157                let output_ast = O::output_ast(input, cst);
158
159                return Ok(output_ast);
160            }
161        }
162
163        // Second choice
164        match &right_rule.second.0 {
165            E::T(terminal_symbol) => {
166                self.eval_terminal_symbol(input, terminal_symbol, pos.clone(), max_pos)
167            }
168            E::V(sc_v) => {
169                let ast = self.eval(input, pos, rules, sc_v, max_pos)?;
170                let span = ast.span.clone();
171
172                let variable_and_choice = Equivalence::new(variable.clone(), ast.into());
173
174                let cst = CST::new(variable_and_choice, span);
175
176                let output_ast = O::output_ast(input, cst);
177
178                Ok(output_ast)
179            }
180        }
181    }
182}