1use super::lex::{StrPart, Tok, Token};
4use super::path::{self, Path};
5use super::{ops, prec_climb};
6use alloc::{boxed::Box, vec::Vec};
7
8pub type Error<S, T = S> = (Expect<S>, T);
10pub type TError<'t, S> = Error<S, Option<&'t Token<S>>>;
12
13#[derive(Debug)]
17#[non_exhaustive]
18pub enum Expect<S> {
19 Just(S),
22 Var,
24 Pattern,
26 ElseOrEnd,
28 CommaOrRBrack,
30 CommaOrRBrace,
32 SemicolonOrRParen,
34 Term,
36 Key,
38 Ident,
40 Arg,
42 Str,
44 Nothing,
46}
47
48impl<'a> Expect<&'a str> {
49 pub fn as_str(&self) -> &'a str {
51 match self {
52 Self::Just(s) => s,
53 Self::Var => "variable",
54 Self::Pattern => "pattern",
55 Self::ElseOrEnd => "else or end",
56 Self::CommaOrRBrack => "comma or right bracket",
57 Self::CommaOrRBrace => "comma or right brace",
58 Self::SemicolonOrRParen => "semicolon or right parenthesis",
59 Self::Term => "term",
60 Self::Key => "key",
61 Self::Ident => "identifier",
62 Self::Arg => "argument",
63 Self::Str => "string",
64 Self::Nothing => "nothing",
65 }
66 }
67}
68
69pub type Result<'s, 't, T> = core::result::Result<T, TError<'t, &'s str>>;
71
72pub struct Parser<'s, 't> {
74 i: core::slice::Iter<'t, Token<&'s str>>,
75 e: Vec<TError<'t, &'s str>>,
76}
77
78#[derive(Debug, Default)]
80pub enum Term<S> {
81 #[default]
83 Id,
84 Recurse,
86
87 Num(S),
89 Str(Option<S>, Vec<StrPart<S, Self>>),
94 Arr(Option<Box<Self>>),
96 Obj(Vec<(Self, Option<Self>)>),
98
99 Neg(Box<Self>),
101 Pipe(Box<Self>, Option<Pattern<S>>, Box<Self>),
103
104 BinOp(Box<Self>, BinaryOp, Box<Self>),
106
107 Label(S, Box<Self>),
109 Break(S),
111
112 Fold(S, Box<Self>, Pattern<S>, Vec<Self>),
114 TryCatch(Box<Self>, Option<Box<Self>>),
116 IfThenElse(Vec<(Self, Self)>, Option<Box<Self>>),
118
119 Def(Vec<Def<S, Self>>, Box<Self>),
121 Call(S, Vec<Self>),
123 Var(S),
125
126 Path(Box<Self>, Path<Self>),
128}
129
130#[derive(Debug)]
132pub enum Pattern<S> {
133 Var(S),
135 Arr(Vec<Self>),
137 Obj(Vec<(Term<S>, Self)>),
139}
140
141#[derive(Debug)]
143pub enum BinaryOp {
144 Comma,
146 Alt,
148 Or,
150 And,
152 Math(ops::Math),
154 Cmp(ops::Cmp),
156 Assign,
158 Update,
160 UpdateMath(ops::Math),
163 UpdateAlt,
165}
166
167impl<S> Term<S> {
168 #[cfg(feature = "std")]
169 pub(crate) fn as_str(&self) -> Option<&S> {
170 if let Term::Str(None, s) = self {
171 if let [StrPart::Str(s)] = &s[..] {
172 return Some(s);
173 }
174 }
175 None
176 }
177
178 pub(crate) fn from_str(s: S) -> Self {
179 Self::Str(None, [StrPart::Str(s)].into())
180 }
181
182 pub(crate) fn recurse(recurse: S) -> Self {
184 let path = (path::Part::Range(None, None), path::Opt::Optional);
186 let path = Term::Path(Term::Id.into(), Path(Vec::from([path])));
188
189 let f = Term::Call(recurse, Vec::new());
191 let pipe = Term::Pipe(path.into(), None, f.into());
193 Term::BinOp(Term::Id.into(), BinaryOp::Comma, pipe.into())
195 }
196
197 pub(crate) fn empty() -> Self {
199 let path = (path::Part::Range(None, None), path::Opt::Essential);
201 let obj = Term::Obj(Vec::new());
203 Term::Path(obj.into(), Path(Vec::from([path])))
205 }
206}
207
208impl<S> Pattern<S> {
209 pub(crate) fn vars(&self) -> Box<dyn Iterator<Item = &S> + '_> {
210 match self {
211 Pattern::Var(x) => Box::new(core::iter::once(x)),
212 Pattern::Arr(a) => Box::new(a.iter().flat_map(|p| p.vars())),
213 Pattern::Obj(o) => Box::new(o.iter().flat_map(|(_k, p)| p.vars())),
214 }
215 }
216}
217
218impl<'s, 't> Parser<'s, 't> {
219 #[must_use]
221 pub fn new(i: &'t [Token<&'s str>]) -> Self {
222 Self {
223 i: i.iter(),
224 e: Vec::new(),
225 }
226 }
227
228 pub fn parse<T: Default, F>(mut self, f: F) -> core::result::Result<T, Vec<TError<'t, &'s str>>>
232 where
233 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
234 {
235 let y = self.finish("", f);
236 if self.e.is_empty() {
237 Ok(y)
238 } else {
239 Err(self.e)
240 }
241 }
242
243 fn verify_last(&mut self, last: &'static str) -> Result<'s, 't, ()> {
245 match (self.i.as_slice(), last) {
246 ([], "") => Ok(()),
247 ([Token(c, _)], last) if *c == last => Ok(()),
248 ([], _) => Err((Expect::Just(last), None)),
249 ([next, ..], "") => Err((Expect::Nothing, Some(next))),
250 ([next, ..], _) => Err((Expect::Just(last), Some(next))),
251 }
252 }
253
254 fn with_tok<T>(&mut self, tokens: &'t [Token<&'s str>], f: impl FnOnce(&mut Self) -> T) -> T {
256 let i = core::mem::replace(&mut self.i, tokens.iter());
257 let y = f(self);
258 self.i = i;
259 y
260 }
261
262 fn finish<T: Default, F>(&mut self, last: &'static str, f: F) -> T
266 where
267 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
268 {
269 f(self)
270 .and_then(|y| {
271 self.verify_last(last)?;
272 Ok(y)
273 })
274 .unwrap_or_else(|e| {
275 self.e.push(e);
276 T::default()
277 })
278 }
279
280 fn with<T: Default, F>(&mut self, tokens: &'t [Token<&'s str>], last: &'static str, f: F) -> T
281 where
282 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
283 {
284 self.with_tok(tokens, |p| p.finish(last, f))
285 }
286
287 fn maybe<T>(&mut self, f: impl Fn(&mut Self) -> Option<T>) -> Option<T> {
289 let i = self.i.clone();
290 let y = f(self);
291 if y.is_none() {
293 self.i = i;
294 }
295 y
296 }
297
298 fn try_maybe<T, F>(&mut self, f: F) -> Result<'s, 't, Option<T>>
300 where
301 F: Fn(&mut Self) -> Result<'s, 't, Option<T>>,
302 {
303 let i = self.i.clone();
304 let y = f(self)?;
305 if y.is_none() {
307 self.i = i;
308 }
309 Ok(y)
310 }
311
312 fn many1<T>(
313 &mut self,
314 f: impl Fn(&mut Self) -> Result<'s, 't, T>,
315 sep: &'s str,
316 allow_trailing_sep: bool,
317 last: &'s str,
318 expect: Expect<&'s str>,
319 ) -> Result<'s, 't, Vec<T>> {
320 let mut y = Vec::from([f(self)?]);
321 let get_last = |p: &mut Self| p.i.next().filter(|Token(s, _)| *s == last);
322 let next_last = |p: &mut Self| allow_trailing_sep && p.maybe(get_last).is_some();
323 loop {
324 match self.i.next() {
325 Some(Token(s, _)) if *s == last => break,
326 Some(Token(s, _)) if *s == sep && next_last(self) => break,
327 Some(Token(s, _)) if *s == sep => y.push(f(self)?),
328 next => return Err((expect, next)),
329 }
330 }
331 Ok(y)
332 }
333
334 fn obj_items<T, F>(&mut self, f: F) -> Result<'s, 't, Vec<T>>
336 where
337 F: Fn(&mut Self) -> Result<'s, 't, T>,
338 {
339 self.many1(f, ",", true, "}", Expect::CommaOrRBrace)
340 }
341
342 fn args<T>(&mut self, f: fn(&mut Self) -> Result<'s, 't, T>) -> Vec<T> {
344 self.maybe(|p| match p.i.next() {
345 Some(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
346 Some(p.with(tokens, "", |p| {
347 p.many1(f, ";", false, ")", Expect::SemicolonOrRParen)
348 }))
349 }
350 _ => None,
351 })
352 .unwrap_or_default()
353 }
354
355 fn op(&mut self, with_comma: bool) -> Option<BinaryOp> {
357 use ops::{Cmp, Math};
358 self.maybe(|p| match p.i.next() {
359 Some(Token(s, _)) => Some(match *s {
360 "," if with_comma => BinaryOp::Comma,
361 "+" => BinaryOp::Math(Math::Add),
362 "-" => BinaryOp::Math(Math::Sub),
363 "*" => BinaryOp::Math(Math::Mul),
364 "/" => BinaryOp::Math(Math::Div),
365 "%" => BinaryOp::Math(Math::Rem),
366 "=" => BinaryOp::Assign,
367 "|=" => BinaryOp::Update,
368 "+=" => BinaryOp::UpdateMath(Math::Add),
369 "-=" => BinaryOp::UpdateMath(Math::Sub),
370 "*=" => BinaryOp::UpdateMath(Math::Mul),
371 "/=" => BinaryOp::UpdateMath(Math::Div),
372 "%=" => BinaryOp::UpdateMath(Math::Rem),
373 "<" => BinaryOp::Cmp(Cmp::Lt),
374 ">" => BinaryOp::Cmp(Cmp::Gt),
375 "<=" => BinaryOp::Cmp(Cmp::Le),
376 ">=" => BinaryOp::Cmp(Cmp::Ge),
377 "==" => BinaryOp::Cmp(Cmp::Eq),
378 "!=" => BinaryOp::Cmp(Cmp::Ne),
379 "//" => BinaryOp::Alt,
380 "//=" => BinaryOp::UpdateAlt,
381 "or" => BinaryOp::Or,
382 "and" => BinaryOp::And,
383 _ => return None,
384 }),
385 None => None,
386 })
387 }
388
389 fn char0(&mut self, c: char) -> Option<&'s str> {
391 self.maybe(|p| match p.i.next() {
392 Some(Token(s, _)) if s.chars().eq([c]) => Some(*s),
393 _ => None,
394 })
395 }
396
397 fn dot(&mut self) -> Option<&'s str> {
403 self.maybe(|p| match p.i.next() {
404 Some(Token(c, _)) if *c != ".." => c.strip_prefix('.'),
405 _ => None,
406 })
407 }
408
409 fn terminated<T, F>(&mut self, f: F) -> Result<'s, 't, T>
410 where
411 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
412 {
413 let y = f(self)?;
414 self.just(";")?;
415 Ok(y)
416 }
417
418 fn just(&mut self, c: &'static str) -> Result<'s, 't, &'s str> {
419 match self.i.next() {
420 Some(Token(s, _)) if *s == c => Ok(*s),
421 next => Err((Expect::Just(c), next)),
422 }
423 }
424
425 fn var(&mut self) -> Result<'s, 't, &'s str> {
426 match self.i.next() {
427 Some(Token(x, Tok::Var)) => Ok(*x),
428 next => Err((Expect::Var, next)),
429 }
430 }
431
432 fn pattern(&mut self) -> Result<'s, 't, Pattern<&'s str>> {
433 match self.i.next() {
434 Some(Token(x, Tok::Var)) => Ok(Pattern::Var(*x)),
435 next @ Some(Token(full, Tok::Block(tokens))) => match &full[..1] {
436 "[" => Ok(Pattern::Arr(self.with(tokens, "", |p| {
437 p.many1(Self::pattern, ",", false, "]", Expect::CommaOrRBrack)
438 }))),
439 "{" => Ok(Pattern::Obj(
440 self.with(tokens, "", |p| p.obj_items(Self::pat_obj_entry)),
441 )),
442 _ => Err((Expect::Pattern, next)),
443 },
444 next => Err((Expect::Pattern, next)),
445 }
446 }
447
448 fn term_with_comma(&mut self, with_comma: bool) -> Result<'s, 't, Term<&'s str>> {
455 let head = self.atom()?;
456 let tail = core::iter::from_fn(|| self.op(with_comma).map(|op| Ok((op, self.atom()?))))
457 .collect::<Result<Vec<_>>>()?;
458 let tm = prec_climb::climb(head, tail);
459
460 let pipe = self.try_maybe(|p| match p.i.next() {
461 Some(Token("|", _)) => Ok(Some(None)),
462 Some(Token("as", _)) => {
463 let x = p.pattern()?;
464 p.just("|")?;
465 Ok(Some(Some(x)))
466 }
467 _ => Ok(None),
468 })?;
469 Ok(match pipe {
470 None => tm,
471 Some(x) => Term::Pipe(Box::new(tm), x, Box::new(self.term_with_comma(with_comma)?)),
472 })
473 }
474
475 fn atom(&mut self) -> Result<'s, 't, Term<&'s str>> {
481 let tm = match self.i.next() {
482 Some(Token("-", _)) => Term::Neg(Box::new(self.atom()?)),
483 Some(Token("def", _)) => {
484 let head = self.def_tail()?;
485 let tail = self.defs()?;
486 let tm = self.term()?;
487 Term::Def(core::iter::once(head).chain(tail).collect(), Box::new(tm))
488 }
489 Some(Token("if", _)) => {
490 let if_then = |p: &mut Self| -> Result<_> {
491 let if_ = p.term()?;
492 p.just("then")?;
493 Ok((if_, p.term()?))
494 };
495 let mut if_thens = Vec::from([if_then(self)?]);
496 let else_ = loop {
497 match self.i.next() {
498 Some(Token("elif", _)) => if_thens.push(if_then(self)?),
499 Some(Token("else", _)) => {
500 let else_ = self.term()?;
501 self.just("end")?;
502 break Some(else_);
503 }
504 Some(Token("end", _)) => break None,
505 next => return Err((Expect::ElseOrEnd, next)),
506 }
507 };
508 Term::IfThenElse(if_thens, else_.map(Box::new))
509 }
510 Some(Token("try", _)) => {
511 let try_ = self.atom()?;
512 let catch = self.try_maybe(|p| match p.i.next() {
513 Some(Token("catch", _)) => Ok(Some(p.atom()?)),
514 _ => Ok(None),
515 })?;
516 Term::TryCatch(Box::new(try_), catch.map(Box::new))
517 }
518 Some(Token("label", _)) => {
519 let x = self.var()?;
520 self.just("|")?;
521 let tm = self.term()?;
522 Term::Label(x, Box::new(tm))
523 }
524 Some(Token("break", _)) => Term::Break(self.var()?),
525 Some(Token(fold @ ("reduce" | "foreach"), _)) => {
526 let xs = self.atom()?;
527 self.just("as")?;
528 let x = self.pattern()?;
529 let args = self.args(Self::term);
530 Term::Fold(*fold, Box::new(xs), x, args)
531 }
532 Some(Token(id, Tok::Var)) => Term::Var(*id),
533 Some(Token(id, Tok::Fmt)) => {
534 let s = self.maybe(|p| match p.i.next() {
535 Some(Token(_, Tok::Str(parts))) => Some(p.str_parts(parts)),
536 _ => None,
537 });
538 match s {
539 None => Term::Call(*id, self.args(Self::term)),
540 Some(parts) => Term::Str(Some(*id), parts),
541 }
542 }
543 Some(Token(id, Tok::Word)) => Term::Call(*id, self.args(Self::term)),
544 Some(Token("..", _)) => Term::Recurse,
545 Some(Token(c, Tok::Sym)) if c.starts_with('.') => {
546 let key = if c.len() > 1 {
547 Some(Term::from_str(&c[1..]))
548 } else {
549 self.maybe(|p| p.str_key().ok())
552 };
553
554 if let Some(key) = key {
555 let head = (path::Part::Index(key), self.opt());
556 let path = core::iter::once(head).chain(self.path()?.0).collect();
557 Term::Path(Box::new(Term::Id), Path(path))
558 } else {
559 Term::Id
560 }
561 }
562 Some(Token(n, Tok::Num)) => Term::Num(*n),
563 Some(Token(full, Tok::Block(tokens))) => match &full[..1] {
564 "[" if matches!(tokens[..], [Token("]", _)]) => Term::Arr(None),
565 "{" if matches!(tokens[..], [Token("}", _)]) => Term::Obj(Vec::new()),
566 "[" => Term::Arr(Some(Box::new(self.with(tokens, "]", Self::term)))),
567 "{" => self.with(tokens, "", |p| p.obj_items(Self::obj_entry).map(Term::Obj)),
568 "(" => self.with(tokens, ")", Self::term),
569 _ => panic!(),
570 },
571 Some(Token(_, Tok::Str(parts))) => Term::Str(None, self.str_parts(parts)),
572 next => return Err((Expect::Term, next)),
573 };
574
575 let tm = match self.opt() {
576 path::Opt::Optional => Term::TryCatch(Box::new(tm), None),
577 path::Opt::Essential => tm,
578 };
579
580 let path = self.path()?;
581 Ok(if path.0.is_empty() {
582 tm
583 } else {
584 Term::Path(Box::new(tm), path)
585 })
586 }
587
588 pub fn term(&mut self) -> Result<'s, 't, Term<&'s str>> {
590 self.term_with_comma(true)
591 }
592
593 fn pat_obj_entry(&mut self) -> Result<'s, 't, (Term<&'s str>, Pattern<&'s str>)> {
602 let i = self.i.clone();
603 let key = match self.i.next() {
604 Some(Token(x, Tok::Var)) => return Ok((Term::from_str(&x[1..]), Pattern::Var(x))),
605 Some(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
606 self.with(tokens, ")", Self::term)
607 }
608 Some(Token(id, Tok::Word)) if !id.contains("::") => Term::from_str(*id),
609 _ => {
610 self.i = i;
611 self.str_key()?
612 }
613 };
614 self.just(":")?;
615 Ok((key, self.pattern()?))
616 }
617
618 fn obj_entry(&mut self) -> Result<'s, 't, (Term<&'s str>, Option<Term<&'s str>>)> {
625 let i = self.i.clone();
626 let key = match self.i.next() {
627 Some(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
628 let k = self.with(tokens, ")", Self::term);
629 self.just(":")?;
630 return Ok((k, Some(self.term_with_comma(false)?)));
631 }
632 Some(Token(id, Tok::Var)) => Term::Var(*id),
633 Some(Token(id, Tok::Word)) if !id.contains("::") => Term::from_str(*id),
634 _ => {
635 self.i = i;
636 self.str_key()?
637 }
638 };
639 let v = self.char0(':').map(|_| self.term_with_comma(false));
640 Ok((key, v.transpose()?))
641 }
642
643 fn str_parts(
644 &mut self,
645 parts: &'t [StrPart<&'s str, Token<&'s str>>],
646 ) -> Vec<StrPart<&'s str, Term<&'s str>>> {
647 let parts = parts.iter().map(|part| match part {
648 StrPart::Str(s) => StrPart::Str(*s),
649 StrPart::Term(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
650 StrPart::Term(self.with(tokens, ")", Self::term))
651 }
652 StrPart::Term(_) => unreachable!(),
653 StrPart::Char(c) => StrPart::Char(*c),
654 });
655 parts.collect()
656 }
657
658 fn path(&mut self) -> Result<'s, 't, Path<Term<&'s str>>> {
659 let mut path: Vec<_> = core::iter::from_fn(|| self.path_part_opt()).collect();
660 while let Some(key) = self.dot() {
661 let key = if key.is_empty() {
662 self.str_key()?
663 } else {
664 Term::from_str(key)
665 };
666 path.push((path::Part::Index(key), self.opt()));
667 path.extend(core::iter::from_fn(|| self.path_part_opt()));
668 }
669 Ok(Path(path))
670 }
671
672 fn path_part(&mut self) -> Result<'s, 't, path::Part<Term<&'s str>>> {
674 use path::Part::{Index, Range};
675 let done = |p: &Self| matches!(p.i.as_slice(), [Token("]", _)]);
676 Ok(if done(self) {
677 Range(None, None)
678 } else if self.char0(':').is_some() {
679 Range(None, Some(self.term()?))
680 } else {
681 let tm = self.term()?;
682 if self.char0(':').is_some() {
683 if done(self) {
684 Range(Some(tm), None)
685 } else {
686 Range(Some(tm), Some(self.term()?))
687 }
688 } else {
689 Index(tm)
690 }
691 })
692 }
693
694 fn path_part_opt(&mut self) -> Option<(path::Part<Term<&'s str>>, path::Opt)> {
695 let part = self.maybe(|p| match p.i.next() {
696 Some(Token(full, Tok::Block(tokens))) if full.starts_with('[') => {
697 Some(p.with(tokens, "]", Self::path_part))
698 }
699 _ => None,
700 })?;
701 Some((part, self.opt()))
702 }
703
704 fn str_key(&mut self) -> Result<'s, 't, Term<&'s str>> {
705 match self.i.next() {
706 Some(Token(id, Tok::Fmt)) => match self.i.next() {
707 Some(Token(_, Tok::Str(parts))) => Ok(Term::Str(Some(*id), self.str_parts(parts))),
708 next => Err((Expect::Str, next)),
709 },
710 Some(Token(_, Tok::Str(parts))) => Ok(Term::Str(None, self.str_parts(parts))),
711 next => Err((Expect::Key, next)),
712 }
713 }
714
715 fn opt(&mut self) -> path::Opt {
716 let mut opt = path::Opt::Essential;
717 while self.char0('?').is_some() {
718 opt = path::Opt::Optional;
719 }
720 opt
721 }
722
723 pub fn defs(&mut self) -> Result<'s, 't, Vec<Def<&'s str>>> {
725 let head = |p: &mut Self| p.just("def").ok();
726 core::iter::from_fn(|| self.maybe(head).map(|_| self.def_tail())).collect()
727 }
728
729 fn def_tail(&mut self) -> Result<'s, 't, Def<&'s str, Term<&'s str>>> {
731 let name = match self.i.next() {
732 Some(Token(w, Tok::Word | Tok::Fmt)) if !w.contains("::") => w,
733 next => return Err((Expect::Ident, next)),
734 };
735 let args = self.args(|p| match p.i.next() {
736 Some(Token(w, Tok::Word | Tok::Var)) if !w.contains("::") => Ok(*w),
737 next => Err((Expect::Arg, next)),
738 });
739 self.just(":")?;
740
741 let body = self.term()?;
742 self.just(";")?;
743
744 Ok(Def { name, args, body })
745 }
746
747 fn bare_str(&mut self) -> Result<'s, 't, &'s str> {
748 match self.i.next() {
749 next @ Some(Token(_, Tok::Str(parts))) => match parts[..] {
750 [StrPart::Str(s)] => Ok(s),
751 _ => Err((Expect::Str, next)),
752 },
753 next => Err((Expect::Str, next)),
754 }
755 }
756
757 fn dep(&mut self, import: bool) -> Result<'s, 't, Dep<&'s str>> {
759 let path = self.bare_str()?;
760 let name = import.then(|| {
761 self.just("as")?;
762 match self.i.next() {
763 Some(Token(v, Tok::Word | Tok::Var)) => Ok(*v),
764 next => Err((Expect::Ident, next)),
765 }
766 });
767 let name = name.transpose()?;
768 let meta = !matches!(self.i.as_slice(), [Token(";", _), ..]);
769 let meta = meta.then(|| self.term()).transpose()?;
770 Ok((path, name, meta))
771 }
772
773 pub(crate) fn module<B, F>(&mut self, f: F) -> Result<'s, 't, Module<&'s str, B>>
775 where
776 F: FnOnce(&mut Self) -> Result<'s, 't, B>,
777 {
778 let meta = self
779 .maybe(|p| match p.i.next() {
780 Some(Token("module", _)) => Some(p.terminated(Self::term)),
781 _ => None,
782 })
783 .transpose()?;
784
785 let deps = core::iter::from_fn(|| {
786 self.maybe(|p| match p.i.next() {
787 Some(Token("include", _)) => Some(p.terminated(|p| p.dep(false))),
788 Some(Token("import", _)) => Some(p.terminated(|p| p.dep(true))),
789 _ => None,
790 })
791 })
792 .collect::<Result<_>>()?;
793
794 let body = f(self)?;
795
796 Ok(Module { meta, deps, body })
797 }
798}
799
800type Dep<S> = (S, Option<S>, Option<Term<S>>);
801
802#[derive(Debug, Default)]
815pub(crate) struct Module<S, B> {
816 pub meta: Option<Term<S>>,
817 pub deps: Vec<Dep<S>>,
818 pub body: B,
819}
820
821#[derive(Debug)]
832pub struct Def<S, F = Term<S>> {
833 pub name: S,
835 pub args: Vec<S>,
837 pub body: F,
839}
840
841impl<S, F> Def<S, F> {
842 pub(crate) fn new(name: S, args: Vec<S>, body: F) -> Self {
843 Self { name, args, body }
844 }
845}
846
847impl prec_climb::Op for BinaryOp {
848 fn precedence(&self) -> usize {
849 use ops::{Cmp, Math};
850 match self {
851 Self::Comma => 1,
852 Self::Assign | Self::Update | Self::UpdateMath(_) | Self::UpdateAlt => 2,
853 Self::Alt => 3,
854 Self::Or => Self::Alt.precedence() + 1,
855 Self::And => Self::Or.precedence() + 1,
856 Self::Cmp(Cmp::Eq | Cmp::Ne) => Self::And.precedence() + 1,
857 Self::Cmp(Cmp::Lt | Cmp::Gt | Cmp::Le | Cmp::Ge) => Self::And.precedence() + 2,
858 Self::Math(Math::Add | Math::Sub) => Self::And.precedence() + 3,
859 Self::Math(Math::Mul | Math::Div) => Self::Math(Math::Add).precedence() + 1,
860 Self::Math(Math::Rem) => Self::Math(Math::Mul).precedence() + 1,
861 }
862 }
863
864 fn associativity(&self) -> prec_climb::Associativity {
865 use prec_climb::Associativity;
866 match self {
867 Self::Assign | Self::Update | Self::UpdateMath(_) | Self::UpdateAlt => {
868 Associativity::Right
869 }
870 _ => Associativity::Left,
871 }
872 }
873}
874
875impl<S> prec_climb::Expr<BinaryOp> for Term<S> {
876 fn from_op(lhs: Self, op: BinaryOp, rhs: Self) -> Self {
877 Self::BinOp(Box::new(lhs), op, Box::new(rhs))
878 }
879}