Add parse for binary operators

This commit is contained in:
Sofia 2026-03-14 16:09:58 +02:00
parent af27da619d
commit 9c56d807fe
2 changed files with 83 additions and 2 deletions

View File

@ -1,6 +1,6 @@
function max (a, b) function max (a, b)
local m = a local m = a
if a then if b > a then
m = b m = b
end end
return m return m

View File

@ -250,10 +250,91 @@ pub enum DefinitionKind {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Expression { pub enum Expression {
ValueRef(String), ValueRef(String),
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
} }
impl Parse for Expression { impl Parse for Expression {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> { fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
Ok(Expression::ValueRef(stream.parse()?)) let primary_expr = stream.parse::<PrimaryExpression>()?;
parse_binop_rhs(&mut stream, primary_expr, None).map(|v| v.kind)
}
}
#[derive(Debug, Clone)]
pub struct PrimaryExpression(Node<Expression>);
#[derive(Debug, Clone, Copy)]
pub enum BinaryOperator {
Lt,
Gt,
}
impl BinaryOperator {
pub fn precedence(&self) -> u32 {
match self {
BinaryOperator::Lt => 100,
BinaryOperator::Gt => 105,
}
}
}
impl Parse for PrimaryExpression {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
let pre = Metadata::pre(&mut stream, "expression")?;
Ok(PrimaryExpression(Node {
kind: Expression::ValueRef(stream.parse()?),
meta: Metadata::produce(&mut stream, pre),
}))
}
}
fn parse_binop_rhs(
stream: &mut TokenStream,
mut lhs: PrimaryExpression,
prev_op: Option<BinaryOperator>,
) -> Result<Node<Expression>, TokenStreamError> {
let meta_pre = Metadata::pre(stream, "binary expression")?;
let precedence = if let Some(op) = prev_op {
op.precedence()
} else {
0
};
while let Ok(curr_operator) =
stream.parse_if::<BinaryOperator, _>(|op| op.precedence() >= precedence)
{
let mut rhs = stream.parse::<PrimaryExpression>()?;
if let Ok(next_op) = stream.parse_peek::<BinaryOperator>() {
if curr_operator.precedence() < next_op.precedence() {
// Operator on the right of rhs has more precedence, turn
// rhs into lhs for new binop
let rhs_expr = stream
.parse_with(|mut st| parse_binop_rhs(&mut st, rhs, Some(curr_operator)))?;
rhs = PrimaryExpression(rhs_expr);
}
}
lhs = PrimaryExpression(Node {
kind: Expression::BinOp(curr_operator, Box::new(lhs.0), Box::new(rhs.0)),
meta: Metadata::produce(stream, meta_pre.clone()),
});
}
Ok(lhs.0)
}
impl Parse for BinaryOperator {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
if let Some(token) = stream.next() {
match token {
Token::Symbol('<') => Ok(BinaryOperator::Lt),
Token::Symbol('>') => Ok(BinaryOperator::Gt),
_ => Err(stream.expected_err("binop")),
}
} else {
Err(stream.expected_err("binop"))
}
} }
} }