satysfi_parser/
grammar.rs

1#![allow(non_snake_case)]
2
3use crate::cst;
4use crate::types::rule::Rule;
5use crate::types::Span;
6use crate::types::{Cst, Vectorize};
7
8/// 様々な型の変数をごちゃまぜに書くと、それをまとめて Vec<T> にしてくれる。
9///
10/// ```
11/// #[macro_use] extern crate satysfi_parser;
12/// use satysfi_parser::types::Vectorize;
13/// let v: Vec<usize> = vectorize![1, vec![2, 3, 4], None, Some(5)];
14/// assert_eq!(v, vec![1, 2, 3, 4, 5])
15/// ```
16macro_rules! vectorize {
17    ($($e:expr),*) => {
18        vec![$($e.vectorize()),*].vectorize()
19    };
20}
21
22peg::parser! {
23    grammar satysfi_parser() for str {
24        use peg::ParseLiteral;
25        // §1. common
26
27        /// WHITESPACE
28        rule _() = spaces()
29        /// COMMENT
30        /// 水平モードにおいて空白は重要な情報だが、コメントは無視できる。
31        rule __() = comment()*
32
33        pub rule spaces() -> Vec<Span> =
34            ranges:([' ' | '\t' | '\n' | '\r'] {None} / range:comment() {Some(range)})*
35            {vectorize![ranges]}
36
37        /// alias for position
38        rule p() -> usize = pos:position!() {pos}
39
40        /// dummy pattern (never match)
41        rule DUMMY() = !"DUMMY" "DUMMY"
42        /// end of file
43        rule EOF() = ![_]
44
45        /// arbitrary character except line feed
46        rule NON_LF() = !['\r' | '\n'] [_]
47
48        /// constants
49        rule ASCII_DIGIT() = quiet!{['0'..='9']} / expected!("number")
50        rule ASCII_ALPHANUMERIC_HYPHEN() = quiet!{['a'..='z' | 'A'..='Z' | '0'..='9' | '-']} / expected!("alphabet, number, or hyphen")
51
52        /// keywords
53        /// 例えば kwd("let") とすると、
54        /// "let" にはマッチするが "leti" や "let-inline" にはマッチしなくなる。
55        rule kwd(word: &'static str) = ##parse_string_literal(word) !ASCII_ALPHANUMERIC_HYPHEN()
56
57        pub rule misc() -> Cst = DUMMY() { cst!(misc (0, 0) []) }
58
59        /// comment
60        rule comment() -> Span = "%" s:p() comment_inner() e:p() ['\r' | '\n'] { Span{ start: s, end: e } }
61        rule comment_inner() = NON_LF()*
62
63        // §1. program
64
65        pub rule program() -> Cst = p:(program_saty() / program_satyh()) EOF() {p}
66
67        pub rule program_saty() -> Cst =
68            s:p() _
69            stage:header_stage()? _
70            headers:headers() _
71            pre:(pre:preamble() _ kwd("in") {pre})? _
72            expr:expr() _
73            e:p()
74        { cst!(program_saty (s, e) [stage, headers, pre, expr]) }
75
76        pub rule program_satyh() -> Cst =
77            s:p() _
78            stage:header_stage()? _
79            headers:headers() _
80            pre:preamble() _
81            e:p()
82        { cst!(program_satyh (s, e) [stage, headers, pre]) }
83
84        // §1. header
85
86        rule header_stage() -> Cst =
87            "@stage:" [' ' | '\t']* stg:stage() [' ' | '\t']* ['\r' | '\n']
88        {stg}
89
90        pub rule stage() -> Cst =
91            s:p() ("0" / "1" / "persistent") e:p()
92        { cst!(stage (s, e) []) }
93
94        pub rule headers() -> Cst =
95            s:p() v:(h: header() _ {h})* e:p()
96        { cst!(headers (s, e) [v]) }
97
98        rule header() -> Cst = header_require() / header_import() / dummy_header()
99
100        pub rule header_require() -> Cst =
101            s:p() "@require:" [' ' | '\t']* pkg:pkgname() ['\n' | '\r'] e:p()
102        { cst!(header_require (s, e) [pkg]) }
103
104        pub rule header_import() -> Cst =
105            s:p() "@import:" [' ' | '\t']* pkg:pkgname() ['\n' | '\r'] e:p()
106        { cst!(header_import (s, e) [pkg]) }
107
108        pub rule dummy_header() -> Cst =
109            s:p()
110            (
111                ("@require:" / "@import") [' ' | '\t']* ['\n' | '\r']
112                / "@" var_ptn() ['\n' | '\r']
113                / "@" ['\n' | '\r']
114            )
115            e:p()
116        { cst!(dummy_header (s, e) []) }
117
118        pub rule pkgname() -> Cst =
119            s:p() NON_LF()+ e:p()
120        { cst!(pkgname (s, e) []) }
121
122        // §1. statement
123
124        pub rule preamble() -> Cst =
125            s:p() stmts:(statement() ++ _) e:p()
126        { cst!(preamble (s, e) [stmts]) }
127
128        #[cache]
129        rule statement() -> Cst =
130            let_stmt()
131            / let_rec_stmt()
132            / let_inline_stmt()
133            / let_block_stmt()
134            / let_math_stmt()
135            / let_mutable_stmt()
136            / type_stmt()
137            / module_stmt()
138            / open_stmt()
139            / dummy_stmt()
140
141        pub rule let_stmt() -> Cst =
142            s:p() kwd("let") _ pat:pattern() _ arg:let_stmt_argument()? _ "=" _ expr:expr() e:p()
143        { cst!(let_stmt (s, e) [pat, arg, expr]) }
144
145        rule let_stmt_argument() -> Vec<Cst> =
146            // TODO: type_expr は本当は txfunc
147            s:p() ":" _ t:type_expr() _ "|" _ a:(arg() ++ _) e:p() { vectorize![t, a] }
148            / s:p() ":" _ t:type_expr() e:p() { vectorize![t] }
149            / s:p() "|"? _ a:(arg() ++ _) e:p() { vectorize![a] }
150
151        pub rule let_rec_stmt() -> Cst =
152            s:p() kwd("let-rec") _ inner:let_rec_inner() _ inners:(let_rec_inner() ** (_ kwd("and") _)) e:p()
153        { cst!(let_rec_stmt (s, e) [inner, inners]) }
154
155        pub rule let_rec_inner() -> Cst =
156            s:p()
157            pat:pattern() _ arg:let_rec_stmt_argument()? _ "=" _ expr:expr()
158            _ arms:("|" _ arm:let_rec_matcharm() _ {arm})*
159            e:p()
160            { cst!(let_rec_inner (s, e) [pat, arg, expr, arms]) }
161            /
162            s:p()
163            pat:pattern() _ arms:("|" _ arm:let_rec_matcharm() _ {arm})*
164            e:p()
165            { cst!(let_rec_inner (s, e) [pat, arms]) }
166
167        rule let_rec_stmt_argument() -> Vec<Cst> =
168            s:p() ":" _ t:type_expr() _ "|" _ a:(arg() ++ _) e:p() { vectorize![t, a] }
169            / s:p() ":" _ t:type_expr() e:p() { vectorize![t] }
170            / s:p() a:(arg() ++ _) e:p() { vectorize![a] }
171
172        pub rule let_rec_matcharm() -> Cst =
173            s:p() a:(arg() ** _) _ "=" _ expr:expr() e:p()
174        { cst!(let_rec_matcharm (s, e) [a, expr]) }
175
176        rule let_inline_stmt() -> Cst = let_inline_stmt_ctx() / let_inline_stmt_noctx()
177        pub rule let_inline_stmt_ctx() -> Cst =
178            s:p() kwd("let-inline") _ ctx:var() _ cmd:inline_cmd_name() _ a:(arg() ** _) _ "=" _ expr:expr() e:p()
179        { cst!(let_inline_stmt_ctx (s, e) [ctx, cmd, a, expr]) }
180        pub rule let_inline_stmt_noctx() -> Cst =
181            s:p() kwd("let-inline") _ cmd:inline_cmd_name() _ pat:(pattern() ** _) _ "=" _ expr:expr() e:p()
182        { cst!(let_inline_stmt_noctx (s, e) [cmd, pat, expr]) }
183
184        rule let_block_stmt() -> Cst = let_block_stmt_ctx() / let_block_stmt_noctx()
185        pub rule let_block_stmt_ctx() -> Cst =
186            s:p() kwd("let-block") _ ctx:var() _ cmd:block_cmd_name() _ a:(arg() ** _) _ "=" _ expr:expr() e:p()
187        { cst!(let_block_stmt_ctx (s, e) [ctx, cmd, a, expr]) }
188        pub rule let_block_stmt_noctx() -> Cst =
189            s:p() kwd("let-block") _ cmd:block_cmd_name() _ pat:(pattern() ** _) _ "=" _ expr:expr() e:p()
190        { cst!(let_block_stmt_noctx (s, e) [cmd, pat, expr]) }
191
192        pub rule let_math_stmt() -> Cst =
193            s:p() kwd("let-math") _ cmd:math_cmd_name() _ a:(arg() ** _) _ "=" _ expr:expr() e:p()
194        { cst!(let_math_stmt (s, e) [cmd, a, expr]) }
195
196        pub rule let_mutable_stmt() -> Cst =
197            s:p() kwd("let-mutable") _ var:var() _ "<-" _ expr:expr() e:p()
198        { cst!(let_mutable_stmt (s, e) [var, expr]) }
199
200        pub rule type_stmt() -> Cst =
201            s:p() kwd("type") _ ts:(type_inner() ++ (_ kwd("and") _)) e:p()
202        { cst!(type_stmt (s, e) [ts]) }
203
204        pub rule type_inner() -> Cst =
205            s:p()
206            tp:(type_param() ** _) _ t:type_name() _ "=" tvs:(_ "|" _ tv:type_variant() {tv})+ _ c:constraint()*
207            e:p()
208            { cst!(type_inner (s, e) [tp, t, tvs, c]) }
209            /
210            s:p()
211            tp:(type_param() ** _) _ t:type_name() _ "=" _ tvs:(type_variant() ++  (_ "|" _)) _ c:constraint()*
212            e:p()
213            { cst!(type_inner (s, e) [tp, t, tvs, c]) }
214            /
215            s:p()
216            tp:(type_param() ** _) _ t:type_name() _ "=" _ te:type_expr() _ c:constraint()*
217            e:p()
218            { cst!(type_inner (s, e) [tp, t, te, c]) }
219
220        pub rule type_variant() -> Cst =
221            s:p() v:variant_name() _ kwd("of") _ t:type_expr() e:p() { cst!(type_variant (s, e) [v, t]) }
222            / s:p() v:variant_name() e:p() { cst!(type_variant (s, e) [v]) }
223
224        pub rule open_stmt() -> Cst =
225            s:p() kwd("open") _ m:module_name() e:p()
226        { cst!(open_stmt (s, e) [m]) }
227
228        pub rule dummy_stmt() -> Cst =
229            s:p()
230            (kwd("let") / kwd("module") / kwd("type")) _ var() ** _
231            e:p()
232        { cst!(dummy_stmt (s, e) []) }
233
234        pub rule arg() -> Cst =
235            s:p() p:pattern() e:p() { cst!(arg (s, e) [p]) }
236            / s:p() "?:" _ p:var_ptn() e:p() { cst!(arg (s, e) [p]) }
237
238        // §1. module
239
240        pub rule module_stmt() -> Cst =
241            s:p()
242            kwd("module") _ n:module_name() _
243            sig:(":" _ s:sig_stmt() {s})? _
244            "=" _ stmt:struct_stmt()
245            e:p()
246        { cst!(module_stmt (s, e) [n, sig, stmt]) }
247
248        pub rule sig_stmt() -> Cst =
249            s:p() kwd("sig") _ inners:(sig_inner() ** _) _ kwd("end") e:p()
250        { cst!(sig_stmt (s, e) [inners]) }
251
252        pub rule struct_stmt() -> Cst =
253            s:p() kwd("struct") _ stmts:(statement() ** _) _ kwd("end") e:p()
254        { cst!(struct_stmt (s, e) [stmts]) }
255
256        rule sig_inner() -> Cst = sig_type_stmt() / sig_val_stmt() / sig_direct_stmt() / dummy_sig_stmt()
257
258        pub rule sig_type_stmt() -> Cst =
259            s:p() kwd("type") _ tps:(type_param() ** _) _ v:var() _ cs:(constraint() ** _) e:p()
260        { cst!(sig_type_stmt (s, e) [tps, v, cs]) }
261
262        pub rule sig_val_stmt() -> Cst =
263            s:p()
264            kwd("val") _
265            v:(var() / "(" _ b:bin_operator() _ ")" {b} / inline_cmd_name() / block_cmd_name()) _
266            ":" _ t: type_expr() _ cs:(constraint() ** _)
267            e:p()
268        { cst!(sig_val_stmt (s, e) [v, t, cs]) }
269
270        pub rule sig_direct_stmt() -> Cst =
271            s:p()
272            kwd("direct") _
273            cmd:(inline_cmd_name() / block_cmd_name()) _
274            ":" _ t: type_expr() _ cs:(constraint() ** _)
275            e:p()
276        { cst!(sig_direct_stmt (s, e) [cmd, t, cs]) }
277
278        pub rule dummy_sig_stmt() -> Cst =
279            s:p()
280            !kwd("end") _ var_ptn()
281            e:p()
282        { cst!(dummy_sig_stmt (s, e) []) }
283
284        // §1. types
285
286        pub rule type_expr() -> Cst =
287            s:p()
288            typeprods:(
289                t:type_optional() _ "?->" _ {t}
290                /
291                t:type_prod() _ "->" _ {t}
292            )* _
293            typeprod:type_prod()
294            e:p()
295        { cst!(type_expr (s, e) [typeprods, typeprod]) }
296
297        pub rule type_optional() -> Cst = s:p() t:type_prod() e:p() { cst!(type_optional (s, e) [t.inner]) }
298
299        pub rule type_prod() -> Cst =
300            s:p() t:type_unary() ts:(_ "*" _ t:type_unary() {t})* e:p()
301        { cst!(type_prod (s, e) [t, ts]) }
302
303        #[cache]
304        rule type_unary() -> Cst =
305            type_inline_cmd()
306            / type_block_cmd()
307            / type_math_cmd()
308            / type_application()
309            / "(" _ t:type_expr() _ ")" {t}
310            / type_record()
311            / type_param()
312
313        pub rule type_inline_cmd() -> Cst = s:p() t:type_list() _ kwd("inline-cmd") e:p() { cst!(type_inline_cmd (s, e) [t]) }
314        pub rule type_block_cmd() -> Cst = s:p() t:type_list() _ kwd("block-cmd") e:p() { cst!(type_block_cmd (s, e) [t]) }
315        pub rule type_math_cmd() -> Cst = s:p() t:type_list() _ kwd("math-cmd") e:p() { cst!(type_math_cmd (s, e) [t]) }
316
317        rule type_list() -> Vec<Cst> =
318            s:p() "[" _ "]" e:p() { vec![] }
319            / s:p() "[" _ t:type_list_unit()
320                ts:(_ ";" _ t:type_list_unit() {t})* _
321                ";"? _ "]" e:p()
322                { vectorize![t, ts] }
323
324        rule type_list_unit() -> Cst =
325            type_list_unit_optional()
326            / type_expr()
327
328        pub rule type_list_unit_optional() -> Cst =
329            s:p() t:type_prod() _ "?" e:p()
330        { cst!(type_list_unit_optional (s, e) [t]) }
331
332        pub rule type_application() -> Cst =
333            s:p() t:type_application_unit() _ ts:(type_application_unit()** _) e:p()
334        { cst!(type_application (s, e) [t, ts]) }
335
336        rule type_application_unit() -> Cst =
337            "(" _ t:type_expr() _ ")" {t}
338            / type_param()
339            / type_name()
340
341        pub rule type_name() -> Cst =
342            s:p() t:(var() / modvar()) e:p()
343        { cst!(type_name (s, e) [t]) }
344
345        pub rule type_record() -> Cst =
346            s:p() "(|" _ "|)" e:p() { cst!(type_record (s, e) []) }
347            / s:p() "(|" _ ts:(type_record_unit() ++ (_ ";" _)) _ ";"? _ "|)" e:p() { cst!(type_record (s, e) [ts]) }
348
349        pub rule type_record_unit() -> Cst =
350            s:p() v:var() _ ":" _ t:type_expr() e:p()
351        { cst!(type_record_unit (s, e) [v, t]) }
352
353        pub rule type_param() -> Cst =
354            s:p() "'" t:var_ptn() e:p()
355        { cst!(type_param (s, e) [t]) }
356
357        pub rule constraint() -> Cst =
358            s:p() kwd("constraint") _ t:type_param() _ "::" _ r:type_record() e:p()
359        { cst!(constraint (s, e) [t, r]) }
360
361        // §1. pattern
362
363        pub rule pat_as() -> Cst =
364            s:p() p:pat_cons() v:(_ kwd("as") _ v:var() {v})? e:p() { cst!(pat_as (s, e) [p, v]) }
365
366        #[cache]
367        pub rule pat_cons() -> Cst =
368            s:p() p:pattern() _ "::" _ m:pat_as() e:p() { cst!(pat_cons (s, e) [p, m]) }
369            / s:p() p:pat_variant() e:p() { cst!(pat_cons (s, e) [p]) }
370            / s:p() p:pattern() e:p() { cst!(pat_cons (s, e) [p]) }
371
372        #[cache]
373        pub rule pattern() -> Cst =
374            s:p() p:pat_list() e:p() { cst!(pattern (s, e) [p]) }
375            / s:p() "(" _ b:bin_operator() _ ")" e:p() { cst!(pattern (s, e) [b]) }
376            / s:p() "(" _ u:unary_operator() _ ")" e:p() { cst!(pattern (s, e) [u]) }
377            / s:p() "(" _ p:pat_as() _ ")" e:p() { cst!(pattern (s, e) [p]) }
378            / s:p() p:pat_tuple() e:p() { cst!(pattern (s, e) [p]) }
379            / s:p() "_" e:p() { cst!(pattern (s, e) []) }
380            / s:p() "~"? v:var() e:p() { cst!(pattern (s, e) [v]) }
381            / s:p() l:constant() e:p() { cst!(pattern (s, e) [l]) }
382
383        pub rule pat_variant() -> Cst =
384            s:p() v:variant_name() _ p:pattern()? e:p()
385        { cst!(pat_variant (s, e) [v, p]) }
386
387        pub rule pat_list() -> Cst =
388            s:p() "[" _ "]" e:p() { cst!(pat_list (s, e) []) }
389            / s:p() "[" _ ms:(pat_as() ** (_ ";" _)) _ ";"? _ "]" e:p() { cst!(pat_list (s, e) [ms]) }
390
391        pub rule pat_tuple() -> Cst =
392            s:p() "(" _ m:pat_as() _ "," _ ms:(pat_as() ++ (_ "," _)) _ ")" e:p()
393            { cst!(pat_tuple (s, e) [m, ms]) }
394
395        // §1. expr
396        pub rule expr() -> Cst =
397            s:p() expr:(
398                match_expr()
399                / bind_stmt()
400                / ctrl_while()
401                / ctrl_if()
402                / lambda()
403                / assignment()
404                / dyadic_expr()
405                / unary_operator_expr()
406                / command_application()
407                / application()
408                / unary()
409                / variant_constructor()
410            ) e:p()
411        { cst!(expr (s, e) [expr]) }
412
413        pub rule match_expr() -> Cst =
414            s:p() kwd("match") _ expr:expr() _ kwd("with") _ "|"? _ arms:(match_arm() ** (_ "|" _)) e:p()
415        { cst!(match_expr (s, e) [expr, arms]) }
416
417        pub rule bind_stmt() -> Cst =
418            s:p() stmt:(let_stmt() / let_rec_stmt() / let_math_stmt() / let_mutable_stmt() / open_stmt())
419            _ kwd("in") _ expr:expr() e:p()
420        { cst!(bind_stmt (s, e) [stmt, expr]) }
421
422        pub rule match_arm() -> Cst =
423            s:p()
424            ptn:pat_as() _ guard:match_guard()? _ "->" _ expr:(!match_expr() e:expr() {e})
425            e:p()
426            { cst!(match_arm (s, e) [ptn, guard, expr]) }
427
428        pub rule match_guard() -> Cst =
429            s:p()
430            kwd("when") _ cond:(!match_expr() e:expr() {e})
431            e:p()
432            { cst!(match_guard (s, e) [cond]) }
433
434        pub rule ctrl_while() -> Cst =
435            s:p() kwd("while") _ cond:expr() _ kwd("do") _
436            expr:(!(match_expr() / bind_stmt()) e:expr() {e})
437            e:p()
438        { cst!(ctrl_while (s, e) [cond, expr]) }
439
440        pub rule ctrl_if() -> Cst =
441            s:p() kwd("if") _ cond:expr() _ kwd("then") _ et:expr() _ kwd("else") _ ee:expr() e:p()
442        { cst!(ctrl_if (s, e) [cond, et, ee]) }
443
444        pub rule lambda() -> Cst =
445            s:p() kwd("fun") _ ptns:(pattern() ++ _) _ "->" _ expr: expr_inner_lambda() e:p()
446        { cst!(lambda (s, e) [ptns, expr]) }
447
448        pub rule assignment() -> Cst =
449            s:p() v:var() _ "<-" _ expr: expr_inner_lambda() e:p()
450        { cst!(assignment (s, e) [v, expr]) }
451
452        rule expr_inner_lambda() -> Cst =
453            dyadic_expr() / unary_operator_expr() / application() / unary() / variant_constructor()
454
455        pub rule dyadic_expr() -> Cst =
456            s:p()
457            t1:(unary_operator_expr() / application() / unary() / variant_constructor())
458            _ op:bin_operator()
459            _ t2:(dyadic_expr() / application() / unary() / variant_constructor())
460            e:p()
461        { cst!(dyadic_expr (s, e) [t1, op, t2]) }
462
463        pub rule unary_operator_expr() -> Cst =
464            s:p() op:unary_operator() _ expr:(application() / unary()) e:p()
465        { cst!(unary_operator_expr (s, e) [op, expr]) }
466
467        pub rule unary_operator() -> Cst =
468            s:p() ("-" / kwd("not") ) e:p()
469        { cst!(unary_operator (s, e) []) }
470
471        pub rule application() -> Cst =
472            s:p()
473            v:(unary()) _
474            args:(application_args() ++ _)
475            e:p()
476        { cst!(application (s, e) [v, args]) }
477
478        rule application_args() -> Cst = application_args_optional() / application_args_normal()
479
480        pub rule application_args_optional() -> Cst =
481            s:p() "?:" _ u:(unary()) e:p() { cst!(application_args_optional (s, e) [u]) }
482            / s:p() "?*" e:p() { cst!(application_args_optional (s, e) []) }
483
484        pub rule application_args_normal() -> Cst =
485            s:p() u:(unary() / variant_name()) e:p()
486        { cst!(application_args_normal (s, e) [u]) }
487
488        pub rule command_application() -> Cst =
489            s:p() kwd("command") _ n:inline_cmd_name() e:p()
490        { cst!(command_application (s, e) [n]) }
491
492        pub rule variant_constructor() -> Cst =
493            s:p() v:variant_name() _ u:unary()? e:p()
494        { cst!(variant_constructor (s, e) [v, u]) }
495
496        // §1. unary
497
498        #[cache]
499        pub rule unary() -> Cst =
500            s:p()
501            prefix:(p:unary_prefix() _ {p})?
502            body:((
503                block_text()
504                / horizontal_text()
505                / math_text()
506                / record()
507                / list()
508                / tuple()
509                / "(" _ op:bin_operator() _ ")" {op}
510                / "(" _ expr:expr() _ ")" {expr}
511                / constant()
512                / expr_with_mod()
513                / modvar()
514                / var()
515                / dummy_modvar_incomplete()
516            ) ++ (_ "#" _))
517            e:p()
518        { cst!(unary (s, e) [prefix, body]) }
519
520        pub rule unary_prefix() -> Cst = s:p() ("!" / "&" / "~") e:p() { cst!(unary_prefix (s, e) []) }
521
522        pub rule block_text() -> Cst =
523            s:p() "'" v:vertical() e:p()
524        { cst!(block_text (s, e) [v]) }
525
526        pub rule horizontal_text() -> Cst =
527            s:p() h:horizontal() e:p()
528        { cst!(horizontal_text (s, e) [h]) }
529
530        pub rule math_text() -> Cst =
531            s:p() "${" _ m:math() _ "}" e:p()
532        { cst!(math_text (s, e) [m]) }
533
534        pub rule record() -> Cst =
535            s:p() "(|" _ "|)" e:p() { cst!(record (s, e) []) }
536            / s:p() "(|" _ u:unary() _ kwd("with") _ i:record_inner() _ "|)" e:p() { cst!(record (s, e) [u, i]) }
537            / s:p() "(|" _ i:record_inner() _ "|)" e:p() { cst!(record (s, e) [i]) }
538
539        rule record_inner() -> Vec<Cst> =
540            s:p() units:(record_unit() ++ (_ ";" _)) _ ";"? e:p()
541        { units }
542
543        pub rule record_unit() -> Cst =
544            s:p() v:var_ptn() _ "=" _ expr:expr() e:p()
545        { cst!(record_unit (s, e) [v, expr]) }
546
547        pub rule list() -> Cst =
548            s:p() "[" _ "]" e:p() { cst!(list (s, e) []) }
549            / s:p() "[" _ exprs:(expr() ++ (_ ";" _)) _ ";"? _ "]" e:p() { cst!(list (s, e) [exprs]) }
550
551        pub rule tuple() -> Cst =
552            s:p() "(" _ expr:expr() _ "," _ exprs:(expr() ++ (_ "," _)) _ ")" e:p() { cst!(tuple (s, e) [expr, exprs]) }
553
554        pub rule bin_operator() -> Cst =
555            s:p() !bin_operator_except() (bin_operator_start() bin_operator_succ()* / "::" / kwd("mod")) e:p()
556        { cst!(bin_operator (s, e) []) }
557        rule bin_operator_start() =
558            [ '-' | '+' | '*' | '/' | '^' | '&' | '|' | '=' | '<' | '>' ]
559        rule bin_operator_succ() =
560            [ '-' | '+' | '*' | '/' | '^' | '&' | '|' | '=' | '<' | '>'
561                  | '!' | ':' | '~' | '\'' | '.' | '?' ]
562        rule bin_operator_except() = ("->" / "<-" / "|") !bin_operator_succ()
563
564        pub rule expr_with_mod() -> Cst =
565            s:p() m:module_name() ".(" _ expr:expr() _ ")" e:p()
566        { cst!(expr_with_mod (s, e) [m, expr]) }
567
568        pub rule var() -> Cst =
569            s:p() !(reserved_word() !ASCII_ALPHANUMERIC_HYPHEN()) var_ptn() e:p()
570        { cst!(var (s, e) []) }
571
572        pub rule var_ptn() -> Cst =
573            s:p() ['a'..='z'] ASCII_ALPHANUMERIC_HYPHEN()* e:p()
574        { cst!(var_ptn (s, e) []) }
575
576        pub rule dummy_modvar_incomplete() -> Cst =
577            s:p() module_name() "." e:p()
578            { cst!(dummy_modvar_incomplete (s, e) []) }
579
580        // 予約語たち
581        rule reserved_word() =
582            ( "constraint"
583            / "inline-cmd" / "block-cmd" / "math-cmd"
584            / "let-mutable" / "let-inline" / "let-block" / "let-math" / "let-rec"
585            / "controls" / "command" / "before" / "module" / "direct" / "struct"
586            / "cycle" / "match" / "while" / "false"
587            / "else" / "open" / "then" / "true" / "type" / "when" / "with"
588            / "and" / "end" / "fun" / "let" / "mod" / "not" / "sig" / "val"
589            / "as" / "do" / "if" / "in" / "of")
590
591
592        pub rule modvar() -> Cst =
593            s:p() modname:module_name() "." var:var_ptn() e:p()
594        { cst!(modvar (s, e) [modname, var]) }
595
596        pub rule mod_cmd_name() -> Cst =
597            s:p() modname:module_name() "." var:cmd_name_ptn() e:p()
598        { cst!(mod_cmd_name (s, e) [modname, var]) }
599
600        pub rule module_name() -> Cst =
601            s:p() ['A' ..= 'Z'] ASCII_ALPHANUMERIC_HYPHEN()* e:p()
602        { cst!(module_name (s, e) []) }
603
604        pub rule variant_name() -> Cst =
605            s:p() ['A' ..= 'Z'] ASCII_ALPHANUMERIC_HYPHEN()* e:p()
606        { cst!(variant_name (s, e) []) }
607
608        // §1. constants
609        rule constant() -> Cst =
610            const_unit()
611            / const_bool()
612            / const_string()
613            / const_float()
614            / const_length()
615            / const_int()
616
617        pub rule const_unit() -> Cst =
618            s:p() "(" _ ")" e:p() { cst!(const_unit (s, e) []) }
619
620        pub rule const_bool() -> Cst =
621            s:p() (kwd("true") / kwd("false")) e:p() {cst!(const_bool (s, e) [])}
622
623        pub rule const_int() -> Cst =
624            s:p() (const_int_decimal() / const_int_hex() / "0") e:p() { cst!(const_int (s, e) []) }
625        rule const_int_decimal() = ['1'..='9'] ASCII_DIGIT()*
626        rule const_int_hex() = "0" ['x' | 'X'] ['0'..='9' | 'A'..='F']+
627
628        pub rule const_float() -> Cst =
629            s:p() const_float_inner() !length_unit() e:p()
630            { cst!(const_float (s, e) []) }
631        rule const_float_inner() = ASCII_DIGIT()+ "." ASCII_DIGIT()* / "." ASCII_DIGIT()+
632
633        pub rule const_length() -> Cst =
634            s:p() length_digit() length_unit() e:p()
635            { cst!(const_length (s, e) []) }
636
637        rule length_digit() = "-"? (const_float_inner() / const_int_decimal() / "0")
638        rule length_unit() = ['a'..='z'] ['0'..='9' | 'a'..='z' | 'A' ..='Z' | '-']*
639
640        pub rule const_string() -> Cst =
641            s:p() "@"? "#"? qs:string_quotes() (!string_inner(qs) [_])+ qe:string_quotes() "#"? e:p()
642            {?
643                if qs == qe {
644                    Ok(cst!(const_string (s, e) []))
645                } else {
646                    Err("number of back quotation does not match.")
647                }
648            }
649        rule string_quotes() -> usize = n:"`"+ {n.len()}
650        rule string_inner(qs: usize) = "`"*<{qs}>
651
652        // §1. commands
653        pub rule inline_cmd() -> Cst = (
654            s:p() name:inline_cmd_name() _
655            opt:((cmd_expr_arg() / cmd_expr_option())** _) _ opttext:(";" {vec![]} / cmd_text_arg() ++ _) e:p()
656            {
657                cst!(inline_cmd (s, e) [name, opt, opttext])
658            }
659        )
660
661        pub rule inline_cmd_name() -> Cst =
662            s:p() r"\" inner:(mod_cmd_name() / cmd_name_ptn()) "@"? e:p()
663        { cst!(inline_cmd_name (s, e) [inner]) }
664
665        pub rule cmd_name_ptn() -> Cst =
666            s:p() ['A'..='Z' | 'a'..='z'] ASCII_ALPHANUMERIC_HYPHEN()* e:p()
667        { cst!(cmd_name_ptn (s, e) []) }
668
669        pub rule block_cmd() -> Cst = (
670            s:p() name:block_cmd_name() _
671            opt:((cmd_expr_arg() / cmd_expr_option())** _) _ opttext:(";" {vec![]} / cmd_text_arg() ++ _) e:p()
672            {
673                cst!(block_cmd (s, e) [name, opt, opttext])
674            }
675        )
676
677        pub rule block_cmd_name() -> Cst =
678            s:p() "+" inner:(mod_cmd_name() / cmd_name_ptn()) "@"? e:p()
679        { cst!(block_cmd_name (s, e) [inner]) }
680
681        pub rule cmd_expr_arg() -> Cst =
682            s:p() inner:cmd_expr_arg_inner() e:p() { cst!(cmd_expr_arg (s, e) [inner]) }
683
684        pub rule cmd_expr_option() -> Cst =
685            s:p() "?:" _ inner:cmd_expr_arg_inner() e:p() { cst!(cmd_expr_option (s, e) [inner]) }
686            / s:p() "?*" e:p() { cst!(cmd_expr_option (s, e) []) }
687
688        rule cmd_expr_arg_inner() -> Cst =
689            const_unit()
690            / list()
691            / record()
692            / "~"? "(" _ expr:expr() _ ")" { expr }
693
694        pub rule cmd_text_arg() -> Cst =
695            s:p()
696            inner:(vertical() / horizontal())
697            e:p()
698        { cst!(cmd_text_arg (s, e) [inner]) }
699
700        pub rule math_cmd() -> Cst =
701            s:p() cmd:math_cmd_name() _ args:((math_cmd_expr_arg() / math_cmd_expr_option()) ** _) e:p()
702        { cst!(math_cmd (s, e) [cmd, args]) }
703
704        pub rule math_cmd_name() -> Cst =
705            s:p() r"\" inner:(mod_cmd_name() / cmd_name_ptn()) e:p()
706        { cst!(math_cmd_name (s, e) [inner]) }
707
708        pub rule math_cmd_expr_arg() -> Cst =
709            s:p() arg:math_cmd_expr_arg_inner() e:p() { cst!(math_cmd_expr_arg (s, e) [arg]) }
710
711        pub rule math_cmd_expr_option() -> Cst =
712            s:p() "?:" _ arg:math_cmd_expr_arg_inner() e:p() { cst!(math_cmd_expr_option (s, e) [arg]) }
713
714        rule math_cmd_expr_arg_inner() -> Cst =
715            "{" _ m:math() _ "}" {m}
716            / "!" h:horizontal() {h}
717            / "!" v:vertical() {v}
718            / "!(" _ expr:expr() _ ")" {expr}
719            / "!" l:list() {l}
720            / "!" r:record() {r}
721
722        // rule math_cmd_list_arg() -> Cst =
723        //     s:p() "![" _ exprs:(expr() ** (_ ";" _)) _ "]" e:p() { cst!((s, e) [exprs]) }
724        //
725        // rule math_cmd_record_arg() -> Cst =
726        //     s:p() "!(" _ "|" _ "|" _ ")" e:p() { cst!((s, e)) }
727        //     / s:p() "!(" _ "|" _ u:unary() _ "with" _ i:record_inner() _ "|" _ ")" e:p() { cst!((s, e) [u, i]) }
728        //     / s:p() "!(" _ "|" _ i:record_inner() _ "|" _ ")" e:p() { cst!((s, e) [i]) }
729
730        // §1. horizontal mode
731        rule horizontal() -> Cst =
732            // horizontal の前後空白は regular_text で食う
733            "{"
734            h:(
735            horizontal_list()
736            / horizontal_bullet_list()
737            / horizontal_single()
738            )
739            "}"
740            {h}
741
742        pub rule horizontal_single() -> Cst =
743            s:p() __ inners:(horizontal_token() ** __) __ e:p() { cst!(horizontal_single (s, e) [inners]) }
744
745        rule horizontal_token() -> Cst =
746            const_string()
747            / inline_cmd()
748            / inline_text_embedding()
749            / math_text()
750            / horizontal_escaped_char()
751            / regular_text()
752            / dummy_inline_cmd_incomplete()
753
754        pub rule inline_text_embedding() -> Cst =
755            s:p() "#" inner:(var_ptn() / modvar()) _ ";" e:p()
756        { cst!(inline_text_embedding (s, e) [inner]) }
757
758        pub rule regular_text() -> Cst =
759            s:p() $(!horizontal_special_char() [_])+ e:p()
760        { cst!(regular_text (s, e) []) }
761
762        pub rule dummy_inline_cmd_incomplete() -> Cst =
763            s:p()
764            "\\" (var_ptn() / modvar() / dummy_modvar_incomplete())?
765            e:p()
766        { cst!(dummy_inline_cmd_incomplete (s, e) []) }
767
768        pub rule horizontal_escaped_char() -> Cst =
769            s:p() "\\" (horizontal_special_char() / horizontal_escapable()) e:p()
770        { cst!(horizontal_escaped_char (s, e) []) }
771
772        rule horizontal_special_char() =
773            ['@' | '`' | '\\' | '{' | '}' | '%' | '|' | '*' | '$' | '#' | ';']
774
775        rule horizontal_escapable() =
776            ['[' | ']' | '(' | ')' | ' ']
777
778        pub rule horizontal_list() -> Cst =
779            s:p() _ "|" inners:horizontal_list_inner()+ _ e:p()
780            { cst!(horizontal_list (s, e) [inners]) }
781        rule horizontal_list_inner() -> Cst = inner:horizontal_single() "|" {inner}
782
783        pub rule horizontal_bullet_list() -> Cst =
784            s:p() inners:horizontal_bullet()+ e:p() { cst!(horizontal_bullet_list (s, e) [inners]) }
785
786        pub rule horizontal_bullet() -> Cst =
787            s:p()
788            _ star:horizontal_bullet_star() _ single:horizontal_single() _
789            e:p()
790            { cst!(horizontal_bullet (s, e) [star, single]) }
791
792        pub rule horizontal_bullet_star() -> Cst =
793            s:p() "*"+ e:p()
794            { cst!(horizontal_bullet_star (s, e) []) }
795
796        // §1. vertical mode
797
798        pub rule vertical() -> Cst =
799            s:p() "<" _ vs:(vertical_element() ** _) _ ">" e:p()
800        { cst!(vertical (s, e) [vs]) }
801
802        rule vertical_element() -> Cst = block_cmd() / block_text_embedding() / dummy_block_cmd_incomplete()
803
804        pub rule block_text_embedding() -> Cst =
805            s:p() "#" inner:(var_ptn() / modvar()) _ ";" e:p()
806        { cst!(block_text_embedding (s, e) [inner]) }
807
808        pub rule dummy_block_cmd_incomplete() -> Cst =
809            s:p()
810            "+" (var_ptn() / modvar() / dummy_modvar_incomplete())?
811            e:p()
812        { cst!(dummy_block_cmd_incomplete (s, e) []) }
813
814        // §1. math mode
815
816        rule math() -> Cst = math_list() / math_single()
817
818        pub rule math_list() -> Cst =
819            s:p() "|" ms:(_ m:math_single() _ "|" {m})+ e:p() { cst!(math_list (s, e) [ms]) }
820
821        pub rule math_single() -> Cst =
822            s:p() ts:(math_token() ** _) e:p()
823        { cst!(math_single (s, e) [ts]) }
824
825        pub rule math_token() -> Cst =
826            s:p() u:math_unary() _ sup:math_sup() _ sub:math_sub() e:p() { cst!(math_token (s, e) [u, sup, sub]) }
827            / s:p() u:math_unary() _ sub:math_sub() _ sup:math_sup() e:p() { cst!(math_token (s, e) [u, sub, sup]) }
828            / s:p() u:math_unary() _ sup:math_sup() e:p() { cst!(math_token (s, e) [u, sup]) }
829            / s:p() u:math_unary() _ sub:math_sub() e:p() { cst!(math_token (s, e) [u, sub]) }
830            / s:p() u:math_unary() e:p() { cst!(math_token (s, e) [u]) }
831
832        pub rule math_sup() -> Cst = "^" s:p() _ g:math_group() e:p() { cst!(math_sup (s, e) [g]) }
833        pub rule math_sub() -> Cst = "_" s:p() _ g:math_group() e:p() { cst!(math_sub (s, e) [g]) }
834        rule math_group() -> Cst = "{" _ m:math_single() _ "}" {m} / math_unary()
835
836        pub rule math_unary() -> Cst =
837            s:p() [^ '+' | '-' | '*' | '/' | ':' | '=' | '<' | '>' | '~' | '.' | ',' | '`' | '?' | ' ' |
838                    '\t' | '\n' | '\r' | '\\' | '{' | '}' | '%' | '|' | '$' | '#' | ';' | '\'' | '^' | '_' | '!' ] e:p() {
839                        cst!(math_unary (s, e) []) 
840            }
841            / s:p() r"\" math_special_char() e:p() { cst!(math_unary (s, e) []) }
842            / s:p() math_symbol() e:p() { cst!(math_unary (s, e) []) }
843            / s:p() m:math_cmd() e:p() { cst!(math_unary (s, e) [m]) }
844            / s:p() m:math_embedding() e:p() { cst!(math_unary (s, e) [m]) }
845
846        pub rule math_embedding() -> Cst =
847            s:p() "#" inner:(var_ptn() / modvar()) e:p()
848        { cst!(math_embedding (s, e) [inner]) }
849
850        rule math_special_char() = [
851            ' ' | '!' | '"' | '#' | '$' | '%' | '&' | '\''
852                | '(' | ')' | '*' | '+' | ',' | '-' | '.' | '/'
853                | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
854                | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '[' | '\\'
855                | ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~'
856            ]
857        rule math_symbol() =
858            ['-' | '+' | '*' | '/' | ':' | '=' | '<' | '>' | '~' | '\'' | '.' | ',' | '?' | '`']+
859
860    }
861}
862
863pub use self::satysfi_parser::*;