1use peg::str::LineCol;
2
3use super::Cst;
4use crate::grammar;
5
6macro_rules! make_rule {
7 ( $($variant:ident,)* ) => {
8 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
9 #[allow(non_camel_case_types)]
10 pub enum Rule {
11 $($variant),*
12 }
13
14 impl Rule {
15 pub fn parse(&self, text: &str) -> Result<Cst, peg::error::ParseError<LineCol>> {
16 match self {
17 $(Rule::$variant => grammar::$variant(&text)),*
18 }
19 }
20 }
21 };
22 ( $($variant:ident),* ) => {
23 make_rule!($($variant),*,);
24 };
25}
26
27make_rule! {
29 misc,
30
31 program_saty,
32 program_satyh,
33 preamble,
34
35 stage,
37 headers,
38 header_require,
39 header_import,
40 pkgname,
41
42 let_stmt,
44 let_rec_stmt,
45 let_rec_inner,
46 let_rec_matcharm,
47 let_inline_stmt_ctx,
48 let_inline_stmt_noctx,
49 let_block_stmt_ctx,
50 let_block_stmt_noctx,
51 let_math_stmt,
52 let_mutable_stmt,
53 type_stmt,
54 type_inner,
55 type_variant,
56 module_stmt,
57 open_stmt,
58 arg,
59
60 sig_stmt,
62 struct_stmt,
63 sig_type_stmt,
64 sig_val_stmt,
65 sig_direct_stmt,
66
67 type_expr,
69 type_optional,
70 type_prod,
71 type_inline_cmd,
72 type_block_cmd,
73 type_math_cmd,
74 type_list_unit_optional,
75 type_application,
76 type_name,
77 type_record,
78 type_record_unit,
79 type_param,
80 constraint,
81
82 pat_as,
84 pat_cons,
85 pattern,
86 pat_variant,
87 pat_list,
88 pat_tuple,
89
90 expr,
92 match_expr,
93 match_arm,
94 match_guard,
95 bind_stmt,
96 ctrl_while,
97 ctrl_if,
98 lambda,
99 assignment,
100 dyadic_expr,
101 unary_operator_expr,
102 unary_operator,
103 application,
104 application_args_normal,
105 application_args_optional,
106 command_application,
107 variant_constructor,
108
109 unary,
111 unary_prefix,
112 block_text,
113 horizontal_text,
114 math_text,
115 list,
116 record,
117 record_unit,
118 tuple,
119 bin_operator,
120 expr_with_mod,
121 var,
122 var_ptn,
123 modvar,
124 mod_cmd_name,
125 module_name,
126 variant_name,
127
128 cmd_name_ptn,
130 cmd_expr_arg,
131 cmd_expr_option,
132 cmd_text_arg,
133 inline_cmd,
134 inline_cmd_name,
135 block_cmd,
136 block_cmd_name,
137 math_cmd,
138 math_cmd_name,
139 math_cmd_expr_arg,
140 math_cmd_expr_option,
141
142 horizontal_single,
144 horizontal_list,
145 horizontal_bullet_list,
146 horizontal_bullet,
147 horizontal_bullet_star,
148 regular_text,
149 horizontal_escaped_char,
150 inline_text_embedding,
151
152 vertical,
153 block_text_embedding,
154
155 const_unit,
157 const_bool,
158 const_int,
159 const_float,
160 const_length,
161 const_string,
162
163 math_single,
165 math_list,
166 math_token,
167 math_sup,
168 math_sub,
169 math_unary,
170 math_embedding,
171
172 dummy_header,
174 dummy_sig_stmt,
175 dummy_stmt,
176 dummy_inline_cmd_incomplete,
177 dummy_block_cmd_incomplete,
178 dummy_modvar_incomplete,
179}
180
181#[derive(Debug, Clone, PartialEq, Eq, Hash)]
182pub enum Mode {
183 Program,
185 ProgramType,
187 Vertical,
189 Horizontal,
191 Math,
193 Header,
195 Literal,
197 Comment,
199}
200
201impl Rule {
202 pub fn mode(&self) -> Option<Mode> {
207 let mode = match self {
208 Rule::stage
209 | Rule::headers
210 | Rule::header_require
211 | Rule::header_import
212 | Rule::dummy_header
213 | Rule::pkgname => Mode::Header,
214
215 Rule::let_stmt
216 | Rule::let_rec_stmt
217 | Rule::let_rec_inner
218 | Rule::let_rec_matcharm
219 | Rule::let_inline_stmt_ctx
220 | Rule::let_inline_stmt_noctx
221 | Rule::let_block_stmt_ctx
222 | Rule::let_block_stmt_noctx
223 | Rule::let_math_stmt
224 | Rule::let_mutable_stmt
225 | Rule::type_stmt
226 | Rule::module_stmt
227 | Rule::open_stmt
228 | Rule::dummy_stmt
229 | Rule::arg
230 | Rule::pat_as
231 | Rule::pat_cons
232 | Rule::pattern
233 | Rule::pat_variant
234 | Rule::pat_list
235 | Rule::pat_tuple
236 | Rule::expr
237 | Rule::match_expr
238 | Rule::match_arm
239 | Rule::match_guard
240 | Rule::bind_stmt
241 | Rule::ctrl_while
242 | Rule::ctrl_if
243 | Rule::lambda
244 | Rule::assignment
245 | Rule::dyadic_expr
246 | Rule::unary_operator_expr
247 | Rule::unary_operator
248 | Rule::application
249 | Rule::application_args_normal
250 | Rule::application_args_optional
251 | Rule::command_application
252 | Rule::variant_constructor
253 | Rule::unary
254 | Rule::unary_prefix
255 | Rule::list
256 | Rule::record
257 | Rule::record_unit
258 | Rule::tuple
259 | Rule::bin_operator
260 | Rule::expr_with_mod
261 | Rule::mod_cmd_name
262 | Rule::module_name
263 | Rule::variant_name
264 | Rule::cmd_expr_arg
265 | Rule::cmd_expr_option
266 | Rule::math_cmd_expr_arg
267 | Rule::math_cmd_expr_option => Mode::Program,
268
269 Rule::sig_stmt
270 | Rule::dummy_sig_stmt
271 | Rule::type_inner
272 | Rule::type_variant
273 | Rule::sig_type_stmt
274 | Rule::sig_val_stmt
275 | Rule::sig_direct_stmt
276 | Rule::type_expr
277 | Rule::type_optional
278 | Rule::type_prod
279 | Rule::type_inline_cmd
280 | Rule::type_block_cmd
281 | Rule::type_math_cmd
282 | Rule::type_list_unit_optional
283 | Rule::type_application
284 | Rule::type_name
285 | Rule::type_record
286 | Rule::type_record_unit
287 | Rule::type_param
288 | Rule::constraint => Mode::ProgramType,
289
290 Rule::horizontal_single
291 | Rule::horizontal_list
292 | Rule::horizontal_bullet_list
293 | Rule::horizontal_bullet
294 | Rule::regular_text
295 | Rule::horizontal_escaped_char => Mode::Horizontal,
296
297 Rule::vertical => Mode::Vertical,
298
299 Rule::const_unit
300 | Rule::const_bool
301 | Rule::const_int
302 | Rule::const_float
303 | Rule::const_length
304 | Rule::const_string => Mode::Literal,
305
306 Rule::math_single
307 | Rule::math_list
308 | Rule::math_token
309 | Rule::math_sup
310 | Rule::math_sub
311 | Rule::math_unary => Mode::Math,
312
313 _ => return None,
314 };
315 Some(mode)
316 }
317
318 pub fn is_error(&self) -> bool {
319 self.error_description().is_some()
320 }
321
322 pub fn error_description(&self) -> Option<String> {
323 let text = match self {
324 Rule::dummy_header => "Missing Package name.",
325 Rule::dummy_stmt => "Missing definition of the statement.",
326 Rule::dummy_sig_stmt => "Incomplete signature syntax.",
327 Rule::dummy_inline_cmd_incomplete => {
328 "Incomplete inline command.\nTry adding semicolon or arguments after the command name."
329 }
330 Rule::dummy_block_cmd_incomplete => {
331 "Incomplete block command.\nTry adding semicolon or arguments after the command name."
332 }
333 _ => return None,
334 };
335 Some(text.to_owned())
336 }
337}