From 9c56d807fe212250caa23eec0d753c2435735249 Mon Sep 17 00:00:00 2001 From: Sofia Date: Sat, 14 Mar 2026 16:09:58 +0200 Subject: [PATCH] Add parse for binary operators --- examples/test.lua | 2 +- src/ast.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/examples/test.lua b/examples/test.lua index fb2f696..3cab439 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -1,6 +1,6 @@ function max (a, b) local m = a - if a then + if b > a then m = b end return m diff --git a/src/ast.rs b/src/ast.rs index f5a3120..decb2ae 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -250,10 +250,91 @@ pub enum DefinitionKind { #[derive(Debug, Clone)] pub enum Expression { ValueRef(String), + BinOp(BinaryOperator, Box>, Box>), } impl Parse for Expression { fn parse(mut stream: TokenStream) -> Result { - Ok(Expression::ValueRef(stream.parse()?)) + let primary_expr = stream.parse::()?; + parse_binop_rhs(&mut stream, primary_expr, None).map(|v| v.kind) + } +} + +#[derive(Debug, Clone)] +pub struct PrimaryExpression(Node); + +#[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 { + 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, +) -> Result, 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::(|op| op.precedence() >= precedence) + { + let mut rhs = stream.parse::()?; + + if let Ok(next_op) = stream.parse_peek::() { + 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 { + 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")) + } } }