feat(parser): add parser

added a basic ast parser that is likely riddled with bugs
This commit is contained in:
ozzy committed 2026-09-25 20:29:43 -05:00
1 parent 26e85652af
commit 66da876e2a
4 files changed
+179 -4

No files matched your search

+3 -1
View File
@@ -3,13 +3,14 @@ use std::str::FromStr;
use crate::math::types::Operator; use crate::math::types::Operator;
use rust_decimal::Decimal; use rust_decimal::Decimal;
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Token { pub enum Token {
Number(Decimal), Number(Decimal),
Identifier(String), Identifier(String),
Operator(Operator), Operator(Operator),
OpenParen, OpenParen,
CloseParen, CloseParen,
Comma,
Eof, Eof,
} }
@@ -73,6 +74,7 @@ impl<'a> Lexer<'a> {
match self.chars.next() { match self.chars.next() {
Some('(') => Token::OpenParen, Some('(') => Token::OpenParen,
Some(')') => Token::CloseParen, Some(')') => Token::CloseParen,
Some(',') => Token::Comma,
Some('+') => Token::Operator(Operator::Add), Some('+') => Token::Operator(Operator::Add),
Some('-') => Token::Operator(Operator::Subtract), Some('-') => Token::Operator(Operator::Subtract),
Some('*') => Token::Operator(Operator::Multiply), Some('*') => Token::Operator(Operator::Multiply),
+6 -2
View File
@@ -1,8 +1,12 @@
use crate::math::types::Expression;
mod lexer; mod lexer;
mod parser;
pub mod types; pub mod types;
pub fn parse(source: &str) -> Vec<lexer::Token> { pub fn parse(source: &str) -> Expression {
let lexer = lexer::from(source); let lexer = lexer::from(source);
lexer.collect() let mut parser = parser::from(lexer.collect());
parser.parse()
} }
+169
View File
@@ -0,0 +1,169 @@
use crate::math::{
lexer::Token,
types::{Expression, Operator},
};
pub fn from(tokens: Vec<Token>) -> Parser {
Parser::new(tokens)
}
pub struct Parser {
tokens: Vec<Token>,
position: usize,
}
impl Parser {
pub fn new(tokens: Vec<Token>) -> Self {
Self {
tokens,
position: 0,
}
}
pub fn parse(&mut self) -> Expression {
self.parse_additive()
}
fn parse_additive(&mut self) -> Expression {
let mut left = self.parse_multiplicative();
while let Some(token) = self.tokens.get(self.position) {
match token {
Token::Operator(Operator::Add) => {
self.position += 1;
let right = self.parse_multiplicative();
left = Expression::Operation(Operator::Add, Box::new(left), Box::new(right));
}
Token::Operator(Operator::Subtract) => {
self.position += 1;
let right = self.parse_multiplicative();
left =
Expression::Operation(Operator::Subtract, Box::new(left), Box::new(right));
}
_ => break,
}
}
left
}
fn parse_multiplicative(&mut self) -> Expression {
let mut left = self.parse_primary();
while let Some(token) = self.tokens.get(self.position) {
match token {
Token::Operator(Operator::Multiply) => {
self.position += 1;
let right = self.parse_exponential();
left =
Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right));
}
Token::Operator(Operator::Divide) => {
self.position += 1;
let right = self.parse_exponential();
left = Expression::Fraction(Box::new(left), Box::new(right));
}
Token::Operator(Operator::Modulo) => {
self.position += 1;
let right = self.parse_exponential();
left = Expression::Operation(Operator::Modulo, Box::new(left), Box::new(right));
}
Token::OpenParen => {
self.position += 1;
let right = self.parse_group();
left =
Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right));
self.position += 1;
}
Token::Identifier(_) => {
let right = self.parse_primary();
left =
Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right));
}
_ => break,
}
}
left
}
fn parse_exponential(&mut self) -> Expression {
let mut left = self.parse_primary();
while let Some(token) = self.tokens.get(self.position) {
match token {
Token::Operator(Operator::Power) => {
self.position += 1;
let right = self.parse_group();
left =
Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right));
}
_ => break,
}
}
left
}
fn parse_group(&mut self) -> Expression {
match self.tokens.get(self.position).expect("expected token!") {
Token::OpenParen => {
self.position += 1;
self.parse_additive()
}
_ => self.parse_primary(),
}
}
fn parse_primary(&mut self) -> Expression {
let token = self
.tokens
.get(self.position)
.cloned()
.expect("expected token!");
match token {
Token::Number(num) => {
self.position += 1;
Expression::Number(num)
}
Token::Identifier(identifier) => {
let is_function =
matches!(self.tokens.get(self.position + 1), Some(Token::OpenParen));
if is_function {
self.position += 2;
let params = self.parse_function_params();
Expression::Function(identifier, params)
} else {
self.position += 1;
Expression::Variable(identifier)
}
}
_ => {
panic!("unexpected token! {:?}", token);
}
}
}
fn parse_function_params(&mut self) -> Vec<Expression> {
let mut params: Vec<Expression> = Vec::new();
while let Some(token) = self.tokens.get(self.position) {
match token {
Token::Comma => {
self.position += 1;
}
Token::CloseParen => {
self.position += 1;
break;
}
_ => {
let expression = self.parse_additive();
params.push(expression);
}
}
}
params
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ pub enum Expression {
Function(String, Vec<Expression>), Function(String, Vec<Expression>),
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Operator { pub enum Operator {
Add, Add,
Subtract, Subtract,