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 {
|
pub enum Ast {
|
||||||
/// `x`, `^x`
|
/// `x`, `^x`
|
||||||
Var(Ident),
|
Var(Ident),
|
||||||
/// `x = y; => y`
|
/// `x := y; #=> y`
|
||||||
Set(Ident, Box<Ast>),
|
Set(Ident, Box<Ast>),
|
||||||
/// `fn ([a b] [c d]) ( ... )`
|
/// `fn ([a b] [c d]) ( ... )`
|
||||||
Fn {
|
Fn {
|
||||||
|
|
@ -29,4 +29,6 @@ pub enum Ast {
|
||||||
BinOp(Box<Ast>, fn(Val, Val) -> Val, Box<Ast>),
|
BinOp(Box<Ast>, fn(Val, Val) -> Val, Box<Ast>),
|
||||||
/// `3`
|
/// `3`
|
||||||
Num(f64),
|
Num(f64),
|
||||||
|
/// `(println bla; 3) #=> 3`
|
||||||
|
Block(Vec<Ast>),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,35 +93,42 @@ where
|
||||||
select! {
|
select! {
|
||||||
Token::Var(s) => Ident::Local(s.to_owned()),
|
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))
|
.then_ignore(just(Token::Semicolon).repeated().at_least(1))
|
||||||
.repeated()
|
.repeated()
|
||||||
.collect()
|
.collect()
|
||||||
|
|
@ -134,8 +141,7 @@ pub fn parse(src: &str) -> Vec<Ast> {
|
||||||
Err(()) => (Token::Error, span.into()),
|
Err(()) => (Token::Error, span.into()),
|
||||||
});
|
});
|
||||||
|
|
||||||
let token_stream =
|
let token_stream = Stream::from_iter(token_iter).map((src.len()..src.len()).into(), |x| x);
|
||||||
Stream::from_iter(token_iter).map((0..src.len()).into(), |(t, s): (_, _)| (t, s));
|
|
||||||
|
|
||||||
let source_filename = "input";
|
let source_filename = "input";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue