add pipeline and logical ops to expr parsing
Co-authored-by: rvcas <x@rvcas.dev>
This commit is contained in:
parent
fff38e30d2
commit
60359ec9b0
|
@ -1,4 +1,5 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
use vec1::Vec1;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, BinOp, TodoKind},
|
ast::{self, BinOp, TodoKind},
|
||||||
|
@ -175,9 +176,7 @@ pub fn fn_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseEr
|
||||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
|
||||||
)
|
)
|
||||||
.then(just(Token::RArrow).ignore_then(type_parser()).or_not())
|
.then(just(Token::RArrow).ignore_then(type_parser()).or_not())
|
||||||
.then_ignore(just(Token::LeftBrace))
|
.then(expr_seq_parser().delimited_by(just(Token::LeftBrace), just(Token::RightBrace)))
|
||||||
.then(expr_seq_parser())
|
|
||||||
.then_ignore(just(Token::RightBrace))
|
|
||||||
.map_with_span(
|
.map_with_span(
|
||||||
|((((opt_pub, name), arguments), return_annotation), body), span| {
|
|((((opt_pub, name), arguments), return_annotation), body), span| {
|
||||||
ast::UntypedDefinition::Fn {
|
ast::UntypedDefinition::Fn {
|
||||||
|
@ -261,6 +260,7 @@ pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseE
|
||||||
|
|
||||||
pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
|
pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
|
||||||
recursive(|_r| {
|
recursive(|_r| {
|
||||||
|
// Product
|
||||||
let op = choice((
|
let op = choice((
|
||||||
just(Token::Star).to(BinOp::MultInt),
|
just(Token::Star).to(BinOp::MultInt),
|
||||||
just(Token::Slash).to(BinOp::DivInt),
|
just(Token::Slash).to(BinOp::DivInt),
|
||||||
|
@ -277,12 +277,13 @@ pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError
|
||||||
})
|
})
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
|
// Sum
|
||||||
let op = choice((
|
let op = choice((
|
||||||
just(Token::Plus).to(BinOp::AddInt),
|
just(Token::Plus).to(BinOp::AddInt),
|
||||||
just(Token::Minus).to(BinOp::SubInt),
|
just(Token::Minus).to(BinOp::SubInt),
|
||||||
));
|
));
|
||||||
|
|
||||||
product
|
let sum = product
|
||||||
.clone()
|
.clone()
|
||||||
.then(op.then(product).repeated())
|
.then(op.then(product).repeated())
|
||||||
.foldl(|a, (op, b)| expr::UntypedExpr::BinOp {
|
.foldl(|a, (op, b)| expr::UntypedExpr::BinOp {
|
||||||
|
@ -291,6 +292,60 @@ pub fn expr_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError
|
||||||
left: Box::new(a),
|
left: Box::new(a),
|
||||||
right: Box::new(b),
|
right: Box::new(b),
|
||||||
})
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
// Logical
|
||||||
|
let op = choice((
|
||||||
|
just(Token::EqualEqual).to(BinOp::Eq),
|
||||||
|
just(Token::NotEqual).to(BinOp::NotEq),
|
||||||
|
just(Token::Less).to(BinOp::LtInt),
|
||||||
|
just(Token::Greater).to(BinOp::GtInt),
|
||||||
|
just(Token::LessEqual).to(BinOp::LtEqInt),
|
||||||
|
just(Token::GreaterEqual).to(BinOp::GtEqInt),
|
||||||
|
));
|
||||||
|
|
||||||
|
let comparison = sum
|
||||||
|
.clone()
|
||||||
|
.then(op.then(sum).repeated())
|
||||||
|
.foldl(|a, (op, b)| expr::UntypedExpr::BinOp {
|
||||||
|
location: a.location().union(b.location()),
|
||||||
|
name: op,
|
||||||
|
left: Box::new(a),
|
||||||
|
right: Box::new(b),
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
let op = choice((
|
||||||
|
just(Token::AmperAmper).to(BinOp::And),
|
||||||
|
just(Token::VbarVbar).to(BinOp::Or),
|
||||||
|
));
|
||||||
|
|
||||||
|
let logical = comparison
|
||||||
|
.clone()
|
||||||
|
.then(op.then(comparison).repeated())
|
||||||
|
.foldl(|a, (op, b)| expr::UntypedExpr::BinOp {
|
||||||
|
location: a.location().union(b.location()),
|
||||||
|
name: op,
|
||||||
|
left: Box::new(a),
|
||||||
|
right: Box::new(b),
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
// Pipeline
|
||||||
|
logical
|
||||||
|
.clone()
|
||||||
|
.then(just(Token::Pipe).ignore_then(logical).repeated())
|
||||||
|
.foldl(|l, r| {
|
||||||
|
let expressions = if let expr::UntypedExpr::PipeLine { mut expressions } = l {
|
||||||
|
expressions.push(r);
|
||||||
|
expressions
|
||||||
|
} else {
|
||||||
|
let mut expressions = Vec1::new(l);
|
||||||
|
expressions.push(r);
|
||||||
|
expressions
|
||||||
|
};
|
||||||
|
expr::UntypedExpr::PipeLine { expressions }
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,18 +630,11 @@ mod tests {
|
||||||
a + 1
|
a + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thing(a: Int) -> List(Int) {
|
pub fn thing(thing a: Int) {
|
||||||
let wow =
|
a + 2
|
||||||
[1, 2, 3]
|
|> add_one
|
||||||
|> list.map(fn(x) { x + a })
|
|> add_one
|
||||||
|> list.filter(fn(x: Int) -> Bool { x % 2 == 0 })
|
|
||||||
|
|
||||||
let who =
|
|
||||||
wow |> list.map(fn(x) { x + a })
|
|
||||||
|
|
||||||
who
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
"#;
|
"#;
|
||||||
let len = code.chars().count();
|
let len = code.chars().count();
|
||||||
|
|
||||||
|
@ -817,6 +865,53 @@ mod tests {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
},
|
},
|
||||||
|
ast::UntypedDefinition::Fn {
|
||||||
|
arguments: vec![ast::Arg {
|
||||||
|
arg_name: ast::ArgName::NamedLabeled {
|
||||||
|
name: "a".to_string(),
|
||||||
|
label: "thing".to_string(),
|
||||||
|
location: Span::new(SrcId::empty(), 487..494),
|
||||||
|
},
|
||||||
|
location: Span::new(SrcId::empty(), 487..499),
|
||||||
|
annotation: Some(ast::Annotation::Constructor {
|
||||||
|
location: Span::new(SrcId::empty(), 496..499),
|
||||||
|
module: None,
|
||||||
|
name: "Int".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
},),
|
||||||
|
tipo: (),
|
||||||
|
},],
|
||||||
|
body: expr::UntypedExpr::PipeLine {
|
||||||
|
expressions: vec1::vec1![
|
||||||
|
expr::UntypedExpr::BinOp {
|
||||||
|
location: Span::new(SrcId::empty(), 519..524),
|
||||||
|
name: ast::BinOp::AddInt,
|
||||||
|
left: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new(SrcId::empty(), 519..520),
|
||||||
|
name: "a".to_string(),
|
||||||
|
}),
|
||||||
|
right: Box::new(expr::UntypedExpr::Int {
|
||||||
|
location: Span::new(SrcId::empty(), 523..524),
|
||||||
|
value: "2".to_string(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
expr::UntypedExpr::Var {
|
||||||
|
location: Span::new(SrcId::empty(), 544..551),
|
||||||
|
name: "add_one".to_string(),
|
||||||
|
},
|
||||||
|
expr::UntypedExpr::Var {
|
||||||
|
location: Span::new(SrcId::empty(), 571..578),
|
||||||
|
name: "add_one".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new(SrcId::empty(), 474..592),
|
||||||
|
name: "thing".to_string(),
|
||||||
|
public: true,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue