Binary wip

This commit is contained in:
2024-11-21 23:07:23 -07:00
parent febb4e9d55
commit 97829005fb
2 changed files with 62 additions and 9 deletions

View File

@@ -4,7 +4,6 @@ use crate::tokenizer::{
token::{Keyword, Symbol, Token, TokenType},
Tokenizer, TokenizerBuffer, TokenizerError,
};
use std::collections::HashSet;
use thiserror::Error;
use tree_node::*;
@@ -20,8 +19,6 @@ pub enum ParseError {
InvalidSyntax { token: Token, reason: String },
#[error("Unexpected EOF")]
UnexpectedEOF,
#[error("An unknown error has occurred")]
UnknownError,
}
macro_rules! self_matches_peek {
@@ -143,7 +140,7 @@ impl Parser {
return Ok(None);
}
let to_return = Some(match current_token.token_type {
let expr = Some(match current_token.token_type {
// match declarations with a `let` keyword
TokenType::Keyword(Keyword::Let) => self.declaration()?,
@@ -169,7 +166,7 @@ impl Parser {
}
// match priority expressions with a left parenthesis
TokenType::Symbol(Symbol::LParen) => Expression::PriorityExpression(self.priority()?),
TokenType::Symbol(Symbol::LParen) => Expression::PriorityExpression(self.priority()?),
_ => {
return Err(ParseError::UnexpectedToken {
@@ -178,7 +175,66 @@ impl Parser {
}
});
Ok(to_return)
let Some(expr) = expr else {
return Ok(None);
};
if self_matches_peek!(self, TokenType::Symbol(s) if s.is_operator()) {
return Ok(Some(self.binary(expr)?));
}
// step 2: check if the next token is an operator and if we should parse a binary expression with the previous expression
Ok(Some(expr))
}
fn binary(&mut self, previous: Expression) -> Result<tree_node::Expression, ParseError> {
let current_token = token_from_option!(self.get_next()?).clone();
// first, make sure the previous expression supports binary expressions
match previous {
Expression::BinaryExpression(_) // 1 + 2 + 3
| Expression::InvocationExpression(_) // add() + 3
| Expression::PriorityExpression(_) // (1 + 2) + 3
| Expression::Literal(_) // 1 + 2
| Expression::Variable(_) // x + 2
| Expression::Negation(_) // -1 + 2
=> {}
_ => {
return Err(ParseError::InvalidSyntax {
token: current_token.clone(),
reason: "Invalid expression for binary operation".to_owned(),
})
}
}
// now check the operator. If we have certain operators, we need to wrap in a priority expression
// Example: subtraction and division. Order of operations is important
let operator = extract_token_data!(
current_token,
TokenType::Symbol(ref s),
s.clone()
);
let expr = match operator {
Symbol::Plus => {
let right = self.expression()?.ok_or(ParseError::UnexpectedEOF)?;
Expression::BinaryExpression(BinaryExpression::Add(Box::new(previous), Box::new(right)))
},
Symbol::Minus => {
let right = self.expression()?.ok_or(ParseError::UnexpectedEOF)?;
Expression::PriorityExpression(Box::new(Expression::BinaryExpression(BinaryExpression::Subtract(Box::new(previous), Box::new(right)))))
},
_ => {
return Err(ParseError::InvalidSyntax {
token: current_token.clone(),
reason: "Invalid operator for binary operation".to_owned(),
})
}
};
todo!()
}
fn priority(&mut self) -> Result<Box<Expression>, ParseError> {
@@ -504,7 +560,6 @@ mod tests {
assert_eq!("(let x = (4))", expression.to_string());
Ok(())
}
}

View File

@@ -1,5 +1,3 @@
use std::collections::HashSet;
use crate::tokenizer::token::Number;
#[derive(Debug, Eq, PartialEq)]