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("^")]
|
#[token("^")]
|
||||||
Return,
|
Return,
|
||||||
|
|
||||||
|
#[token("fn")]
|
||||||
|
Fn,
|
||||||
|
|
||||||
#[regex(r"[+*/%=-]")]
|
#[regex(r"[+*/%=-]")]
|
||||||
BinOp(&'a str),
|
BinOp(&'a str),
|
||||||
|
|
||||||
|
|
@ -70,6 +73,7 @@ impl fmt::Display for Token<'_> {
|
||||||
Token::OpenBrace => write!(f, "{{"),
|
Token::OpenBrace => write!(f, "{{"),
|
||||||
Token::CloseBrace => write!(f, "}}"),
|
Token::CloseBrace => write!(f, "}}"),
|
||||||
Token::Return => write!(f, "^"),
|
Token::Return => write!(f, "^"),
|
||||||
|
Token::Fn => write!(f, "fn"),
|
||||||
Token::BinOp(x) | Token::Var(x) | Token::Num(x) => write!(f, "{x}"),
|
Token::BinOp(x) | Token::Var(x) | Token::Num(x) => write!(f, "{x}"),
|
||||||
Token::Error => write!(f, "ERROR"),
|
Token::Error => write!(f, "ERROR"),
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +84,7 @@ fn error_ast() -> Ast {
|
||||||
Ast::Var(Ident::Local("!invalid".to_owned()))
|
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>()
|
fn parser<'tokens, 'src: 'tokens, I>()
|
||||||
-> impl Parser<'tokens, I, Vec<Ast>, extra::Err<Rich<'tokens, Token<'src>>>>
|
-> impl Parser<'tokens, I, Vec<Ast>, extra::Err<Rich<'tokens, Token<'src>>>>
|
||||||
where
|
where
|
||||||
|
|
@ -128,8 +133,8 @@ where
|
||||||
let block = expr
|
let block = expr
|
||||||
.clone()
|
.clone()
|
||||||
.separated_by(semicolon.clone())
|
.separated_by(semicolon.clone())
|
||||||
|
.allow_trailing()
|
||||||
.collect()
|
.collect()
|
||||||
.map(Ast::Block)
|
|
||||||
.delimited_by(just(Token::OpenParen), just(Token::CloseParen))
|
.delimited_by(just(Token::OpenParen), just(Token::CloseParen))
|
||||||
.labelled("block");
|
.labelled("block");
|
||||||
|
|
||||||
|
|
@ -142,12 +147,60 @@ where
|
||||||
.delimited_by(just(Token::OpenBrace), just(Token::CloseBrace))
|
.delimited_by(just(Token::OpenBrace), just(Token::CloseBrace))
|
||||||
.labelled("map");
|
.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((
|
let non_app = choice((
|
||||||
set,
|
set,
|
||||||
num,
|
num,
|
||||||
|
standalone_func,
|
||||||
|
lambda,
|
||||||
ident.map(Ast::Var).labelled("variable"),
|
ident.map(Ast::Var).labelled("variable"),
|
||||||
map,
|
map,
|
||||||
block,
|
block.map(Ast::Block),
|
||||||
));
|
));
|
||||||
|
|
||||||
let app = non_app
|
let app = non_app
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl fmt::Debug for Val {
|
||||||
Self::Number(n) => write!(f, "{n:?}"),
|
Self::Number(n) => write!(f, "{n:?}"),
|
||||||
Self::Function {
|
Self::Function {
|
||||||
inputs, outputs, ..
|
inputs, outputs, ..
|
||||||
} => write!(f, "fn([{}], [{}]", inputs.join(" "), outputs.join(" ")),
|
} => write!(f, "fn([{}] [{}])", inputs.join(" "), outputs.join(" ")),
|
||||||
Self::Map(map) => write!(f, "{map:?}"),
|
Self::Map(map) => write!(f, "{map:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue