parse functions
This commit is contained in:
parent
86fb16faea
commit
fcac4db1dc
2 changed files with 56 additions and 3 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue