Skip to main content

graphix_compiler/expr/parser/
mod.rs

1use crate::{
2    expr::{
3        set_origin, BindExpr, Doc, Expr, ExprKind, ModPath, Origin, Pattern, SelectExpr,
4        Sig, SigItem, StructExpr, StructWithExpr, TryCatchExpr,
5    },
6    typ::{FnType, Type},
7};
8use arcstr::{literal, ArcStr};
9use combine::{
10    attempt, between, choice, eof, look_ahead, many, none_of, not_followed_by, optional,
11    parser::{
12        char::{space, string},
13        combinator::recognize,
14        range::{take_while, take_while1},
15    },
16    position, sep_by1, skip_many,
17    stream::{
18        position::{self, SourcePosition},
19        Range,
20    },
21    token, unexpected_any, value, EasyParser, ParseError, Parser, RangeStream,
22};
23use compact_str::CompactString;
24use escaping::Escape;
25use fxhash::FxHashSet;
26use netidx::{path::Path, publisher::Value};
27use netidx_value::parser::{
28    escaped_string, int, not_prefix, sep_by1_tok, sep_by_tok, value as parse_value,
29    VAL_ESC, VAL_MUST_ESC,
30};
31use poolshark::local::LPooled;
32use std::sync::LazyLock;
33use triomphe::Arc;
34
35mod interpolateexp;
36use interpolateexp::interpolated;
37
38mod modexp;
39use modexp::{module, sig_item, use_module};
40
41mod typexp;
42use typexp::{fntype, typ, typedef};
43
44mod lambdaexp;
45use lambdaexp::{apply, lambda};
46
47mod arrayexp;
48use arrayexp::{array, arrayref};
49
50pub(crate) mod arithexp;
51use arithexp::arith;
52
53#[cfg(test)]
54mod test;
55
56mod patternexp;
57use patternexp::{pattern, structure_pattern};
58
59fn escape_generic(c: char) -> bool {
60    c.is_control()
61}
62
63pub const GRAPHIX_MUST_ESC: [char; 4] = ['"', '\\', '[', ']'];
64pub static GRAPHIX_ESC: LazyLock<Escape> = LazyLock::new(|| {
65    Escape::new(
66        '\\',
67        &['"', '\\', '[', ']', '\n', '\r', '\t', '\0'],
68        &[('\n', "n"), ('\r', "r"), ('\t', "t"), ('\0', "0")],
69        Some(escape_generic),
70    )
71    .unwrap()
72});
73pub const RESERVED: LazyLock<FxHashSet<&str>> = LazyLock::new(|| {
74    FxHashSet::from_iter([
75        "true", "false", "ok", "null", "mod", "let", "select", "type", "fn", "cast",
76        "if", "i8", "u8", "i16", "u16", "u32", "v32", "i32", "z32", "u64", "v64", "i64",
77        "z64", "f32", "f64", "decimal", "datetime", "duration", "bool", "string",
78        "bytes", "null", "_", "?", "fn", "Array", "Map", "any", "Any", "use", "rec",
79        "catch", "try",
80    ])
81});
82
83// sep_by1 but a separator terminator is allowed and mapped to an output value
84pub fn sep_by1_tok_exp<I, O, OC, F, EP, SP, TP>(
85    p: EP,
86    sep: SP,
87    term: TP,
88    f: F,
89) -> impl Parser<I, Output = OC>
90where
91    I: RangeStream<Token = char>,
92    I::Error: ParseError<I::Token, I::Range, I::Position>,
93    I::Range: Range,
94    OC: Extend<O> + Default,
95    SP: Parser<I>,
96    EP: Parser<I, Output = O>,
97    TP: Parser<I>,
98    F: Fn(I::Position) -> O,
99{
100    sep_by1((position(), choice((look_ahead(term).map(|_| None::<O>), p.map(Some)))), sep)
101        .map(move |mut e: LPooled<Vec<(_, Option<O>)>>| {
102            let mut res = OC::default();
103            res.extend(e.drain(..).map(|(pos, e)| match e {
104                Some(e) => e,
105                None => f(pos),
106            }));
107            res
108        })
109}
110
111fn spaces<I>() -> impl Parser<I, Output = ()>
112where
113    I: RangeStream<Token = char>,
114    I::Error: ParseError<I::Token, I::Range, I::Position>,
115    I::Range: Range,
116{
117    combine::parser::char::spaces().with(skip_many(
118        attempt(string("//").with(not_followed_by(token('/'))))
119            .with(skip_many(none_of(['\n'])))
120            .with(combine::parser::char::spaces()),
121    ))
122}
123
124fn spaces1<I>() -> impl Parser<I, Output = ()>
125where
126    I: RangeStream<Token = char>,
127    I::Error: ParseError<I::Token, I::Range, I::Position>,
128    I::Range: Range,
129{
130    space().with(spaces())
131}
132
133fn doc_comment<I>() -> impl Parser<I, Output = Doc>
134where
135    I: RangeStream<Token = char>,
136    I::Error: ParseError<I::Token, I::Range, I::Position>,
137    I::Range: Range,
138{
139    combine::parser::char::spaces()
140        .with(many(
141            string("///")
142                .with(many(none_of(['\n'])))
143                .skip(combine::parser::char::spaces()),
144        ))
145        .map(|lines: LPooled<Vec<String>>| {
146            if lines.len() == 0 {
147                Doc(None)
148            } else {
149                Doc(Some(ArcStr::from(lines.join("\n"))))
150            }
151        })
152}
153
154fn spstring<'a, I>(s: &'static str) -> impl Parser<I, Output = &'a str>
155where
156    I: RangeStream<Token = char>,
157    I::Error: ParseError<I::Token, I::Range, I::Position>,
158    I::Range: Range,
159{
160    spaces().with(string(s))
161}
162
163fn ident<I>(cap: bool) -> impl Parser<I, Output = ArcStr>
164where
165    I: RangeStream<Token = char>,
166    I::Error: ParseError<I::Token, I::Range, I::Position>,
167    I::Range: Range,
168{
169    recognize((
170        take_while1(move |c: char| c.is_alphabetic() && cap == c.is_uppercase()),
171        take_while(|c: char| c.is_alphanumeric() || c == '_'),
172    ))
173    .map(|s: CompactString| ArcStr::from(s.as_str()))
174}
175
176fn fname<I>() -> impl Parser<I, Output = ArcStr>
177where
178    I: RangeStream<Token = char>,
179    I::Error: ParseError<I::Token, I::Range, I::Position>,
180    I::Range: Range,
181{
182    ident(false).then(|s| {
183        if RESERVED.contains(&s.as_str()) {
184            unexpected_any("can't use keyword as a function or variable name").left()
185        } else {
186            value(s).right()
187        }
188    })
189}
190
191fn spfname<I>() -> impl Parser<I, Output = ArcStr>
192where
193    I: RangeStream<Token = char>,
194    I::Error: ParseError<I::Token, I::Range, I::Position>,
195    I::Range: Range,
196{
197    spaces().with(fname())
198}
199
200fn typname<I>() -> impl Parser<I, Output = ArcStr>
201where
202    I: RangeStream<Token = char>,
203    I::Error: ParseError<I::Token, I::Range, I::Position>,
204    I::Range: Range,
205{
206    ident(true).then(|s| {
207        if RESERVED.contains(&s.as_str()) {
208            unexpected_any("can't use keyword as a type name").left()
209        } else {
210            value(s).right()
211        }
212    })
213}
214
215pub(crate) fn modpath<I>() -> impl Parser<I, Output = ModPath>
216where
217    I: RangeStream<Token = char>,
218    I::Error: ParseError<I::Token, I::Range, I::Position>,
219    I::Range: Range,
220{
221    sep_by1(fname(), string("::"))
222        .map(|mut v: LPooled<Vec<ArcStr>>| ModPath(Path::from_iter(v.drain(..))))
223}
224
225fn spmodpath<I>() -> impl Parser<I, Output = ModPath>
226where
227    I: RangeStream<Token = char>,
228    I::Error: ParseError<I::Token, I::Range, I::Position>,
229    I::Range: Range,
230{
231    spaces().with(modpath())
232}
233
234fn csep<I>() -> impl Parser<I, Output = char>
235where
236    I: RangeStream<Token = char>,
237    I::Error: ParseError<I::Token, I::Range, I::Position>,
238    I::Range: Range,
239{
240    attempt(spaces().with(token(','))).skip(spaces())
241}
242
243fn semisep<I>() -> impl Parser<I, Output = char>
244where
245    I: RangeStream<Token = char>,
246    I::Error: ParseError<I::Token, I::Range, I::Position>,
247    I::Range: Range,
248{
249    attempt(spaces().with(token(';'))).skip(spaces())
250}
251
252fn sptoken<I>(t: char) -> impl Parser<I, Output = char>
253where
254    I: RangeStream<Token = char>,
255    I::Error: ParseError<I::Token, I::Range, I::Position>,
256    I::Range: Range,
257{
258    spaces().with(token(t))
259}
260
261fn do_block<I>() -> impl Parser<I, Output = Expr>
262where
263    I: RangeStream<Token = char, Position = SourcePosition>,
264    I::Error: ParseError<I::Token, I::Range, I::Position>,
265    I::Range: Range,
266{
267    (
268        position(),
269        between(
270            token('{'),
271            sptoken('}'),
272            sep_by1_tok_exp(expr(), semisep(), token('}'), |pos| {
273                ExprKind::NoOp.to_expr(pos)
274            }),
275        ),
276    )
277        .then(|(pos, mut args): (_, LPooled<Vec<Expr>>)| {
278            if args.len() < 2 {
279                unexpected_any("do must contain at least 2 expressions").left()
280            } else {
281                let exprs = Arc::from_iter(args.drain(..));
282                value(ExprKind::Do { exprs }.to_expr(pos)).right()
283            }
284        })
285}
286
287fn ref_pexp<I>() -> impl Parser<I, Output = Expr>
288where
289    I: RangeStream<Token = char, Position = SourcePosition>,
290    I::Error: ParseError<I::Token, I::Range, I::Position>,
291    I::Range: Range,
292{
293    choice((
294        between(attempt(sptoken('(')), sptoken(')'), expr()),
295        spaces().with(qop(reference())),
296    ))
297}
298
299fn structref<I>() -> impl Parser<I, Output = Expr>
300where
301    I: RangeStream<Token = char, Position = SourcePosition>,
302    I::Error: ParseError<I::Token, I::Range, I::Position>,
303    I::Range: Range,
304{
305    (position(), ref_pexp().skip(sptoken('.')), spfname()).map(|(pos, source, field)| {
306        ExprKind::StructRef { source: Arc::new(source), field }.to_expr(pos)
307    })
308}
309
310fn tupleref<I>() -> impl Parser<I, Output = Expr>
311where
312    I: RangeStream<Token = char, Position = SourcePosition>,
313    I::Error: ParseError<I::Token, I::Range, I::Position>,
314    I::Range: Range,
315{
316    (position(), ref_pexp().skip(sptoken('.')), int::<_, usize>()).map(
317        |(pos, source, field)| {
318            ExprKind::TupleRef { source: Arc::new(source), field }.to_expr(pos)
319        },
320    )
321}
322
323fn mapref<I>() -> impl Parser<I, Output = Expr>
324where
325    I: RangeStream<Token = char, Position = SourcePosition>,
326    I::Error: ParseError<I::Token, I::Range, I::Position>,
327    I::Range: Range,
328{
329    (position(), ref_pexp(), between(sptoken('{'), sptoken('}'), expr())).map(
330        |(pos, source, key)| {
331            ExprKind::MapRef { source: Arc::new(source), key: Arc::new(key) }.to_expr(pos)
332        },
333    )
334}
335
336fn any<I>() -> impl Parser<I, Output = Expr>
337where
338    I: RangeStream<Token = char, Position = SourcePosition>,
339    I::Error: ParseError<I::Token, I::Range, I::Position>,
340    I::Range: Range,
341{
342    (
343        position(),
344        attempt(string("any").skip(not_prefix())).with(between(
345            token('('),
346            sptoken(')'),
347            sep_by_tok(expr(), csep(), token(')')),
348        )),
349    )
350        .map(|(pos, mut args): (_, LPooled<Vec<Expr>>)| {
351            ExprKind::Any { args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
352        })
353}
354
355fn letbind<I>() -> impl Parser<I, Output = Expr>
356where
357    I: RangeStream<Token = char, Position = SourcePosition>,
358    I::Error: ParseError<I::Token, I::Range, I::Position>,
359    I::Range: Range,
360{
361    (
362        position(),
363        attempt(string("let").skip(spaces1()))
364            .with((
365                optional(attempt(string("rec").with(spaces1()))),
366                structure_pattern(),
367                spaces().with(optional(token(':').with(typ()))),
368            ))
369            .skip(sptoken('=')),
370        expr(),
371    )
372        .map(|(pos, (rec, pattern, typ), value)| {
373            let rec = rec.is_some();
374            ExprKind::Bind(Arc::new(BindExpr { rec, pattern, typ, value })).to_expr(pos)
375        })
376}
377
378fn connect<I>() -> impl Parser<I, Output = Expr>
379where
380    I: RangeStream<Token = char, Position = SourcePosition>,
381    I::Error: ParseError<I::Token, I::Range, I::Position>,
382    I::Range: Range,
383{
384    (position(), optional(token('*')), spmodpath().skip(spstring("<-")), expr()).map(
385        |(pos, deref, name, e)| {
386            ExprKind::Connect { name, value: Arc::new(e), deref: deref.is_some() }
387                .to_expr(pos)
388        },
389    )
390}
391
392fn literal<I>() -> impl Parser<I, Output = Expr>
393where
394    I: RangeStream<Token = char, Position = SourcePosition>,
395    I::Error: ParseError<I::Token, I::Range, I::Position>,
396    I::Range: Range,
397{
398    (position(), parse_value(&VAL_MUST_ESC, &VAL_ESC).skip(not_prefix())).then(
399        |(pos, v)| match v {
400            Value::String(_) => {
401                unexpected_any("parse error in string interpolation").left()
402            }
403            v => value(ExprKind::Constant(v).to_expr(pos)).right(),
404        },
405    )
406}
407
408fn reference<I>() -> impl Parser<I, Output = Expr>
409where
410    I: RangeStream<Token = char, Position = SourcePosition>,
411    I::Error: ParseError<I::Token, I::Range, I::Position>,
412    I::Range: Range,
413{
414    (position(), modpath()).map(|(pos, name)| ExprKind::Ref { name }.to_expr(pos))
415}
416
417fn qop<I, P>(p: P) -> impl Parser<I, Output = Expr>
418where
419    I: RangeStream<Token = char, Position = SourcePosition>,
420    I::Error: ParseError<I::Token, I::Range, I::Position>,
421    I::Range: Range,
422    P: Parser<I, Output = Expr>,
423{
424    enum Op {
425        Qop,
426        OrNever,
427    }
428    (
429        position(),
430        p,
431        optional(attempt(spaces().with(choice((
432            token('?').map(|_| Op::Qop),
433            token('$').map(|_| Op::OrNever),
434        ))))),
435    )
436        .map(|(pos, e, qop)| match qop {
437            None => e,
438            Some(Op::Qop) => ExprKind::Qop(Arc::new(e)).to_expr(pos),
439            Some(Op::OrNever) => ExprKind::OrNever(Arc::new(e)).to_expr(pos),
440        })
441}
442
443fn raw_string<I>() -> impl Parser<I, Output = Expr>
444where
445    I: RangeStream<Token = char, Position = SourcePosition>,
446    I::Error: ParseError<I::Token, I::Range, I::Position>,
447    I::Range: Range,
448{
449    static MUST_ESC: [char; 2] = ['\\', '\''];
450    static ESC: LazyLock<Escape> =
451        LazyLock::new(|| Escape::new('\\', &MUST_ESC, &[], None).unwrap());
452    (
453        position(),
454        between(attempt(string("r\'")), token('\''), escaped_string(&MUST_ESC, &ESC)),
455    )
456        .map(|(pos, s): (_, String)| {
457            ExprKind::Constant(Value::String(s.into())).to_expr(pos)
458        })
459}
460
461fn select<I>() -> impl Parser<I, Output = Expr>
462where
463    I: RangeStream<Token = char, Position = SourcePosition>,
464    I::Error: ParseError<I::Token, I::Range, I::Position>,
465    I::Range: Range,
466{
467    (
468        position(),
469        attempt(string("select").with(not_prefix())).with(spaces1()).with((
470            expr(),
471            between(
472                sptoken('{'),
473                sptoken('}'),
474                spaces().with(sep_by1_tok(
475                    (pattern(), spstring("=>").with(expr())),
476                    csep(),
477                    token('}'),
478                )),
479            ),
480        )),
481    )
482        .map(|(pos, (arg, mut arms)): (_, (Expr, LPooled<Vec<(Pattern, Expr)>>))| {
483            ExprKind::Select(SelectExpr {
484                arg: Arc::new(arg),
485                arms: Arc::from_iter(arms.drain(..)),
486            })
487            .to_expr(pos)
488        })
489}
490
491fn cast<I>() -> impl Parser<I, Output = Expr>
492where
493    I: RangeStream<Token = char, Position = SourcePosition>,
494    I::Error: ParseError<I::Token, I::Range, I::Position>,
495    I::Range: Range,
496{
497    (
498        position(),
499        attempt(string("cast").skip(not_prefix())).with(between(
500            sptoken('<'),
501            sptoken('>'),
502            typ(),
503        )),
504        between(sptoken('('), sptoken(')'), expr()),
505    )
506        .map(|(pos, typ, e)| ExprKind::TypeCast { expr: Arc::new(e), typ }.to_expr(pos))
507}
508
509fn tuple<I>() -> impl Parser<I, Output = Expr>
510where
511    I: RangeStream<Token = char, Position = SourcePosition>,
512    I::Error: ParseError<I::Token, I::Range, I::Position>,
513    I::Range: Range,
514{
515    (
516        position(),
517        between(token('('), sptoken(')'), sep_by1_tok(expr(), csep(), token(')'))),
518    )
519        .then(|(pos, mut exprs): (_, LPooled<Vec<Expr>>)| {
520            if exprs.len() < 2 {
521                unexpected_any("tuples must have at least 2 elements").left()
522            } else {
523                value(
524                    ExprKind::Tuple { args: Arc::from_iter(exprs.drain(..)) }
525                        .to_expr(pos),
526                )
527                .right()
528            }
529        })
530}
531
532fn structure<I>() -> impl Parser<I, Output = Expr>
533where
534    I: RangeStream<Token = char, Position = SourcePosition>,
535    I::Error: ParseError<I::Token, I::Range, I::Position>,
536    I::Range: Range,
537{
538    (
539        position(),
540        between(
541            token('{'),
542            sptoken('}'),
543            spaces().with(sep_by1_tok(
544                (fname(), spaces().with(optional(token(':').with(expr())))),
545                csep(),
546                token('}'),
547            )),
548        ),
549    )
550        .then(|(pos, mut exprs): (_, LPooled<Vec<(ArcStr, Option<Expr>)>>)| {
551            let s = exprs.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
552            if s.len() < exprs.len() {
553                return unexpected_any("struct fields must be unique").left();
554            }
555            drop(s);
556            exprs.sort_by_key(|(n, _)| n.clone());
557            let args = exprs.drain(..).map(|(n, e)| match e {
558                Some(e) => (n, e),
559                None => {
560                    let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
561                    (n, e)
562                }
563            });
564            value(
565                ExprKind::Struct(StructExpr { args: Arc::from_iter(args) }).to_expr(pos),
566            )
567            .right()
568        })
569}
570
571fn map<I>() -> impl Parser<I, Output = Expr>
572where
573    I: RangeStream<Token = char, Position = SourcePosition>,
574    I::Error: ParseError<I::Token, I::Range, I::Position>,
575    I::Range: Range,
576{
577    (
578        position(),
579        between(
580            token('{'),
581            sptoken('}'),
582            sep_by_tok((expr(), spstring("=>").with(expr())), csep(), token('}')),
583        ),
584    )
585        .map(|(pos, mut args): (_, LPooled<Vec<(Expr, Expr)>>)| {
586            ExprKind::Map { args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
587        })
588}
589
590fn variant<I>() -> impl Parser<I, Output = Expr>
591where
592    I: RangeStream<Token = char, Position = SourcePosition>,
593    I::Error: ParseError<I::Token, I::Range, I::Position>,
594    I::Range: Range,
595{
596    (
597        position(),
598        token('`').with(ident(true)),
599        spaces().with(optional(between(
600            token('('),
601            sptoken(')'),
602            sep_by1_tok(expr(), csep(), token(')')),
603        ))),
604    )
605        .map(|(pos, tag, args): (_, ArcStr, Option<LPooled<Vec<Expr>>>)| {
606            let mut args = match args {
607                None => LPooled::take(),
608                Some(a) => a,
609            };
610            ExprKind::Variant { tag, args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
611        })
612}
613
614fn structwith<I>() -> impl Parser<I, Output = Expr>
615where
616    I: RangeStream<Token = char, Position = SourcePosition>,
617    I::Error: ParseError<I::Token, I::Range, I::Position>,
618    I::Range: Range,
619{
620    (
621        position(),
622        between(
623            token('{'),
624            sptoken('}'),
625            (
626                ref_pexp().skip(space()).skip(spstring("with")).skip(space()),
627                sep_by1_tok(
628                    (spfname(), spaces().with(optional(token(':').with(expr())))),
629                    csep(),
630                    token('}'),
631                ),
632            ),
633        ),
634    )
635        .then(
636            |(pos, (source, mut exprs)): (
637                _,
638                (Expr, LPooled<Vec<(ArcStr, Option<Expr>)>>),
639            )| {
640                let s = exprs.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
641                if s.len() < exprs.len() {
642                    return unexpected_any("struct fields must be unique").left();
643                }
644                drop(s);
645                exprs.sort_by_key(|(n, _)| n.clone());
646                let exprs = exprs.drain(..).map(|(name, e)| match e {
647                    Some(e) => (name, e),
648                    None => {
649                        let e = ExprKind::Ref { name: ModPath::from([name.clone()]) }
650                            .to_expr(pos);
651                        (name, e)
652                    }
653                });
654                let e = ExprKind::StructWith(StructWithExpr {
655                    source: Arc::new(source),
656                    replace: Arc::from_iter(exprs),
657                })
658                .to_expr(pos);
659                value(e).right()
660            },
661        )
662}
663
664fn try_catch<I>() -> impl Parser<I, Output = Expr>
665where
666    I: RangeStream<Token = char, Position = SourcePosition>,
667    I::Error: ParseError<I::Token, I::Range, I::Position>,
668    I::Range: Range,
669{
670    (
671        position().skip(attempt(string("try").skip(space()))),
672        sep_by1_tok(expr(), semisep(), attempt(string("catch"))),
673        spstring("catch").with(between(
674            sptoken('('),
675            sptoken(')'),
676            (spfname(), spaces().with(optional(token(':').with(typ())))),
677        )),
678        spstring("=>").with(expr()),
679    )
680        .map(
681            |(pos, mut exprs, (bind, constraint), handler): (
682                _,
683                LPooled<Vec<Expr>>,
684                _,
685                _,
686            )| {
687                ExprKind::TryCatch(Arc::new(TryCatchExpr {
688                    bind,
689                    constraint,
690                    exprs: Arc::from_iter(exprs.drain(..)),
691                    handler: Arc::new(handler),
692                }))
693                .to_expr(pos)
694            },
695        )
696}
697
698fn byref<I>() -> impl Parser<I, Output = Expr>
699where
700    I: RangeStream<Token = char, Position = SourcePosition>,
701    I::Error: ParseError<I::Token, I::Range, I::Position>,
702    I::Range: Range,
703{
704    (position(), token('&').with(expr()))
705        .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
706}
707
708fn deref<I>() -> impl Parser<I, Output = Expr>
709where
710    I: RangeStream<Token = char, Position = SourcePosition>,
711    I::Error: ParseError<I::Token, I::Range, I::Position>,
712    I::Range: Range,
713{
714    (position(), token('*').with(expr()))
715        .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
716}
717
718parser! {
719    fn expr[I]()(I) -> Expr
720    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
721    {
722        spaces().with(choice((
723            module(),
724            use_module(),
725            try_catch(),
726            typedef(),
727            letbind(),
728            attempt(lambda()),
729            attempt(connect()),
730            attempt(arith()),
731            byref(),
732            qop(deref()),
733            (position(), between(token('('), sptoken(')'), expr())).map(|(pos, e)| {
734                ExprKind::ExplicitParens(Arc::new(e)).to_expr(pos)
735            }),
736            attempt(literal()),
737            qop(reference())
738        )))
739    }
740}
741
742/// Parse one or more expressions
743///
744/// followed by (optional) whitespace and then eof. At least one
745/// expression is required otherwise this function will fail.
746pub fn parse(ori: Origin) -> anyhow::Result<Arc<[Expr]>> {
747    let ori = Arc::new(ori);
748    set_origin(ori.clone());
749    let mut r: LPooled<Vec<Expr>> =
750        sep_by1_tok_exp(expr(), semisep(), eof(), |pos| ExprKind::NoOp.to_expr(pos))
751            .skip(spaces())
752            .skip(eof())
753            .easy_parse(position::Stream::new(&*ori.text))
754            .map(|(r, _)| r)
755            .map_err(|e| anyhow::anyhow!(format!("{}", e)))?;
756    Ok(Arc::from_iter(r.drain(..)))
757}
758
759/// Parse one or more signature expressions
760///
761/// followed by (optional) whitespace and then eof. At least one
762/// expression is required otherwise this function will fail.
763pub fn parse_sig(ori: Origin) -> anyhow::Result<Sig> {
764    let ori = Arc::new(ori);
765    set_origin(ori.clone());
766    let mut r: LPooled<Vec<SigItem>> = sep_by1_tok(sig_item(), semisep(), eof())
767        .skip(spaces())
768        .skip(eof())
769        .easy_parse(position::Stream::new(&*ori.text))
770        .map(|(r, _)| r)
771        .map_err(|e| anyhow::anyhow!(format!("{}", e)))?;
772    Ok(Sig { toplevel: true, items: Arc::from_iter(r.drain(..)) })
773}
774
775/// Parse one and only one expression.
776pub fn parse_one(s: &str) -> anyhow::Result<Expr> {
777    expr()
778        .skip(spaces())
779        .skip(eof())
780        .easy_parse(position::Stream::new(&*s))
781        .map(|(r, _)| r)
782        .map_err(|e| anyhow::anyhow!(format!("{e}")))
783}
784
785#[cfg(test)]
786pub fn test_parse_mapref(s: &str) -> anyhow::Result<Expr> {
787    mapref()
788        .skip(spaces())
789        .skip(eof())
790        .easy_parse(position::Stream::new(&*s))
791        .map(|(r, _)| r)
792        .map_err(|e| anyhow::anyhow!(format!("{e}")))
793}
794
795/// Parse one fntype expression
796pub fn parse_fn_type(s: &str) -> anyhow::Result<FnType> {
797    fntype()
798        .skip(spaces())
799        .skip(eof())
800        .easy_parse(position::Stream::new(s))
801        .map(|(r, _)| r)
802        .map_err(|e| anyhow::anyhow!(format!("{e}")))
803}
804
805/// Parse one type expression
806pub fn parse_type(s: &str) -> anyhow::Result<Type> {
807    typ()
808        .skip(spaces())
809        .skip(eof())
810        .easy_parse(position::Stream::new(s))
811        .map(|(r, _)| r)
812        .map_err(|e| anyhow::anyhow!(format!("{e}")))
813}
814
815pub(super) fn parse_modpath(s: &str) -> anyhow::Result<ModPath> {
816    modpath()
817        .skip(spaces())
818        .skip(eof())
819        .easy_parse(position::Stream::new(s))
820        .map(|(r, _)| r)
821        .map_err(|e| anyhow::anyhow!(format!("{e}")))
822}