better parser labelling
This commit is contained in:
parent
cb714e70b7
commit
a93092e925
2 changed files with 38 additions and 30 deletions
|
|
@ -13,7 +13,7 @@ pub enum Ident {
|
|||
pub enum Ast {
|
||||
/// `x`, `^x`
|
||||
Var(Ident),
|
||||
/// `x = y; => y`
|
||||
/// `x := y; #=> y`
|
||||
Set(Ident, Box<Ast>),
|
||||
/// `fn ([a b] [c d]) ( ... )`
|
||||
Fn {
|
||||
|
|
@ -29,4 +29,6 @@ pub enum Ast {
|
|||
BinOp(Box<Ast>, fn(Val, Val) -> Val, Box<Ast>),
|
||||
/// `3`
|
||||
Num(f64),
|
||||
/// `(println bla; 3) #=> 3`
|
||||
Block(Vec<Ast>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,35 +93,42 @@ where
|
|||
select! {
|
||||
Token::Var(s) => Ident::Local(s.to_owned()),
|
||||
},
|
||||
));
|
||||
|
||||
// let semicolon = just(Token::Semicolon).repeated().at_least(1);
|
||||
|
||||
choice((
|
||||
just(Token::OpenParen)
|
||||
.ignore_then(expr.clone())
|
||||
.then_ignore(just(Token::CloseParen)),
|
||||
// expr.clone()
|
||||
// .then(expr.clone())
|
||||
// .map(|(f, x)| Ast::App(Box::new(f), Box::new(x))),
|
||||
ident
|
||||
.clone()
|
||||
.then_ignore(just(Token::Set))
|
||||
.then(expr)
|
||||
.map(|(id, val)| Ast::Set(id, Box::new(val))),
|
||||
ident.map(Ast::Var),
|
||||
select! {
|
||||
Token::Num(n) => n,
|
||||
}
|
||||
.validate(|n, e, emitter| match n.parse::<f64>() {
|
||||
Ok(n) => Ast::Num(n),
|
||||
Err(err) => {
|
||||
emitter.emit(Rich::custom(e.span(), format!("Invalid number: {err}")));
|
||||
error_ast()
|
||||
}
|
||||
}),
|
||||
))
|
||||
.labelled("identifier");
|
||||
|
||||
let set = ident
|
||||
.clone()
|
||||
.then_ignore(just(Token::Set))
|
||||
.then(expr.clone())
|
||||
.map(|(id, val)| Ast::Set(id, Box::new(val)))
|
||||
.labelled("assignment");
|
||||
|
||||
let num = select! {
|
||||
Token::Num(n) => n,
|
||||
}
|
||||
.validate(|n, e, emitter| match n.parse::<f64>() {
|
||||
Ok(n) => Ast::Num(n),
|
||||
Err(err) => {
|
||||
emitter.emit(Rich::custom(e.span(), format!("Invalid number: {err}")));
|
||||
error_ast()
|
||||
}
|
||||
})
|
||||
.labelled("number");
|
||||
|
||||
let semicolon = just(Token::Semicolon)
|
||||
.repeated()
|
||||
.at_least(1)
|
||||
.labelled("semicolon");
|
||||
|
||||
let block = just(Token::OpenParen)
|
||||
.ignore_then(expr.clone().separated_by(semicolon).collect())
|
||||
.then_ignore(just(Token::CloseParen))
|
||||
.map(Ast::Block)
|
||||
.labelled("block");
|
||||
|
||||
choice((set, ident.map(Ast::Var).labelled("variable"), num, block))
|
||||
})
|
||||
.labelled("expression")
|
||||
.then_ignore(just(Token::Semicolon).repeated().at_least(1))
|
||||
.repeated()
|
||||
.collect()
|
||||
|
|
@ -134,8 +141,7 @@ pub fn parse(src: &str) -> Vec<Ast> {
|
|||
Err(()) => (Token::Error, span.into()),
|
||||
});
|
||||
|
||||
let token_stream =
|
||||
Stream::from_iter(token_iter).map((0..src.len()).into(), |(t, s): (_, _)| (t, s));
|
||||
let token_stream = Stream::from_iter(token_iter).map((src.len()..src.len()).into(), |x| x);
|
||||
|
||||
let source_filename = "input";
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue