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
83pub 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
742pub 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
759pub 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
775pub 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
795pub 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
805pub 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}