satysfi_parser/types/
rule.rs

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
27// TODO: expand macro when all implementation has done
28make_rule! {
29    misc,
30
31    program_saty,
32    program_satyh,
33    preamble,
34
35    // header
36    stage,
37    headers,
38    header_require,
39    header_import,
40    pkgname,
41
42    // statement
43    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    // struct
61    sig_stmt,
62    struct_stmt,
63    sig_type_stmt,
64    sig_val_stmt,
65    sig_direct_stmt,
66
67    // types
68    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    // pattern
83    pat_as,
84    pat_cons,
85    pattern,
86    pat_variant,
87    pat_list,
88    pat_tuple,
89
90    // expr
91    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
110    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    // command
129    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
143    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    // constants
156    const_unit,
157    const_bool,
158    const_int,
159    const_float,
160    const_length,
161    const_string,
162
163    // math
164    math_single,
165    math_list,
166    math_token,
167    math_sup,
168    math_sub,
169    math_unary,
170    math_embedding,
171
172    // dummy
173    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    /// プログラムモード
184    Program,
185    /// プログラムモードのうち、型を記述する箇所
186    ProgramType,
187    /// 垂直モード
188    Vertical,
189    /// 水平モード
190    Horizontal,
191    /// 数式モード
192    Math,
193    /// ヘッダ
194    Header,
195    /// リテラル
196    Literal,
197    /// コメント(不使用)
198    Comment,
199}
200
201impl Rule {
202    /// Mode が一意に定まるときは Mode を出力する。
203    /// たとえば horizontal_single であれば水平モードであることが分かるため
204    /// Some(Mode::Horizontal) を出力するが、
205    /// var_ptn であれば不明のため None を返す。
206    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}