1use super::lex::{StrPart, Tok, Token};
4use super::path::{self, Path};
5use super::{ops, prec_climb};
6use alloc::{boxed::Box, vec::Vec};
7use core::fmt::{self, Debug};
8
9pub type Error<S, T = S> = (Expect<S>, T);
11pub type TError<'t, S> = Error<S, Option<&'t Token<S>>>;
13
14#[derive(Debug)]
18#[non_exhaustive]
19pub enum Expect<S> {
20 Just(S),
23 Var,
25 Pattern,
27 ElseOrEnd,
29 CommaOrRBrack,
31 CommaOrRBrace,
33 SemicolonOrRParen,
35 Term,
37 Key,
39 Ident,
41 Arg,
43 Str,
45 Nothing,
47}
48
49impl<'a> Expect<&'a str> {
50 pub fn as_str(&self) -> &'a str {
52 match self {
53 Self::Just(s) => s,
54 Self::Var => "variable",
55 Self::Pattern => "pattern",
56 Self::ElseOrEnd => "else or end",
57 Self::CommaOrRBrack => "comma or right bracket",
58 Self::CommaOrRBrace => "comma or right brace",
59 Self::SemicolonOrRParen => "semicolon or right parenthesis",
60 Self::Term => "term",
61 Self::Key => "key",
62 Self::Ident => "identifier",
63 Self::Arg => "argument",
64 Self::Str => "string",
65 Self::Nothing => "nothing",
66 }
67 }
68}
69
70pub type Result<'s, 't, T> = core::result::Result<T, TError<'t, &'s str>>;
72
73pub struct Parser<'s, 't> {
75 i: core::slice::Iter<'t, Token<&'s str>>,
76 e: Vec<TError<'t, &'s str>>,
77}
78
79#[derive(Clone, Debug, Default)]
81pub enum Term<S> {
82 #[default]
84 Id,
85 Recurse,
87
88 Num(S),
90 Str(Option<S>, Vec<StrPart<S, Self>>),
95 Arr(Option<Box<Self>>),
97 Obj(Vec<(Self, Option<Self>)>),
99
100 Neg(Box<Self>),
102
103 BinOp(Box<Self>, BinaryOp<S>, Box<Self>),
105
106 Label(S, Box<Self>),
108 Break(S),
110
111 Fold(S, Box<Self>, Pattern<S>, Vec<Self>),
113 TryCatch(Box<Self>, Option<Box<Self>>),
115 IfThenElse(Vec<(Self, Self)>, Option<Box<Self>>),
117
118 Def(Vec<Def<S, Self>>, Box<Self>),
120 Call(S, Vec<Self>),
122 Var(S),
124
125 Path(Box<Self>, Path<Self>),
127}
128
129#[derive(Clone, Debug)]
131pub enum Pattern<S> {
132 Var(S),
134 Arr(Vec<Self>),
136 Obj(Vec<(Term<S>, Self)>),
138}
139
140#[derive(Clone, Debug)]
142pub enum BinaryOp<S> {
143 Pipe(Option<Pattern<S>>),
145 Comma,
147 Alt,
149 Or,
151 And,
153 Math(ops::Math),
155 Cmp(ops::Cmp),
157 Assign,
159 Update,
161 UpdateMath(ops::Math),
164 UpdateAlt,
166}
167
168impl<S> Term<S> {
169 #[cfg(feature = "std")]
170 pub(crate) fn as_str(&self) -> Option<&S> {
171 if let Term::Str(None, s) = self {
172 if let [StrPart::Str(s)] = &s[..] {
173 return Some(s);
174 }
175 }
176 None
177 }
178
179 pub(crate) fn from_str(s: S) -> Self {
180 Self::Str(None, [StrPart::Str(s)].into())
181 }
182
183 pub(crate) fn empty() -> Self {
185 let path = (path::Part::Range(None, None), path::Opt::Essential);
187 let obj = Term::Obj(Vec::new());
189 Term::Path(obj.into(), Path(Vec::from([path])))
191 }
192
193 fn climb(self, tail: &mut impl Iterator<Item = (BinaryOp<S>, Self)>) -> Self {
197 let tail = core::iter::from_fn(|| {
198 tail.next().map(|(op, tm)| match op {
199 BinaryOp::Pipe(Some(_)) => (op, tm.climb(tail)),
200 _ => (op, tm),
201 })
202 });
203 prec_climb::climb(self, tail)
204 }
205}
206
207impl<S> Pattern<S> {
208 pub(crate) fn vars(&self) -> Box<dyn Iterator<Item = &S> + '_> {
209 match self {
210 Pattern::Var(x) => Box::new(core::iter::once(x)),
211 Pattern::Arr(a) => Box::new(a.iter().flat_map(|p| p.vars())),
212 Pattern::Obj(o) => Box::new(o.iter().flat_map(|(_k, p)| p.vars())),
213 }
214 }
215}
216
217impl<'s, 't> Parser<'s, 't> {
218 #[must_use]
220 pub fn new(i: &'t [Token<&'s str>]) -> Self {
221 Self {
222 i: i.iter(),
223 e: Vec::new(),
224 }
225 }
226
227 pub fn parse<T: Default, F>(mut self, f: F) -> core::result::Result<T, Vec<TError<'t, &'s str>>>
231 where
232 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
233 {
234 let y = self.finish("", f);
235 if self.e.is_empty() {
236 Ok(y)
237 } else {
238 Err(self.e)
239 }
240 }
241
242 fn verify_last(&mut self, last: &'static str) -> Result<'s, 't, ()> {
244 match (self.i.as_slice(), last) {
245 ([], "") => Ok(()),
246 ([Token(c, _)], last) if *c == last => Ok(()),
247 ([], _) => Err((Expect::Just(last), None)),
248 ([next, ..], "") => Err((Expect::Nothing, Some(next))),
249 ([next, ..], _) => Err((Expect::Just(last), Some(next))),
250 }
251 }
252
253 fn with_tok<T>(&mut self, tokens: &'t [Token<&'s str>], f: impl FnOnce(&mut Self) -> T) -> T {
255 let i = core::mem::replace(&mut self.i, tokens.iter());
256 let y = f(self);
257 self.i = i;
258 y
259 }
260
261 fn finish<T: Default, F>(&mut self, last: &'static str, f: F) -> T
265 where
266 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
267 {
268 f(self)
269 .and_then(|y| {
270 self.verify_last(last)?;
271 Ok(y)
272 })
273 .unwrap_or_else(|e| {
274 self.e.push(e);
275 T::default()
276 })
277 }
278
279 fn with<T: Default, F>(&mut self, tokens: &'t [Token<&'s str>], last: &'static str, f: F) -> T
280 where
281 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
282 {
283 self.with_tok(tokens, |p| p.finish(last, f))
284 }
285
286 fn maybe<T>(&mut self, f: impl Fn(&mut Self) -> Option<T>) -> Option<T> {
288 let i = self.i.clone();
289 let y = f(self);
290 if y.is_none() {
292 self.i = i;
293 }
294 y
295 }
296
297 fn try_maybe<T, F>(&mut self, f: F) -> Result<'s, 't, Option<T>>
299 where
300 F: Fn(&mut Self) -> Result<'s, 't, Option<T>>,
301 {
302 let i = self.i.clone();
303 let y = f(self)?;
304 if y.is_none() {
306 self.i = i;
307 }
308 Ok(y)
309 }
310
311 fn many1<T>(
312 &mut self,
313 f: impl Fn(&mut Self) -> Result<'s, 't, T>,
314 sep: &'s str,
315 allow_trailing_sep: bool,
316 last: &'s str,
317 expect: Expect<&'s str>,
318 ) -> Result<'s, 't, Vec<T>> {
319 let mut y = Vec::from([f(self)?]);
320 let get_last = |p: &mut Self| p.i.next().filter(|Token(s, _)| *s == last);
321 let next_last = |p: &mut Self| allow_trailing_sep && p.maybe(get_last).is_some();
322 loop {
323 match self.i.next() {
324 Some(Token(s, _)) if *s == last => break,
325 Some(Token(s, _)) if *s == sep && next_last(self) => break,
326 Some(Token(s, _)) if *s == sep => y.push(f(self)?),
327 next => return Err((expect, next)),
328 }
329 }
330 Ok(y)
331 }
332
333 fn obj_items<T, F>(&mut self, f: F) -> Result<'s, 't, Vec<T>>
335 where
336 F: Fn(&mut Self) -> Result<'s, 't, T>,
337 {
338 self.many1(f, ",", true, "}", Expect::CommaOrRBrace)
339 }
340
341 fn args<T>(&mut self, f: fn(&mut Self) -> Result<'s, 't, T>) -> Vec<T> {
343 self.maybe(|p| match p.i.next() {
344 Some(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
345 Some(p.with(tokens, "", |p| {
346 p.many1(f, ";", false, ")", Expect::SemicolonOrRParen)
347 }))
348 }
349 _ => None,
350 })
351 .unwrap_or_default()
352 }
353
354 fn op(&mut self, with_comma: bool) -> Result<'s, 't, Option<BinaryOp<&'s str>>> {
356 use ops::{Cmp, Math};
357 self.try_maybe(|p| match p.i.next() {
358 Some(Token(s, _)) => Ok(Some(match *s {
359 "|" => BinaryOp::Pipe(None),
360 "as" => {
361 let x = p.pattern()?;
362 p.just("|")?;
363 BinaryOp::Pipe(Some(x))
364 }
365 "," if with_comma => BinaryOp::Comma,
366 "+" => BinaryOp::Math(Math::Add),
367 "-" => BinaryOp::Math(Math::Sub),
368 "*" => BinaryOp::Math(Math::Mul),
369 "/" => BinaryOp::Math(Math::Div),
370 "%" => BinaryOp::Math(Math::Rem),
371 "=" => BinaryOp::Assign,
372 "|=" => BinaryOp::Update,
373 "+=" => BinaryOp::UpdateMath(Math::Add),
374 "-=" => BinaryOp::UpdateMath(Math::Sub),
375 "*=" => BinaryOp::UpdateMath(Math::Mul),
376 "/=" => BinaryOp::UpdateMath(Math::Div),
377 "%=" => BinaryOp::UpdateMath(Math::Rem),
378 "<" => BinaryOp::Cmp(Cmp::Lt),
379 ">" => BinaryOp::Cmp(Cmp::Gt),
380 "<=" => BinaryOp::Cmp(Cmp::Le),
381 ">=" => BinaryOp::Cmp(Cmp::Ge),
382 "==" => BinaryOp::Cmp(Cmp::Eq),
383 "!=" => BinaryOp::Cmp(Cmp::Ne),
384 "//" => BinaryOp::Alt,
385 "//=" => BinaryOp::UpdateAlt,
386 "or" => BinaryOp::Or,
387 "and" => BinaryOp::And,
388 _ => return Ok(None),
389 })),
390 None => Ok(None),
391 })
392 }
393
394 fn char0(&mut self, c: char) -> Option<&'s str> {
396 self.maybe(|p| match p.i.next() {
397 Some(Token(s, _)) if s.chars().eq([c]) => Some(*s),
398 _ => None,
399 })
400 }
401
402 fn dot(&mut self) -> Option<&'s str> {
408 self.maybe(|p| match p.i.next() {
409 Some(Token(c, _)) if *c != ".." => c.strip_prefix('.'),
410 _ => None,
411 })
412 }
413
414 fn terminated<T, F>(&mut self, f: F) -> Result<'s, 't, T>
415 where
416 F: FnOnce(&mut Self) -> Result<'s, 't, T>,
417 {
418 let y = f(self)?;
419 self.just(";")?;
420 Ok(y)
421 }
422
423 fn just(&mut self, c: &'static str) -> Result<'s, 't, &'s str> {
424 match self.i.next() {
425 Some(Token(s, _)) if *s == c => Ok(*s),
426 next => Err((Expect::Just(c), next)),
427 }
428 }
429
430 fn var(&mut self) -> Result<'s, 't, &'s str> {
431 match self.i.next() {
432 Some(Token(x, Tok::Var)) => Ok(*x),
433 next => Err((Expect::Var, next)),
434 }
435 }
436
437 fn pattern(&mut self) -> Result<'s, 't, Pattern<&'s str>> {
438 match self.i.next() {
439 Some(Token(x, Tok::Var)) => Ok(Pattern::Var(*x)),
440 next @ Some(Token(full, Tok::Block(tokens))) => match &full[..1] {
441 "[" => Ok(Pattern::Arr(self.with(tokens, "", |p| {
442 p.many1(Self::pattern, ",", false, "]", Expect::CommaOrRBrack)
443 }))),
444 "{" => Ok(Pattern::Obj(
445 self.with(tokens, "", |p| p.obj_items(Self::pat_obj_entry)),
446 )),
447 _ => Err((Expect::Pattern, next)),
448 },
449 next => Err((Expect::Pattern, next)),
450 }
451 }
452
453 fn term_with_comma(&mut self, with_comma: bool) -> Result<'s, 't, Term<&'s str>> {
460 let head = self.atom()?;
461 let mut tail = Vec::new();
462 while let Some(op) = self.op(with_comma)? {
463 tail.push((op, self.atom()?))
464 }
465 Ok(head.climb(&mut tail.into_iter()))
466 }
467
468 fn atom(&mut self) -> Result<'s, 't, Term<&'s str>> {
474 let tm = match self.i.next() {
475 Some(Token("-", _)) => Term::Neg(Box::new(self.atom()?)),
476 Some(Token("def", _)) => {
477 let head = self.def_tail()?;
478 let tail = self.defs()?;
479 let tm = self.term()?;
480 Term::Def(core::iter::once(head).chain(tail).collect(), Box::new(tm))
481 }
482 Some(Token("if", _)) => {
483 let if_then = |p: &mut Self| -> Result<_> {
484 let if_ = p.term()?;
485 p.just("then")?;
486 Ok((if_, p.term()?))
487 };
488 let mut if_thens = Vec::from([if_then(self)?]);
489 let else_ = loop {
490 match self.i.next() {
491 Some(Token("elif", _)) => if_thens.push(if_then(self)?),
492 Some(Token("else", _)) => {
493 let else_ = self.term()?;
494 self.just("end")?;
495 break Some(else_);
496 }
497 Some(Token("end", _)) => break None,
498 next => return Err((Expect::ElseOrEnd, next)),
499 }
500 };
501 Term::IfThenElse(if_thens, else_.map(Box::new))
502 }
503 Some(Token("try", _)) => {
504 let try_ = self.atom()?;
505 let catch = self.try_maybe(|p| match p.i.next() {
506 Some(Token("catch", _)) => Ok(Some(p.atom()?)),
507 _ => Ok(None),
508 })?;
509 Term::TryCatch(Box::new(try_), catch.map(Box::new))
510 }
511 Some(Token("label", _)) => {
512 let x = self.var()?;
513 self.just("|")?;
514 let tm = self.term()?;
515 Term::Label(x, Box::new(tm))
516 }
517 Some(Token("break", _)) => Term::Break(self.var()?),
518 Some(Token(fold @ ("reduce" | "foreach"), _)) => {
519 let xs = self.atom()?;
520 self.just("as")?;
521 let x = self.pattern()?;
522 let args = self.args(Self::term);
523 Term::Fold(*fold, Box::new(xs), x, args)
524 }
525 Some(Token(id, Tok::Var)) => Term::Var(*id),
526 Some(Token(id, Tok::Fmt)) => {
527 let s = self.maybe(|p| match p.i.next() {
528 Some(Token(_, Tok::Str(parts))) => Some(p.str_parts(parts)),
529 _ => None,
530 });
531 match s {
532 None => Term::Call(*id, self.args(Self::term)),
533 Some(parts) => Term::Str(Some(*id), parts),
534 }
535 }
536 Some(Token(id, Tok::Word)) => Term::Call(*id, self.args(Self::term)),
537 Some(Token("..", _)) => Term::Recurse,
538 Some(Token(c, Tok::Sym)) if c.starts_with('.') => {
539 let key = if c.len() > 1 {
540 Some(Term::from_str(&c[1..]))
541 } else {
542 self.maybe(|p| p.str_key().ok())
545 };
546
547 if let Some(key) = key {
548 let head = (path::Part::Index(key), self.opt());
549 let path = core::iter::once(head).chain(self.path()?.0).collect();
550 Term::Path(Box::new(Term::Id), Path(path))
551 } else {
552 Term::Id
553 }
554 }
555 Some(Token(n, Tok::Num)) => Term::Num(*n),
556 Some(Token(full, Tok::Block(tokens))) => match &full[..1] {
557 "[" if matches!(tokens[..], [Token("]", _)]) => Term::Arr(None),
558 "{" if matches!(tokens[..], [Token("}", _)]) => Term::Obj(Vec::new()),
559 "[" => Term::Arr(Some(Box::new(self.with(tokens, "]", Self::term)))),
560 "{" => self.with(tokens, "", |p| p.obj_items(Self::obj_entry).map(Term::Obj)),
561 "(" => self.with(tokens, ")", Self::term),
562 _ => panic!(),
563 },
564 Some(Token(_, Tok::Str(parts))) => Term::Str(None, self.str_parts(parts)),
565 next => return Err((Expect::Term, next)),
566 };
567
568 let tm = match self.opt() {
569 path::Opt::Optional => Term::TryCatch(Box::new(tm), None),
570 path::Opt::Essential => tm,
571 };
572
573 let path = self.path()?;
574 Ok(if path.0.is_empty() {
575 tm
576 } else {
577 Term::Path(Box::new(tm), path)
578 })
579 }
580
581 pub fn term(&mut self) -> Result<'s, 't, Term<&'s str>> {
583 self.term_with_comma(true)
584 }
585
586 fn pat_obj_entry(&mut self) -> Result<'s, 't, (Term<&'s str>, Pattern<&'s str>)> {
595 let i = self.i.clone();
596 let key = match self.i.next() {
597 Some(Token(x, Tok::Var)) => return Ok((Term::from_str(&x[1..]), Pattern::Var(x))),
598 Some(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
599 self.with(tokens, ")", Self::term)
600 }
601 Some(Token(id, Tok::Word)) if !id.contains("::") => Term::from_str(*id),
602 _ => {
603 self.i = i;
604 self.str_key()?
605 }
606 };
607 self.just(":")?;
608 Ok((key, self.pattern()?))
609 }
610
611 fn obj_entry(&mut self) -> Result<'s, 't, (Term<&'s str>, Option<Term<&'s str>>)> {
618 let i = self.i.clone();
619 let key = match self.i.next() {
620 Some(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
621 let k = self.with(tokens, ")", Self::term);
622 self.just(":")?;
623 return Ok((k, Some(self.term_with_comma(false)?)));
624 }
625 Some(Token(id, Tok::Var)) => Term::Var(*id),
626 Some(Token(id, Tok::Word)) if !id.contains("::") => Term::from_str(*id),
627 _ => {
628 self.i = i;
629 self.str_key()?
630 }
631 };
632 let v = self.char0(':').map(|_| self.term_with_comma(false));
633 Ok((key, v.transpose()?))
634 }
635
636 fn str_parts(
637 &mut self,
638 parts: &'t [StrPart<&'s str, Token<&'s str>>],
639 ) -> Vec<StrPart<&'s str, Term<&'s str>>> {
640 let parts = parts.iter().map(|part| match part {
641 StrPart::Str(s) => StrPart::Str(*s),
642 StrPart::Term(Token(full, Tok::Block(tokens))) if full.starts_with('(') => {
643 StrPart::Term(self.with(tokens, ")", Self::term))
644 }
645 StrPart::Term(_) => unreachable!(),
646 StrPart::Char(c) => StrPart::Char(*c),
647 });
648 parts.collect()
649 }
650
651 fn path(&mut self) -> Result<'s, 't, Path<Term<&'s str>>> {
652 let mut path: Vec<_> = core::iter::from_fn(|| self.path_part_opt()).collect();
653 while let Some(key) = self.dot() {
654 path.push(if key.is_empty() {
655 match self.path_part_opt() {
656 Some(part_opt) => part_opt,
657 None => (path::Part::Index(self.str_key()?), self.opt()),
658 }
659 } else {
660 (path::Part::Index(Term::from_str(key)), self.opt())
661 });
662
663 path.extend(core::iter::from_fn(|| self.path_part_opt()));
664 }
665 Ok(Path(path))
666 }
667
668 fn path_part(&mut self) -> Result<'s, 't, path::Part<Term<&'s str>>> {
670 use path::Part::{Index, Range};
671 let done = |p: &Self| matches!(p.i.as_slice(), [Token("]", _)]);
672 Ok(if done(self) {
673 Range(None, None)
674 } else if self.char0(':').is_some() {
675 Range(None, Some(self.term()?))
676 } else {
677 let tm = self.term()?;
678 if self.char0(':').is_some() {
679 if done(self) {
680 Range(Some(tm), None)
681 } else {
682 Range(Some(tm), Some(self.term()?))
683 }
684 } else {
685 Index(tm)
686 }
687 })
688 }
689
690 fn path_part_opt(&mut self) -> Option<(path::Part<Term<&'s str>>, path::Opt)> {
691 let part = self.maybe(|p| match p.i.next() {
692 Some(Token(full, Tok::Block(tokens))) if full.starts_with('[') => {
693 Some(p.with(tokens, "]", Self::path_part))
694 }
695 _ => None,
696 })?;
697 Some((part, self.opt()))
698 }
699
700 fn str_key(&mut self) -> Result<'s, 't, Term<&'s str>> {
701 match self.i.next() {
702 Some(Token(id, Tok::Fmt)) => match self.i.next() {
703 Some(Token(_, Tok::Str(parts))) => Ok(Term::Str(Some(*id), self.str_parts(parts))),
704 next => Err((Expect::Str, next)),
705 },
706 Some(Token(_, Tok::Str(parts))) => Ok(Term::Str(None, self.str_parts(parts))),
707 next => Err((Expect::Key, next)),
708 }
709 }
710
711 fn opt(&mut self) -> path::Opt {
712 let mut opt = path::Opt::Essential;
713 while self.char0('?').is_some() {
714 opt = path::Opt::Optional;
715 }
716 opt
717 }
718
719 pub fn defs(&mut self) -> Result<'s, 't, Vec<Def<&'s str>>> {
721 let head = |p: &mut Self| p.just("def").ok();
722 core::iter::from_fn(|| self.maybe(head).map(|_| self.def_tail())).collect()
723 }
724
725 fn def_tail(&mut self) -> Result<'s, 't, Def<&'s str, Term<&'s str>>> {
727 let name = match self.i.next() {
728 Some(Token(w, Tok::Word | Tok::Fmt)) if !w.contains("::") => w,
729 next => return Err((Expect::Ident, next)),
730 };
731 let args = self.args(|p| match p.i.next() {
732 Some(Token(w, Tok::Word | Tok::Var)) if !w.contains("::") => Ok(*w),
733 next => Err((Expect::Arg, next)),
734 });
735 self.just(":")?;
736
737 let body = self.term()?;
738 self.just(";")?;
739
740 Ok(Def { name, args, body })
741 }
742
743 fn bare_str(&mut self) -> Result<'s, 't, &'s str> {
744 match self.i.next() {
745 next @ Some(Token(_, Tok::Str(parts))) => match parts[..] {
746 [StrPart::Str(s)] => Ok(s),
747 _ => Err((Expect::Str, next)),
748 },
749 next => Err((Expect::Str, next)),
750 }
751 }
752
753 fn dep(&mut self, import: bool) -> Result<'s, 't, Dep<&'s str>> {
755 let path = self.bare_str()?;
756 let name = import.then(|| {
757 self.just("as")?;
758 match self.i.next() {
759 Some(Token(v, Tok::Word | Tok::Var)) => Ok(*v),
760 next => Err((Expect::Ident, next)),
761 }
762 });
763 let name = name.transpose()?;
764 let meta = !matches!(self.i.as_slice(), [Token(";", _), ..]);
765 let meta = meta.then(|| self.term()).transpose()?;
766 Ok((path, name, meta))
767 }
768
769 pub(crate) fn module<B, F>(&mut self, f: F) -> Result<'s, 't, Module<&'s str, B>>
771 where
772 F: FnOnce(&mut Self) -> Result<'s, 't, B>,
773 {
774 let meta = self
775 .maybe(|p| match p.i.next() {
776 Some(Token("module", _)) => Some(p.terminated(Self::term)),
777 _ => None,
778 })
779 .transpose()?;
780
781 let deps = core::iter::from_fn(|| {
782 self.maybe(|p| match p.i.next() {
783 Some(Token("include", _)) => Some(p.terminated(|p| p.dep(false))),
784 Some(Token("import", _)) => Some(p.terminated(|p| p.dep(true))),
785 _ => None,
786 })
787 })
788 .collect::<Result<_>>()?;
789
790 let body = f(self)?;
791
792 Ok(Module { meta, deps, body })
793 }
794}
795
796type Dep<S> = (S, Option<S>, Option<Term<S>>);
797
798#[derive(Debug, Default)]
811pub(crate) struct Module<S, B> {
812 pub meta: Option<Term<S>>,
813 pub deps: Vec<Dep<S>>,
814 pub body: B,
815}
816
817#[derive(Clone)]
828pub struct Def<S = &'static str, F = Term<S>> {
829 pub name: S,
831 pub args: Vec<S>,
833 pub body: F,
835}
836
837impl<S: Debug, F: Debug> Debug for Def<S, F> {
843 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
844 write!(f, "({:?}, {:?}, {:?})", self.name, self.args, self.body)
845 }
846}
847
848impl<S, F> Def<S, F> {
849 pub(crate) fn new(name: S, args: Vec<S>, body: F) -> Self {
850 Self { name, args, body }
851 }
852}
853
854impl<S> prec_climb::Op for BinaryOp<S> {
855 fn precedence(&self) -> usize {
856 use ops::{Cmp, Math};
857 match self {
858 Self::Pipe(None) => 0,
859 Self::Comma => 1,
860 Self::Pipe(Some(_)) => 2,
861 Self::Assign | Self::Update | Self::UpdateMath(_) | Self::UpdateAlt => 3,
862 Self::Alt => 4,
863 Self::Or => Self::Alt.precedence() + 1,
864 Self::And => Self::Or.precedence() + 1,
865 Self::Cmp(Cmp::Eq | Cmp::Ne) => Self::And.precedence() + 1,
866 Self::Cmp(Cmp::Lt | Cmp::Gt | Cmp::Le | Cmp::Ge) => Self::And.precedence() + 2,
867 Self::Math(Math::Add | Math::Sub) => Self::And.precedence() + 3,
868 Self::Math(Math::Mul | Math::Div) => Self::Math(Math::Add).precedence() + 1,
869 Self::Math(Math::Rem) => Self::Math(Math::Mul).precedence() + 1,
870 }
871 }
872
873 fn associativity(&self) -> prec_climb::Associativity {
874 use prec_climb::Associativity;
875 match self {
876 Self::Pipe(_) | Self::Assign | Self::Update | Self::UpdateMath(_) | Self::UpdateAlt => {
877 Associativity::Right
878 }
879 _ => Associativity::Left,
880 }
881 }
882}
883
884impl<S> prec_climb::Expr<BinaryOp<S>> for Term<S> {
885 fn from_op(lhs: Self, op: BinaryOp<S>, rhs: Self) -> Self {
886 Self::BinOp(Box::new(lhs), op, Box::new(rhs))
887 }
888}