rudus/src/parser.rs

659 lines
20 KiB
Rust
Raw Normal View History

2025-06-25 21:43:30 +00:00
// TODO: move AST to its own module
// TODO: remove StringMatcher cruft
// TODO: good error messages?
2025-06-27 23:05:17 +00:00
use crate::ast::{Ast, StringPart};
2024-10-31 20:59:26 +00:00
use crate::lexer::*;
use crate::spans::*;
use chumsky::{input::ValueInput, prelude::*, recursive::Recursive};
use std::fmt;
2024-11-09 19:10:08 +00:00
pub struct StringMatcher();
2024-12-10 23:40:43 +00:00
impl PartialEq for StringMatcher {
fn eq(&self, _other: &StringMatcher) -> bool {
true
}
}
impl Clone for StringMatcher {
fn clone(&self) -> StringMatcher {
unreachable!()
}
}
impl fmt::Display for StringMatcher {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "string matcher")
}
}
impl fmt::Debug for StringMatcher {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "string matcher")
}
}
2024-12-04 23:30:03 +00:00
fn is_word_char(c: char) -> bool {
if c.is_ascii_alphanumeric() {
return true;
};
matches!(c, '_' | '/' | '?' | '!')
}
fn parse_string(s: &'static str, span: SimpleSpan) -> Result<Vec<Spanned<StringPart>>, String> {
// println!("parsing string pattern: {s}");
2024-12-04 23:30:03 +00:00
let mut parts = vec![];
let mut current_part = String::new();
let mut start = span.start;
let mut is_word = false;
let mut chars = s.char_indices();
while let Some((i, char)) = chars.next() {
match char {
'{' => {
if is_word {
return Err("interpolations must only contain words".to_string());
};
match chars.next() {
None => return Err("unclosed brace".to_string()),
Some((_, '{')) => current_part.push('{'),
Some((i, c)) => {
if !current_part.is_empty() {
parts.push((
StringPart::Data(current_part),
SimpleSpan::new(span.context(), start..start + i),
2024-12-04 23:30:03 +00:00
));
};
current_part = String::new();
start = i;
is_word = true;
if c.is_ascii_lowercase() {
current_part.push(c);
} else {
return Err("interpolations must only contain words".to_string());
}
}
}
}
'}' => {
if is_word {
parts.push((
StringPart::Word(current_part.clone()),
SimpleSpan::new(span.context(), start..start + i),
2024-12-04 23:30:03 +00:00
));
current_part = String::new();
start = i;
is_word = false;
} else {
match chars.next() {
None => return Err("unclosed brace".to_string()),
Some((_, c)) => current_part.push(c),
}
}
}
_ => {
if is_word {
if is_word_char(char) {
current_part.push(char)
} else {
return Err("interpolations must only contain words".to_string());
}
} else {
current_part.push(char)
}
}
}
}
if current_part == s {
parts.push((
StringPart::Inline(current_part),
SimpleSpan::new(span.context(), start..span.end),
))
2025-06-06 01:23:08 +00:00
} else if !current_part.is_empty() {
let part_len = current_part.len();
parts.push((
StringPart::Data(current_part),
SimpleSpan::new(span.context(), start..part_len),
2025-06-06 01:23:08 +00:00
))
}
2024-12-04 23:30:03 +00:00
Ok(parts)
2024-12-04 20:03:09 +00:00
}
pub fn parser<I>(
) -> impl Parser<'static, I, Spanned<Ast>, extra::Err<Rich<'static, Token, Span>>> + Clone
2024-10-31 20:59:26 +00:00
where
I: ValueInput<'static, Token = Token, Span = Span>,
2024-10-31 20:59:26 +00:00
{
2024-12-10 23:40:43 +00:00
use Ast::*;
2024-10-31 20:59:26 +00:00
let mut expr = Recursive::declare();
let mut pattern = Recursive::declare();
let mut simple = Recursive::declare();
let mut nonbinding = Recursive::declare();
let separators = recursive(|separators| {
just(Token::Punctuation(","))
.or(just(Token::Punctuation("\n")))
.then(separators.clone().repeated())
});
let terminators = recursive(|terminators| {
just(Token::Punctuation(";"))
.or(just(Token::Punctuation("\n")))
.then(terminators.clone().repeated())
});
let placeholder_pattern =
2024-12-10 23:40:43 +00:00
select! {Token::Punctuation("_") => PlaceholderPattern}.map_with(|p, e| (p, e.span()));
2024-10-31 20:59:26 +00:00
2024-12-10 23:40:43 +00:00
let word_pattern = select! { Token::Word(w) => WordPattern(w) }.map_with(|w, e| (w, e.span()));
2024-10-31 20:59:26 +00:00
let atom_pattern = select! {
2024-12-10 23:40:43 +00:00
Token::Nil => NilPattern,
Token::Boolean(b) => BooleanPattern(b),
Token::Number(n) => NumberPattern(n),
Token::Keyword(k) => KeywordPattern(k),
2024-10-31 20:59:26 +00:00
}
.map_with(|a, e| (a, e.span()));
let string_pattern = select! {Token::String(s) => s}.try_map_with(|s, e| {
let parsed = parse_string(s, e.span());
match parsed {
Ok(parts) => match parts[0] {
2024-12-10 23:40:43 +00:00
(StringPart::Inline(_), _) => Ok((StringPattern(s), e.span())),
_ => Ok((InterpolatedPattern(parts.clone()), e.span())),
},
Err(msg) => Err(Rich::custom(e.span(), msg)),
}
});
2024-11-18 18:25:54 +00:00
let bare_splat = just(Token::Punctuation("...")).map_with(|_, e| {
(
2024-12-10 23:40:43 +00:00
Splattern(Box::new((PlaceholderPattern, e.span()))),
2024-11-18 18:25:54 +00:00
e.span(),
)
});
2024-11-22 00:54:50 +00:00
let splattable = word_pattern.or(placeholder_pattern);
2024-11-18 18:25:54 +00:00
let patt_splat = just(Token::Punctuation("..."))
.ignore_then(splattable)
2024-12-10 23:40:43 +00:00
.map_with(|x, e| (Splattern(Box::new(x)), e.span()));
2024-11-18 18:25:54 +00:00
let splattern = patt_splat.or(bare_splat);
2024-10-31 20:59:26 +00:00
let tuple_pattern = pattern
.clone()
2024-11-18 18:25:54 +00:00
.or(splattern.clone())
2024-10-31 20:59:26 +00:00
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
2024-12-10 23:40:43 +00:00
.map_with(|tuple, e| (TuplePattern(tuple), e.span()))
2024-10-31 20:59:26 +00:00
.labelled("tuple pattern");
let list_pattern = pattern
.clone()
2024-11-18 18:25:54 +00:00
.or(splattern.clone())
2024-10-31 20:59:26 +00:00
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
2024-12-10 23:40:43 +00:00
.map_with(|list, e| (ListPattern(list), e.span()));
2024-10-31 20:59:26 +00:00
let pair_pattern = select! {Token::Keyword(k) => k}
2024-10-31 20:59:26 +00:00
.then(pattern.clone())
2024-12-10 23:40:43 +00:00
.map_with(|(key, patt), e| (PairPattern(key, Box::new(patt)), e.span()));
2024-10-31 20:59:26 +00:00
let shorthand_pattern = select! {Token::Word(w) => w}.map_with(|w, e| {
(
2024-12-10 23:40:43 +00:00
PairPattern(w, Box::new((WordPattern(w), e.span()))),
2024-10-31 20:59:26 +00:00
e.span(),
)
});
let dict_pattern = pair_pattern
.or(shorthand_pattern)
2024-11-21 01:10:17 +00:00
.or(splattern.clone())
2024-10-31 20:59:26 +00:00
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(
just(Token::Punctuation("#{")),
just(Token::Punctuation("}")),
)
2024-12-10 23:40:43 +00:00
.map_with(|dict, e| (DictPattern(dict), e.span()));
2024-10-31 20:59:26 +00:00
2024-12-10 23:40:43 +00:00
let keyword = select! {Token::Keyword(k) => Keyword(k),}.map_with(|k, e| (k, e.span()));
2024-11-09 19:10:08 +00:00
let as_pattern = select! {Token::Word(w) => w}
.then_ignore(just(Token::Reserved("as")))
.then(select! {Token::Keyword(k) => k})
2024-12-10 23:40:43 +00:00
.map_with(|(w, t), e| (AsPattern(w, t), e.span()));
2024-11-09 19:10:08 +00:00
2024-10-31 20:59:26 +00:00
pattern.define(
atom_pattern
.or(string_pattern)
2024-11-09 19:10:08 +00:00
.or(as_pattern)
2024-10-31 20:59:26 +00:00
.or(word_pattern)
.or(placeholder_pattern)
.or(tuple_pattern.clone())
.or(list_pattern)
.or(dict_pattern)
.labelled("pattern"),
);
let placeholder =
2024-12-10 23:40:43 +00:00
select! {Token::Punctuation("_") => Placeholder}.map_with(|p, e| (p, e.span()));
2024-10-31 20:59:26 +00:00
2024-12-10 23:40:43 +00:00
let word = select! { Token::Word(w) => Word(w) }
2024-10-31 20:59:26 +00:00
.map_with(|w, e| (w, e.span()))
.labelled("word");
let value = select! {
2024-12-10 23:40:43 +00:00
Token::Nil => Nil,
Token::Boolean(b) => Boolean(b),
Token::Number(n) => Number(n),
2024-10-31 20:59:26 +00:00
}
.map_with(|v, e| (v, e.span()));
2024-12-04 23:30:03 +00:00
let string = select! {Token::String(s) => s}.try_map_with(|s, e| {
let parsed = parse_string(s, e.span());
match parsed {
Ok(parts) => match parts[0] {
2024-12-10 23:40:43 +00:00
(StringPart::Inline(_), _) => Ok((String(s), e.span())),
_ => Ok((Interpolated(parts), e.span())),
2024-12-04 23:30:03 +00:00
},
Err(msg) => Err(Rich::custom(e.span(), msg)),
}
});
2024-11-22 03:36:57 +00:00
2024-10-31 20:59:26 +00:00
let tuple = simple
.clone()
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
2024-12-10 23:40:43 +00:00
.map_with(|tuple, e| (Tuple(tuple), e.span()));
2024-10-31 20:59:26 +00:00
let args = simple
.clone()
.or(placeholder)
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
2024-12-10 23:40:43 +00:00
.map_with(|args, e| (Arguments(args), e.span()));
2024-10-31 20:59:26 +00:00
2025-05-28 20:37:25 +00:00
let or = just(Token::Reserved("or")).map_with(|_, e| (Or, e.span()));
let and = just(Token::Reserved("and")).map_with(|_, e| (And, e.span()));
let synth_root = or.or(and).or(word).or(keyword);
2024-10-31 20:59:26 +00:00
2024-11-22 00:54:50 +00:00
let synth_term = keyword.or(args);
2024-10-31 20:59:26 +00:00
let synthetic = synth_root
.then(synth_term.clone())
.then(synth_term.clone().repeated().collect())
.map_with(|((root, first), rest), e| {
2024-12-10 23:40:43 +00:00
(Synthetic(Box::new(root), Box::new(first), rest), e.span())
2024-10-31 20:59:26 +00:00
});
2024-11-21 21:41:46 +00:00
let splat = just(Token::Punctuation("..."))
2024-11-22 00:54:50 +00:00
.ignore_then(word)
2024-11-21 21:41:46 +00:00
.map_with(|(w, _), e| {
(
2024-12-10 23:40:43 +00:00
Splat(if let Word(w) = w { w } else { unreachable!() }),
2024-11-21 21:41:46 +00:00
e.span(),
)
});
2024-10-31 20:59:26 +00:00
let list = simple
.clone()
2024-11-21 21:41:46 +00:00
.or(splat.clone())
2024-10-31 20:59:26 +00:00
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
2024-12-10 23:40:43 +00:00
.map_with(|list, e| (List(list), e.span()));
2024-10-31 20:59:26 +00:00
let pair = select! {Token::Keyword(k) => k}
2024-10-31 20:59:26 +00:00
.then(simple.clone())
2024-12-10 23:40:43 +00:00
.map_with(|(key, value), e| (Pair(key, Box::new(value)), e.span()));
2024-10-31 20:59:26 +00:00
2024-11-21 21:41:46 +00:00
let shorthand = select! {Token::Word(w) => w}
2024-12-10 23:40:43 +00:00
.map_with(|w, e| (Pair(w, Box::new((Word(w), e.span()))), e.span()));
2024-10-31 20:59:26 +00:00
let dict = pair
.or(shorthand)
2024-11-21 21:41:46 +00:00
.or(splat.clone())
2024-10-31 20:59:26 +00:00
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(
just(Token::Punctuation("#{")),
just(Token::Punctuation("}")),
)
2024-12-10 23:40:43 +00:00
.map_with(|dict, e| (Dict(dict), e.span()));
2024-10-31 20:59:26 +00:00
2024-11-21 21:41:46 +00:00
let recur = just(Token::Reserved("recur"))
.ignore_then(tuple.clone())
.map_with(|args, e| {
2024-12-10 23:40:43 +00:00
let (Tuple(args), _) = args else {
2024-11-21 21:41:46 +00:00
unreachable!()
};
2024-12-10 23:40:43 +00:00
(Recur(args), e.span())
2024-11-21 21:41:46 +00:00
});
2024-10-31 20:59:26 +00:00
let block = expr
.clone()
.separated_by(terminators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}")))
2024-12-10 23:40:43 +00:00
.map_with(|block, e| (Block(block), e.span()))
2024-10-31 20:59:26 +00:00
.recover_with(via_parser(nested_delimiters(
Token::Punctuation("{"),
Token::Punctuation("}"),
[
(Token::Punctuation("("), Token::Punctuation(")")),
(Token::Punctuation("["), Token::Punctuation("]")),
],
2024-12-10 23:40:43 +00:00
|span| (Error, span),
2024-10-31 20:59:26 +00:00
)));
let r#if = just(Token::Reserved("if"))
2024-10-31 20:59:26 +00:00
.ignore_then(simple.clone())
2024-12-09 04:33:02 +00:00
.then_ignore(terminators.clone().or_not())
2024-10-31 20:59:26 +00:00
.then_ignore(just(Token::Reserved("then")))
.then(expr.clone())
2024-12-09 04:33:02 +00:00
.then_ignore(terminators.clone().or_not())
2024-10-31 20:59:26 +00:00
.then_ignore(just(Token::Reserved("else")))
.then(expr.clone())
.map_with(|((condition, then_branch), else_branch), e| {
(
2024-12-10 23:40:43 +00:00
If(
2024-10-31 20:59:26 +00:00
Box::new(condition),
Box::new(then_branch),
Box::new(else_branch),
),
e.span(),
)
});
let when_clause = simple
.clone()
.then_ignore(just(Token::Punctuation("->")))
.then(expr.clone())
2024-12-10 23:40:43 +00:00
.map_with(|(cond, body), e| (WhenClause(Box::new(cond), Box::new(body)), e.span()));
2024-10-31 20:59:26 +00:00
let when = just(Token::Reserved("when"))
.ignore_then(
when_clause
.separated_by(terminators.clone())
.allow_trailing()
.allow_leading()
.collect()
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}"))),
)
2024-12-10 23:40:43 +00:00
.map_with(|clauses, e| (When(clauses), e.span()));
2024-10-31 20:59:26 +00:00
2024-11-21 01:10:17 +00:00
let guarded_clause = pattern
.clone()
.then_ignore(just(Token::Reserved("if")))
.then(simple.clone())
.then_ignore(just(Token::Punctuation("->")))
.then(expr.clone())
2024-12-10 23:40:43 +00:00
.map_with(|((patt, guard), body), e| {
(
MatchClause(Box::new(patt), Box::new(Some(guard)), Box::new(body)),
e.span(),
)
2024-11-21 01:10:17 +00:00
});
2024-10-31 20:59:26 +00:00
let match_clause = pattern
.clone()
.then_ignore(just(Token::Punctuation("->")))
.then(expr.clone())
2024-12-10 23:40:43 +00:00
.map_with(|(patt, body), e| {
(
MatchClause(Box::new(patt), Box::new(None), Box::new(body)),
e.span(),
)
2024-11-09 19:10:08 +00:00
});
2024-10-31 20:59:26 +00:00
2024-12-10 23:40:43 +00:00
let r#match = just(Token::Reserved("match"))
2024-10-31 20:59:26 +00:00
.ignore_then(simple.clone())
.then_ignore(just(Token::Reserved("with")))
.then(
match_clause
.clone()
.or(guarded_clause.clone())
2024-10-31 20:59:26 +00:00
.separated_by(terminators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}"))),
)
2024-12-10 23:40:43 +00:00
.map_with(|(expr, clauses), e| (Match(Box::new(expr), clauses), e.span()));
2024-10-31 20:59:26 +00:00
let receive = just(Token::Reserved("receive"))
.ignore_then(
match_clause
.clone()
.or(guarded_clause)
.separated_by(terminators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}"))),
)
.map_with(|clauses, e| (Receive(clauses), e.span()));
let conditional = when.or(r#if).or(r#match).or(receive);
2024-10-31 20:59:26 +00:00
let panic = just(Token::Reserved("panic!"))
.ignore_then(nonbinding.clone())
2024-12-10 23:40:43 +00:00
.map_with(|expr, e| (Panic(Box::new(expr)), e.span()));
2024-10-31 20:59:26 +00:00
let do_ = just(Token::Reserved("do"))
.ignore_then(
nonbinding
.clone()
.separated_by(
just(Token::Punctuation(">")).then(just(Token::Punctuation("\n")).repeated()),
)
.collect(),
)
2024-12-10 23:40:43 +00:00
.map_with(|exprs, e| (Do(exprs), e.span()));
2024-10-31 20:59:26 +00:00
let repeat = just(Token::Reserved("repeat"))
.ignore_then(simple.clone())
.then(block.clone())
2024-12-10 23:40:43 +00:00
.map_with(|(count, body), e| (Repeat(Box::new(count), Box::new(body)), e.span()));
2024-10-31 20:59:26 +00:00
2024-11-21 01:10:17 +00:00
let fn_guarded = tuple_pattern
.clone()
.then_ignore(just(Token::Reserved("if")))
.then(simple.clone())
.then_ignore(just(Token::Punctuation("->")))
.then(nonbinding.clone())
2024-12-10 23:40:43 +00:00
.map_with(|((patt, guard), body), e| {
(
MatchClause(Box::new(patt), Box::new(Some(guard)), Box::new(body)),
e.span(),
)
2024-11-21 01:10:17 +00:00
})
.labelled("function clause");
2024-11-21 21:41:46 +00:00
let fn_unguarded = tuple_pattern
2024-10-31 20:59:26 +00:00
.clone()
.then_ignore(just(Token::Punctuation("->")))
.then(nonbinding.clone())
2024-12-10 23:40:43 +00:00
.map_with(|(patt, body), e| {
(
MatchClause(Box::new(patt), Box::new(None), Box::new(body)),
e.span(),
)
2024-11-09 19:10:08 +00:00
})
2024-10-31 20:59:26 +00:00
.labelled("function clause");
2024-11-21 21:41:46 +00:00
let fn_clause = fn_guarded.clone().or(fn_unguarded.clone());
2024-10-31 20:59:26 +00:00
let lambda = just(Token::Reserved("fn"))
2024-11-21 21:41:46 +00:00
.ignore_then(fn_unguarded.clone())
2024-12-24 17:35:44 +00:00
.map_with(|clause, e| {
(
Fn("", Box::new((Ast::FnBody(vec![clause]), e.span())), None),
e.span(),
)
});
2024-10-31 20:59:26 +00:00
2024-11-22 03:36:57 +00:00
let fn_clauses = fn_clause
2024-11-21 21:41:46 +00:00
.clone()
.separated_by(terminators.clone())
.allow_leading()
.allow_trailing()
2024-11-22 03:36:57 +00:00
.collect();
let loop_multiclause = fn_clauses
.clone()
2024-11-21 21:41:46 +00:00
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}")));
2024-11-21 22:10:50 +00:00
let fn_single_clause = fn_clause.clone().map_with(|c, _| vec![c]);
2024-11-21 21:41:46 +00:00
let r#loop = just(Token::Reserved("loop"))
.ignore_then(tuple.clone())
.then_ignore(just(Token::Reserved("with")))
2024-11-22 03:36:57 +00:00
.then(loop_multiclause.clone().or(fn_single_clause.clone()))
2024-12-10 23:40:43 +00:00
.map_with(|(init, body), e| (Loop(Box::new(init), body), e.span()));
2024-11-21 21:41:46 +00:00
2024-12-09 04:33:02 +00:00
simple.define(
synthetic
.or(recur)
.or(word)
.or(keyword)
.or(value)
.or(tuple.clone())
.or(list)
.or(dict)
.or(string)
.or(lambda.clone())
.labelled("simple expression"),
);
2024-10-31 20:59:26 +00:00
nonbinding.define(
simple
.clone()
.or(conditional)
.or(block)
.or(panic)
.or(do_)
.or(repeat)
2024-11-21 21:41:46 +00:00
.or(r#loop)
2024-10-31 20:59:26 +00:00
.labelled("nonbinding expression"),
);
let let_ = just(Token::Reserved("let"))
.ignore_then(pattern.clone())
.then_ignore(just(Token::Punctuation("=")))
.then(nonbinding.clone())
.map_with(|(pattern, expression), e| {
2024-12-10 23:40:43 +00:00
(Let(Box::new(pattern), Box::new(expression)), e.span())
2024-10-31 20:59:26 +00:00
});
let box_ = just(Token::Reserved("box"))
2024-11-22 00:54:50 +00:00
.ignore_then(word)
2024-10-31 20:59:26 +00:00
.then_ignore(just(Token::Punctuation("=")))
.then(nonbinding.clone())
.map_with(|(word, expr), e| {
2024-12-10 23:40:43 +00:00
let name = if let Word(w) = word.0 {
2024-10-31 20:59:26 +00:00
w
} else {
unreachable!()
};
2024-12-10 23:40:43 +00:00
(LBox(name, Box::new(expr)), e.span())
2024-10-31 20:59:26 +00:00
});
let fn_decl = just(Token::Reserved("fn"))
2024-11-22 00:54:50 +00:00
.ignore_then(word)
2024-10-31 20:59:26 +00:00
.map_with(|(word, _), e| {
2024-12-10 23:40:43 +00:00
let name = if let Word(w) = word {
2024-10-31 20:59:26 +00:00
w
} else {
unreachable!()
};
2024-12-10 23:40:43 +00:00
(FnDeclaration(name), e.span())
2024-10-31 20:59:26 +00:00
});
let fn_named = just(Token::Reserved("fn"))
2024-11-22 00:54:50 +00:00
.ignore_then(word)
2024-11-21 21:41:46 +00:00
.then(fn_unguarded.clone())
2024-10-31 20:59:26 +00:00
.map_with(|(word, clause), e| {
2024-12-10 23:40:43 +00:00
let name = if let Word(word) = word.0 {
2024-10-31 20:59:26 +00:00
word
} else {
unreachable!()
};
2024-12-24 17:35:44 +00:00
(
Fn(name, Box::new((Ast::FnBody(vec![clause]), e.span())), None),
e.span(),
)
2024-10-31 20:59:26 +00:00
});
2024-11-22 03:36:57 +00:00
let docstr = select! {Token::String(s) => s};
let fn_multiclause = separators
.clone()
.or_not()
.ignore_then(docstr.or_not())
.then(fn_clauses.clone())
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}")))
.map_with(|(docstr, clauses), e| (docstr, clauses, e.span()));
2024-10-31 20:59:26 +00:00
let fn_compound = just(Token::Reserved("fn"))
2024-11-22 00:54:50 +00:00
.ignore_then(word)
2024-11-22 03:36:57 +00:00
.then(fn_multiclause)
.map_with(|(word, (docstr, clauses, _)), e| {
2024-12-10 23:40:43 +00:00
let name = if let Word(word) = word.0 {
2024-10-31 20:59:26 +00:00
word
} else {
unreachable!()
};
2024-12-24 17:35:44 +00:00
(
Fn(name, Box::new((Ast::FnBody(clauses), e.span())), docstr),
e.span(),
)
2024-10-31 20:59:26 +00:00
});
let fn_ = fn_named.or(fn_compound).or(fn_decl);
let binding = let_.or(box_).or(fn_);
expr.define(binding.or(nonbinding));
let script = expr
.separated_by(terminators.clone())
.allow_trailing()
.allow_leading()
.collect()
2024-12-10 23:40:43 +00:00
.map_with(|exprs, e| (Block(exprs), e.span()));
2024-10-31 20:59:26 +00:00
script
}