fixed implicit multiplication parsing going to `parse_primary` instead of `parse_additive`
169 lines
5.2 KiB
Rust
169 lines
5.2 KiB
Rust
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_exponential();
|
|
|
|
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 => {
|
|
let right = self.parse_group();
|
|
left =
|
|
Expression::Operation(Operator::Multiply, Box::new(left), Box::new(right));
|
|
}
|
|
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_group();
|
|
|
|
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::Power, 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;
|
|
let expression = self.parse_additive();
|
|
self.position += 1;
|
|
expression
|
|
}
|
|
_ => 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
|
|
}
|
|
}
|