mathengine_parser/
parser.rs1use crate::ast::Expression;
2use crate::error::ParseError;
3use mathengine_lexer::{Operation, Token};
4
5pub struct Parser {
6 tokens: Vec<Token>,
7 pos: usize,
8}
9
10impl Parser {
11 pub fn new(tokens: Vec<Token>) -> Self {
12 Self { tokens, pos: 0 }
13 }
14
15 pub fn parse(&mut self) -> Result<Expression, ParseError> {
17 if self.tokens.is_empty() {
18 return Err(ParseError::EmptyTokenStream);
19 }
20
21 let expr = self.parse_expression(0)?;
22 if self.pos < self.tokens.len() {
23 return Err(ParseError::UnexpectedToken {
24 expected: "end of input".to_string(),
25 found: self.tokens[self.pos].clone(),
26 position: self.pos,
27 });
28 }
29 Ok(expr)
30 }
31
32 fn parse_expression(&mut self, min_precedence: u8) -> Result<Expression, ParseError> {
35 let mut left = self.parse_primary()?;
36
37 while let Some(token) = self.peek() {
38 match token {
39 Token::Operation(op) => {
40 let precedence = self.get_precedence(op);
41 if precedence < min_precedence {
42 break;
43 }
44
45 let op = match self.advance() {
46 Some(Token::Operation(o)) => o.clone(),
47 _ => unreachable!(),
48 };
49
50 let right_precedence = if self.is_right_associative(&op) {
51 precedence
52 } else {
53 precedence + 1
54 };
55
56 let right = self.parse_expression(right_precedence)?;
57 left = Expression::Binary {
58 op,
59 left: Box::new(left),
60 right: Box::new(right),
61 };
62 }
63 _ => break,
64 }
65 }
66
67 Ok(left)
68 }
69
70 fn parse_primary(&mut self) -> Result<Expression, ParseError> {
72 let start_pos = self.pos;
73 match self.advance() {
74 Some(Token::Number(n)) => Ok(Expression::Number(*n)),
75 Some(Token::UnitValue { value, unit }) => Ok(Expression::UnitValue {
76 value: *value,
77 unit: unit.clone(),
78 }),
79 Some(Token::Unit(unit)) => Ok(Expression::Unit(unit.clone())),
80 Some(Token::Lparen) => {
81 let expr = self.parse_expression(0)?;
82 match self.advance() {
83 Some(Token::Rparen) => Ok(expr),
84 Some(other) => Err(ParseError::UnexpectedToken {
85 expected: "')'".to_string(),
86 found: other.clone(),
87 position: self.pos - 1,
88 }),
89 None => Err(ParseError::UnexpectedEndOfInput {
90 expected: "')'".to_string(),
91 }),
92 }
93 }
94 Some(Token::Operation(Operation::Subtract)) => {
95 let operand = self.parse_primary()?;
96 Ok(Expression::Unary {
97 op: Operation::Subtract,
98 operand: Box::new(operand),
99 })
100 }
101 Some(token) => Err(ParseError::UnexpectedToken {
102 expected: "number, unit value, '(', or unary operator".to_string(),
103 found: token.clone(),
104 position: start_pos,
105 }),
106 None => Err(ParseError::UnexpectedEndOfInput {
107 expected: "expression".to_string(),
108 }),
109 }
110 }
111
112 fn peek(&self) -> Option<&Token> {
114 self.tokens.get(self.pos)
115 }
116
117 fn advance(&mut self) -> Option<&Token> {
119 if self.pos < self.tokens.len() {
120 let token = &self.tokens[self.pos];
121 self.pos += 1;
122 Some(token)
123 } else {
124 None
125 }
126 }
127
128 fn get_precedence(&self, op: &Operation) -> u8 {
130 match op {
131 Operation::Add | Operation::Subtract => 1,
132 Operation::Multiply | Operation::Divide => 2,
133 Operation::Power => 3,
134 Operation::Convert => 5,
135 }
136 }
137
138 fn is_right_associative(&self, op: &Operation) -> bool {
140 match op {
141 Operation::Power => true, _ => false,
143 }
144 }
145}
146