parse functions

This commit is contained in:
mehbark 2026-01-02 01:55:25 -05:00
parent 86fb16faea
commit fcac4db1dc
2 changed files with 56 additions and 3 deletions

View file

@ -44,6 +44,9 @@ enum Token<'a> {
#[token("^")]
Return,
#[token("fn")]
Fn,
#[regex(r"[+*/%=-]")]
BinOp(&'a str),
@ -70,6 +73,7 @@ impl fmt::Display for Token<'_> {
Token::OpenBrace => write!(f, "{{"),
Token::CloseBrace => write!(f, "}}"),
Token::Return => write!(f, "^"),
Token::Fn => write!(f, "fn"),
Token::BinOp(x) | Token::Var(x) | Token::Num(x) => write!(f, "{x}"),
Token::Error => write!(f, "ERROR"),
}
@ -80,6 +84,7 @@ fn error_ast() -> Ast {
Ast::Var(Ident::Local("!invalid".to_owned()))
}
#[allow(clippy::too_many_lines, reason = "you're right but leave me alone")]
fn parser<'tokens, 'src: 'tokens, I>()
-> impl Parser<'tokens, I, Vec<Ast>, extra::Err<Rich<'tokens, Token<'src>>>>
where
@ -128,8 +133,8 @@ where
let block = expr
.clone()
.separated_by(semicolon.clone())
.allow_trailing()
.collect()
.map(Ast::Block)
.delimited_by(just(Token::OpenParen), just(Token::CloseParen))
.labelled("block");
@ -142,12 +147,60 @@ where
.delimited_by(just(Token::OpenBrace), just(Token::CloseBrace))
.labelled("map");
let arg_list = select! { Token::Var(s) => s.to_owned() }
.repeated()
.collect()
.delimited_by(just(Token::OpenBracket), just(Token::CloseBracket));
let signature = choice((
// ([x] [y])
arg_list
.clone()
.labelled("input list")
.then(arg_list.clone().labelled("output list")),
// ([x])
arg_list
.clone()
.labelled("input list")
.map(|x: Vec<_>| (x.clone(), x)),
// ()
empty().map(|()| (vec![], vec![])),
))
.delimited_by(just(Token::OpenParen), just(Token::CloseParen))
.labelled("function signature");
let lambda = just(Token::Fn)
.ignore_then(signature.clone())
.then(block.clone())
.map(|((inputs, outputs), body)| Ast::Fn {
inputs,
outputs,
body,
});
// this is purely syntax sugar
let standalone_func = just(Token::Fn)
.ignore_then(ident.clone())
.then(signature.clone())
.then(block.clone())
.map(|((id, (inputs, outputs)), body)| {
let lambda = Ast::Fn {
inputs,
outputs,
body,
};
Ast::Set(id, Box::new(lambda))
})
.labelled("standalone function");
let non_app = choice((
set,
num,
standalone_func,
lambda,
ident.map(Ast::Var).labelled("variable"),
map,
block,
block.map(Ast::Block),
));
let app = non_app

View file

@ -18,7 +18,7 @@ impl fmt::Debug for Val {
Self::Number(n) => write!(f, "{n:?}"),
Self::Function {
inputs, outputs, ..
} => write!(f, "fn([{}], [{}]", inputs.join(" "), outputs.join(" ")),
} => write!(f, "fn([{}] [{}])", inputs.join(" "), outputs.join(" ")),
Self::Map(map) => write!(f, "{map:?}"),
}
}