1use 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
11pub 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 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 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 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 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 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}