parser done
This commit is contained in:
		
							parent
							
								
									8705272a77
								
							
						
					
					
						commit
						f6dd337ba1
					
				
							
								
								
									
										61
									
								
								src/ast.rs
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								src/ast.rs
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ pub struct Node<T> { | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum Expr { | ||||
|     Error(String), | ||||
|     Unit, | ||||
|     Id(String), | ||||
|     Int(i64), | ||||
| @ -15,9 +16,15 @@ pub enum Expr { | ||||
|     String(String), | ||||
|     Bool(bool), | ||||
|     Array(Vec<Node<Expr>>), | ||||
|     Object(Vec<ObjectEntry>), | ||||
|     Object(Vec<Node<ObjectEntry>>), | ||||
|     Tuple(Vec<Node<Expr>>), | ||||
| 
 | ||||
|     If { | ||||
|         condition: Box<Node<Expr>>, | ||||
|         truthy: Box<Node<Expr>>, | ||||
|         falsy: Option<Box<Node<Expr>>>, | ||||
|     }, | ||||
| 
 | ||||
|     Member { | ||||
|         subject: Box<Node<Expr>>, | ||||
|         value: String, | ||||
| @ -39,11 +46,44 @@ pub enum Expr { | ||||
|         left: Box<Node<Expr>>, | ||||
|         right: Box<Node<Expr>>, | ||||
|     }, | ||||
| 
 | ||||
|     Assign { | ||||
|         assign_type: AssignType, | ||||
|         subject: Box<Node<Expr>>, | ||||
|         value: Box<Node<Expr>>, | ||||
|     }, | ||||
|     Let { | ||||
|         subject: Node<Parameter>, | ||||
|         value: Option<Box<Node<Expr>>>, | ||||
|     }, | ||||
|     Continue, | ||||
|     Break, | ||||
|     While { | ||||
|         condition: Box<Node<Expr>>, | ||||
|         body: Box<Node<Expr>>, | ||||
|     }, | ||||
|     Return(Option<Box<Node<Expr>>>), | ||||
|     Function { | ||||
|         name: String, | ||||
|         parameters: Vec<Node<Parameter>>, | ||||
|         body: Box<Node<Expr>>, | ||||
|     }, | ||||
|     Block { | ||||
|         statements: Vec<Node<Expr>>, | ||||
|         value: Option<Box<Node<Expr>>>, | ||||
|     }, | ||||
| 
 | ||||
|     Spread(Box<Node<Expr>>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum ObjectEntry { | ||||
|     Pair(Box<Node<Expr>>, Box<Expr>), | ||||
|     Error(String), | ||||
|     Pair { | ||||
|         key: Box<Node<Expr>>, | ||||
|         value: Box<Node<Expr>>, | ||||
|     }, | ||||
|     Spread(Box<Node<Expr>>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| @ -73,3 +113,20 @@ pub enum BinaryType { | ||||
|     And, | ||||
|     Or, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum AssignType { | ||||
|     Assign, | ||||
|     Add, | ||||
|     Subtract, | ||||
|     Multiply, | ||||
|     Divide, | ||||
|     Modulo, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum Parameter { | ||||
|     Error(String), | ||||
|     Id { name: String, mutable: bool }, | ||||
|     Spread(Box<Node<Parameter>>), | ||||
| } | ||||
|  | ||||
							
								
								
									
										25
									
								
								src/lexer.rs
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/lexer.rs
									
									
									
									
									
								
							| @ -46,9 +46,7 @@ impl<'a> Lexer<'a> { | ||||
|                 '=', | ||||
|                 TokenType::PercentEqual, | ||||
|             )), | ||||
|             '=' => { | ||||
|                 Some(self.single_or_double_char_token(TokenType::Equal, '=', TokenType::EqualEqual)) | ||||
|             } | ||||
|             '=' => Some(self.equal_token()), | ||||
|             '!' => Some(self.single_or_double_char_token( | ||||
|                 TokenType::Exclamation, | ||||
|                 '=', | ||||
| @ -104,7 +102,7 @@ impl<'a> Lexer<'a> { | ||||
|             self.step(); | ||||
|         } | ||||
|         if self.done() || self.current() != '"' { | ||||
|             self.step_and_token(TokenType::MalformedString, start) | ||||
|             self.token(TokenType::MalformedString, start) | ||||
|         } else { | ||||
|             self.step_and_token(TokenType::String, start) | ||||
|         } | ||||
| @ -213,6 +211,18 @@ impl<'a> Lexer<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn equal_token(&mut self) -> Token { | ||||
|         let start = self.pos(); | ||||
|         self.step(); | ||||
|         if !self.done() && self.current() == '=' { | ||||
|             self.step_and_token(TokenType::EqualEqual, start) | ||||
|         } else if !self.done() && self.current() == '>' { | ||||
|             self.step_and_token(TokenType::EqualLessThan, start) | ||||
|         } else { | ||||
|             self.step_and_token(TokenType::Equal, start) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn dot_token(&mut self) -> Token { | ||||
|         let start = self.pos(); | ||||
|         self.step(); | ||||
| @ -222,6 +232,13 @@ impl<'a> Lexer<'a> { | ||||
|                 self.step(); | ||||
|             } | ||||
|             self.token(TokenType::Decimal, start) | ||||
|         } else if !self.done() && self.current() == '.' { | ||||
|             self.step(); | ||||
|             if !self.done() && self.current() == '.' { | ||||
|                 self.step_and_token(TokenType::DotDotDot, start) | ||||
|             } else { | ||||
|                 self.token(TokenType::DotDot, start) | ||||
|             } | ||||
|         } else { | ||||
|             self.token(TokenType::Dot, start) | ||||
|         } | ||||
|  | ||||
							
								
								
									
										30
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -9,15 +9,33 @@ use crate::lexer::Lexer; | ||||
| use crate::parser::Parser; | ||||
| 
 | ||||
| fn main() { | ||||
|     // println!("tokens = [");
 | ||||
|     // let text = "** 3.14 \"foo\" false true ( ) + += /* 1 /* 2 */ 3 */  // 4 \n 5";
 | ||||
|     // let lexer = Lexer::new(text);
 | ||||
|     // lexer.for_each(|token| {
 | ||||
|     //     println!(
 | ||||
|     //         "    {:?} = `{}`,",
 | ||||
|     //         token.token_type,
 | ||||
|     //         &text[token.pos.index..token.pos.index + token.length]
 | ||||
|     //     );
 | ||||
|     // });
 | ||||
|     // println!("]");
 | ||||
| 
 | ||||
|     let text2 = "[1, 2, ...a]"; | ||||
|     let lexer2 = Lexer::new(text2); | ||||
|     println!("tokens = ["); | ||||
|     let text = "** 3.14 \"foo\" false true ( ) + += /* 1 /* 2 */ 3 */  // 4 \n 5"; | ||||
|     let lexer = Lexer::new(text); | ||||
|     lexer.for_each(|token| { | ||||
|         println!("    {:?},", token); | ||||
|     lexer2.for_each(|token| { | ||||
|         println!( | ||||
|             "    ({:?}, `{}`, [{}], {}, {}:{}),", | ||||
|             token.token_type, | ||||
|             &text2[token.pos.index..token.pos.index + token.length], | ||||
|             token.pos.index, | ||||
|             token.length, | ||||
|             token.pos.line, | ||||
|             token.pos.col, | ||||
|         ); | ||||
|     }); | ||||
|     println!("]"); | ||||
| 
 | ||||
|     let text2 = "1 + 2 * 3"; | ||||
|     let mut parser = Parser::new(text2, Lexer::new(text2)); | ||||
|     let expr = parser.parse_expr(); | ||||
|     println!("ast = {:#?}", expr); | ||||
|  | ||||
							
								
								
									
										558
									
								
								src/parser.rs
									
									
									
									
									
								
							
							
						
						
									
										558
									
								
								src/parser.rs
									
									
									
									
									
								
							| @ -1,11 +1,8 @@ | ||||
| use crate::ast::{BinaryType, Expr, Node, UnaryType}; | ||||
| use crate::tokens::{Position, PositionKnowing, Token, TokenType}; | ||||
| use std::iter::Peekable; | ||||
| use std::str::Chars; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ParserError { | ||||
|     pos: Position, | ||||
|     message: String, | ||||
| } | ||||
| use crate::ast::{AssignType, BinaryType, Expr, Node, ObjectEntry, Parameter, UnaryType}; | ||||
| use crate::tokens::{PositionKnowing, Token, TokenType}; | ||||
| 
 | ||||
| pub struct Parser<'a, Tokens> | ||||
| where | ||||
| @ -28,16 +25,239 @@ where | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn parse_expr(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|     pub fn parse_top_level_statements(&mut self) -> Vec<Node<Expr>> { | ||||
|         let mut statements = Vec::<Node<Expr>>::new(); | ||||
|         while !self.done() { | ||||
|             statements.push(self.parse_statement()); | ||||
|         } | ||||
|         statements | ||||
|     } | ||||
| 
 | ||||
|     fn parse_block(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let mut statements = Vec::<Node<Expr>>::new(); | ||||
|         let mut last = None; | ||||
|         while !self.done() && !self.current_is(TokenType::RBrace) { | ||||
|             if let Some(statement) = last { | ||||
|                 statements.push(statement); | ||||
|             } | ||||
|             last = Some(self.parse_statement()); | ||||
|         } | ||||
|         if self.done() || !self.current_is(TokenType::RBrace) { | ||||
|             statements.push(self.error("expected '}'")); | ||||
|         } | ||||
|         self.node(Expr::Block { | ||||
|             statements, | ||||
|             value: last.map(|v| Box::new(v)), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn parse_statement(&mut self) -> Node<Expr> { | ||||
|         if self.done() { | ||||
|             return self.error("expected statement"); | ||||
|         } | ||||
|         match self.current().token_type { | ||||
|             TokenType::Fn => self.parse_function(), | ||||
|             TokenType::Return => self.parse_function(), | ||||
|             TokenType::While => self.parse_function(), | ||||
|             TokenType::Break => self.parse_function(), | ||||
|             TokenType::Continue => self.parse_function(), | ||||
|             _ => self.parse_assign(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_function(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         if self.done() || !self.current_is(TokenType::Id) { | ||||
|             return self.error("expected Id"); | ||||
|         } | ||||
|         let name = self.token_string(self.current()); | ||||
|         self.step(); | ||||
|         if self.done() || !self.current_is(TokenType::LParen) { | ||||
|             return self.error("expected '('"); | ||||
|         } | ||||
|         self.step(); | ||||
|         let mut parameters = Vec::<Node<Parameter>>::new(); | ||||
|         if !self.done() && !self.current_is(TokenType::RParen) { | ||||
|             if self.current_is(TokenType::DotDotDot) { | ||||
|                 self.step(); | ||||
|                 let inner = self.parse_parameter(); | ||||
|                 parameters.push(self.node(Parameter::Spread(Box::new(inner)))); | ||||
|             } else { | ||||
|                 parameters.push(self.parse_parameter()); | ||||
|                 while !self.done() && self.current_is(TokenType::Comma) { | ||||
|                     self.step(); | ||||
|                     if self.current_is(TokenType::DotDotDot) { | ||||
|                         self.step(); | ||||
|                         let inner = self.parse_parameter(); | ||||
|                         parameters.push(self.node(Parameter::Spread(Box::new(inner)))); | ||||
|                         break; | ||||
|                     } | ||||
|                     if self.done() || self.current_is(TokenType::RParen) { | ||||
|                         break; | ||||
|                     } | ||||
|                     parameters.push(self.parse_parameter()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if self.done() || !self.current_is(TokenType::RParen) { | ||||
|             return self.error("expected ')'"); | ||||
|         } | ||||
|         self.step(); | ||||
|         if self.done() || !self.current_is(TokenType::LBrace) { | ||||
|             return self.error("expected '{'"); | ||||
|         } | ||||
|         let body = self.parse_block(); | ||||
|         self.node(Expr::Function { | ||||
|             name, | ||||
|             parameters, | ||||
|             body: Box::new(body), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_parameter(&mut self) -> Node<Parameter> { | ||||
|         let mutable = if !self.done() && self.current_is(TokenType::Mut) { | ||||
|             self.step(); | ||||
|             true | ||||
|         } else { | ||||
|             false | ||||
|         }; | ||||
|         if self.done() || !self.current_is(TokenType::Id) { | ||||
|             return self.node(Parameter::Error("expected Id".to_string())); | ||||
|         } | ||||
|         let name = self.token_string(self.current()); | ||||
|         self.step_and_node(Parameter::Id { mutable, name }) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_return(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         if !self.done() && !self.current_is(TokenType::Semicolon) { | ||||
|             let value = self.parse_expr(); | ||||
|             self.node(Expr::Return(Some(Box::new(value)))) | ||||
|         } else { | ||||
|             self.node(Expr::Return(None)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_while(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let condition = self.parse_expr(); | ||||
|         if self.done() || !self.current_is(TokenType::LBrace) { | ||||
|             return self.error("expected '{'"); | ||||
|         } | ||||
|         let body = self.parse_block(); | ||||
|         self.node(Expr::While { | ||||
|             condition: Box::new(condition), | ||||
|             body: Box::new(body), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_break(&mut self) -> Node<Expr> { | ||||
|         self.step_and_node(Expr::Continue) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_continue(&mut self) -> Node<Expr> { | ||||
|         self.step_and_node(Expr::Continue) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_let(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let subject = self.parse_parameter(); | ||||
|         if !self.done() && self.current_is(TokenType::Equal) { | ||||
|             self.step(); | ||||
|             let value = self.parse_expr(); | ||||
|             self.node(Expr::Let { | ||||
|                 subject, | ||||
|                 value: Some(Box::new(value)), | ||||
|             }) | ||||
|         } else { | ||||
|             self.node(Expr::Let { | ||||
|                 subject, | ||||
|                 value: None, | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_assign(&mut self) -> Node<Expr> { | ||||
|         let subject = self.parse_expr(); | ||||
|         if self.done() { | ||||
|             return subject; | ||||
|         } | ||||
|         match self.current().token_type { | ||||
|             TokenType::Equal => { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(Expr::Assign { | ||||
|                     assign_type: AssignType::Assign, | ||||
|                     subject: Box::new(subject), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             TokenType::PlusEqual => { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(Expr::Assign { | ||||
|                     assign_type: AssignType::Add, | ||||
|                     subject: Box::new(subject), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             TokenType::MinusEqual => { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(Expr::Assign { | ||||
|                     assign_type: AssignType::Subtract, | ||||
|                     subject: Box::new(subject), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             TokenType::AsteriskEqual => { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(Expr::Assign { | ||||
|                     assign_type: AssignType::Multiply, | ||||
|                     subject: Box::new(subject), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             TokenType::SlashEqual => { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(Expr::Assign { | ||||
|                     assign_type: AssignType::Divide, | ||||
|                     subject: Box::new(subject), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             TokenType::PercentEqual => { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(Expr::Assign { | ||||
|                     assign_type: AssignType::Modulo, | ||||
|                     subject: Box::new(subject), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             _ => subject, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_spread(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let inner = self.parse_expr(); | ||||
|         self.node(Expr::Spread(Box::new(inner))) | ||||
|     } | ||||
| 
 | ||||
|     pub fn parse_expr(&mut self) -> Node<Expr> { | ||||
|         self.parse_prec_or() | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_or(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut left = self.parse_prec_and()?; | ||||
|     fn parse_prec_or(&mut self) -> Node<Expr> { | ||||
|         let mut left = self.parse_prec_and(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::Or) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_and()?; | ||||
|                 let right = self.parse_prec_and(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Or, | ||||
|                     left: Box::new(left), | ||||
| @ -47,15 +267,15 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(left) | ||||
|         left | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_and(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut left = self.parse_prec_equal_inequal()?; | ||||
|     fn parse_prec_and(&mut self) -> Node<Expr> { | ||||
|         let mut left = self.parse_prec_equal_inequal(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::And) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_equal_inequal()?; | ||||
|                 let right = self.parse_prec_equal_inequal(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::And, | ||||
|                     left: Box::new(left), | ||||
| @ -65,15 +285,15 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(left) | ||||
|         left | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_equal_inequal(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut left = self.parse_prec_lt_lte_gt_gte_in()?; | ||||
|     fn parse_prec_equal_inequal(&mut self) -> Node<Expr> { | ||||
|         let mut left = self.parse_prec_lt_lte_gt_gte_in(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::EqualEqual) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_lt_lte_gt_gte_in()?; | ||||
|                 let right = self.parse_prec_lt_lte_gt_gte_in(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Equal, | ||||
|                     left: Box::new(left), | ||||
| @ -81,7 +301,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::ExclamationEqual) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_lt_lte_gt_gte_in()?; | ||||
|                 let right = self.parse_prec_lt_lte_gt_gte_in(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Inequal, | ||||
|                     left: Box::new(left), | ||||
| @ -91,15 +311,15 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(left) | ||||
|         left | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut left = self.parse_prec_add_subtract()?; | ||||
|     fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Node<Expr> { | ||||
|         let mut left = self.parse_prec_add_subtract(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::LessThan) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_add_subtract()?; | ||||
|                 let right = self.parse_prec_add_subtract(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::LT, | ||||
|                     left: Box::new(left), | ||||
| @ -107,7 +327,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::GreaterThan) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_add_subtract()?; | ||||
|                 let right = self.parse_prec_add_subtract(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::GT, | ||||
|                     left: Box::new(left), | ||||
| @ -115,7 +335,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::LessThanEqual) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_add_subtract()?; | ||||
|                 let right = self.parse_prec_add_subtract(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::LTE, | ||||
|                     left: Box::new(left), | ||||
| @ -123,7 +343,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::GreaterThanEqual) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_add_subtract()?; | ||||
|                 let right = self.parse_prec_add_subtract(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::GTE, | ||||
|                     left: Box::new(left), | ||||
| @ -131,7 +351,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::In) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_add_subtract()?; | ||||
|                 let right = self.parse_prec_add_subtract(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::In, | ||||
|                     left: Box::new(left), | ||||
| @ -141,15 +361,15 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(left) | ||||
|         left | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_add_subtract(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut left = self.parse_prec_multiply_divide_modulo()?; | ||||
|     fn parse_prec_add_subtract(&mut self) -> Node<Expr> { | ||||
|         let mut left = self.parse_prec_multiply_divide_modulo(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::Plus) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_multiply_divide_modulo()?; | ||||
|                 let right = self.parse_prec_multiply_divide_modulo(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Add, | ||||
|                     left: Box::new(left), | ||||
| @ -157,7 +377,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::Minus) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_multiply_divide_modulo()?; | ||||
|                 let right = self.parse_prec_multiply_divide_modulo(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Subtract, | ||||
|                     left: Box::new(left), | ||||
| @ -167,15 +387,15 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(left) | ||||
|         left | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_multiply_divide_modulo(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut left = self.parse_prec_unary()?; | ||||
|     fn parse_prec_multiply_divide_modulo(&mut self) -> Node<Expr> { | ||||
|         let mut left = self.parse_prec_unary(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::Asterisk) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_unary()?; | ||||
|                 let right = self.parse_prec_unary(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Multiply, | ||||
|                     left: Box::new(left), | ||||
| @ -183,7 +403,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::Slash) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_unary()?; | ||||
|                 let right = self.parse_prec_unary(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Divide, | ||||
|                     left: Box::new(left), | ||||
| @ -191,7 +411,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::Percent) { | ||||
|                 self.step(); | ||||
|                 let right = self.parse_prec_unary()?; | ||||
|                 let right = self.parse_prec_unary(); | ||||
|                 left = self.node(Expr::Binary { | ||||
|                     binary_type: BinaryType::Modulo, | ||||
|                     left: Box::new(left), | ||||
| @ -201,21 +421,21 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(left) | ||||
|         left | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_unary(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|     fn parse_prec_unary(&mut self) -> Node<Expr> { | ||||
|         if !self.done() && self.current_is(TokenType::Not) { | ||||
|             self.step(); | ||||
|             let subject = Box::new(self.parse_prec_unary()?); | ||||
|             self.ok_node(Expr::Unary { | ||||
|             let subject = Box::new(self.parse_prec_unary()); | ||||
|             self.node(Expr::Unary { | ||||
|                 unary_type: UnaryType::Not, | ||||
|                 subject, | ||||
|             }) | ||||
|         } else if !self.done() && self.current_is(TokenType::Minus) { | ||||
|             self.step(); | ||||
|             let subject = Box::new(self.parse_prec_unary()?); | ||||
|             self.ok_node(Expr::Unary { | ||||
|             let subject = Box::new(self.parse_prec_unary()); | ||||
|             self.node(Expr::Unary { | ||||
|                 unary_type: UnaryType::Negate, | ||||
|                 subject, | ||||
|             }) | ||||
| @ -223,22 +443,22 @@ where | ||||
|             self.step(); | ||||
|             if !self.done() && self.current_is(TokenType::Mut) { | ||||
|                 self.step(); | ||||
|                 let subject = Box::new(self.parse_prec_unary()?); | ||||
|                 self.ok_node(Expr::Unary { | ||||
|                 let subject = Box::new(self.parse_prec_unary()); | ||||
|                 self.node(Expr::Unary { | ||||
|                     unary_type: UnaryType::ReferenceMut, | ||||
|                     subject, | ||||
|                 }) | ||||
|             } else { | ||||
|                 let subject = Box::new(self.parse_prec_unary()?); | ||||
|                 self.ok_node(Expr::Unary { | ||||
|                 let subject = Box::new(self.parse_prec_unary()); | ||||
|                 self.node(Expr::Unary { | ||||
|                     unary_type: UnaryType::Reference, | ||||
|                     subject, | ||||
|                 }) | ||||
|             } | ||||
|         } else if !self.done() && self.current_is(TokenType::Asterisk) { | ||||
|             self.step(); | ||||
|             let subject = Box::new(self.parse_prec_unary()?); | ||||
|             self.ok_node(Expr::Unary { | ||||
|             let subject = Box::new(self.parse_prec_unary()); | ||||
|             self.node(Expr::Unary { | ||||
|                 unary_type: UnaryType::Dereference, | ||||
|                 subject, | ||||
|             }) | ||||
| @ -247,22 +467,22 @@ where | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_exponentiate(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let left = self.parse_prec_member_index_call()?; | ||||
|     fn parse_prec_exponentiate(&mut self) -> Node<Expr> { | ||||
|         let left = self.parse_prec_member_index_call(); | ||||
|         if !self.done() && self.current_is(TokenType::AsteriskEqual) { | ||||
|             let right = self.parse_prec_exponentiate()?; | ||||
|             self.step_and_ok_node(Expr::Binary { | ||||
|             let right = self.parse_prec_exponentiate(); | ||||
|             self.step_and_node(Expr::Binary { | ||||
|                 binary_type: BinaryType::Exponentiate, | ||||
|                 left: Box::new(left), | ||||
|                 right: Box::new(right), | ||||
|             }) | ||||
|         } else { | ||||
|             Ok(left) | ||||
|             left | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_prec_member_index_call(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         let mut subject = self.parse_operand()?; | ||||
|     fn parse_prec_member_index_call(&mut self) -> Node<Expr> { | ||||
|         let mut subject = self.parse_operand(); | ||||
|         while !self.done() { | ||||
|             if self.current_is(TokenType::Dot) { | ||||
|                 self.step(); | ||||
| @ -277,7 +497,7 @@ where | ||||
|                 }); | ||||
|             } else if self.current_is(TokenType::LBracket) { | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr()?; | ||||
|                 let value = self.parse_expr(); | ||||
|                 if self.done() || !self.current_is(TokenType::RBracket) { | ||||
|                     return self.error("expected ']'"); | ||||
|                 } | ||||
| @ -289,13 +509,13 @@ where | ||||
|                 self.step(); | ||||
|                 let mut arguments = Vec::<Node<Expr>>::new(); | ||||
|                 if !self.done() && !self.current_is(TokenType::RParen) { | ||||
|                     arguments.push(self.parse_expr()?); | ||||
|                     arguments.push(self.parse_expr()); | ||||
|                     while !self.done() && self.current_is(TokenType::Comma) { | ||||
|                         self.step(); | ||||
|                         if self.done() || self.current_is(TokenType::RParen) { | ||||
|                             self.step(); | ||||
|                         } | ||||
|                         arguments.push(self.parse_expr()?); | ||||
|                         arguments.push(self.parse_expr()); | ||||
|                     } | ||||
|                 } | ||||
|                 if self.done() || !self.current_is(TokenType::RParen) { | ||||
| @ -310,82 +530,172 @@ where | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         Ok(subject) | ||||
|         subject | ||||
|     } | ||||
| 
 | ||||
|     fn parse_operand(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|     fn parse_operand(&mut self) -> Node<Expr> { | ||||
|         if self.done() { | ||||
|             return self.error("expected value, got eof"); | ||||
|         } | ||||
|         match self.current().token_type { | ||||
|             TokenType::Id => self.step_and_ok_node(Expr::Id(self.token_string(self.current()))), | ||||
|         match &self.current().token_type { | ||||
|             TokenType::Id => self.step_and_node(Expr::Id(self.token_string(self.current()))), | ||||
|             TokenType::Int => { | ||||
|                 let mut value_string = self.token_string(self.current()); | ||||
|                 self.step(); | ||||
|                 if !self.done() && self.current_is(TokenType::Decimal) { | ||||
|                     value_string.push_str(&self.token_string(self.current())); | ||||
|                     self.step_and_ok_node(Expr::Float( | ||||
|                         value_string.parse::<f64>().expect("valid f64"), | ||||
|                     )) | ||||
|                     self.step_and_node(Expr::Float(value_string.parse::<f64>().expect("valid f64"))) | ||||
|                 } else { | ||||
|                     self.ok_node(Expr::Int((value_string).parse::<i64>().expect("valid i64"))) | ||||
|                     self.node(Expr::Int((value_string).parse::<i64>().expect("valid i64"))) | ||||
|                 } | ||||
|             } | ||||
|             TokenType::Decimal => self.step_and_ok_node(Expr::Float( | ||||
|             TokenType::Decimal => self.step_and_node(Expr::Float( | ||||
|                 self.token_string(self.current()) | ||||
|                     .parse::<f64>() | ||||
|                     .expect("valid f64"), | ||||
|             )), | ||||
|             TokenType::False => self.step_and_ok_node(Expr::Bool(false)), | ||||
|             TokenType::True => self.step_and_ok_node(Expr::Bool(true)), | ||||
|             TokenType::String => self.parse_string(), | ||||
|             TokenType::False => self.step_and_node(Expr::Bool(false)), | ||||
|             TokenType::True => self.step_and_node(Expr::Bool(true)), | ||||
|             TokenType::LParen => self.parse_unit_group_or_tuple(), | ||||
|             TokenType::LBrace => self.parse_object(), | ||||
|             TokenType::LBrace => self.parse_block(), | ||||
|             TokenType::Underscore => todo!(), | ||||
|             TokenType::LBracket => self.parse_array(), | ||||
|             TokenType::Fn => self.parse_function(), | ||||
|             _ => self.error("expected value"), | ||||
|             TokenType::If => self.parse_if(), | ||||
|             TokenType::MalformedString => self.error("malformed string"), | ||||
|             other => self.node(Expr::Error(format!("expected value, got {:?}", other))), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_unit_group_or_tuple(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|     fn parse_string(&mut self) -> Node<Expr> { | ||||
|         let value_result = parse_string_value(&self.token_string(self.current())); | ||||
|         self.step_and_node(match value_result { | ||||
|             Ok(value) => Expr::String(value), | ||||
|             Err(error) => Expr::Error(error), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_unit_group_or_tuple(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         if !self.done() && !self.current_is(TokenType::LParen) { | ||||
|             todo!() | ||||
|             let first_value = self.parse_expr(); | ||||
|             if !self.done() && !self.current_is(TokenType::LParen) { | ||||
|                 todo!() | ||||
|             } else { | ||||
|                 self.step_and(first_value) | ||||
|             } | ||||
|         } else { | ||||
|             self.step_and_ok_node(Expr::Unit) | ||||
|             self.step_and_node(Expr::Unit) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_object(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         todo!() | ||||
|     fn parse_object(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let mut values = Vec::<Node<ObjectEntry>>::new(); | ||||
|         if !self.done() && !self.current_is(TokenType::RBracket) { | ||||
|             if self.current_is(TokenType::DotDotDot) { | ||||
|                 values.push(self.parse_object_entry()); | ||||
|             } else { | ||||
|                 values.push(self.parse_object_entry()); | ||||
|                 while !self.done() && self.current_is(TokenType::Comma) { | ||||
|                     self.step(); | ||||
|                     if self.done() || self.current_is(TokenType::RBracket) { | ||||
|                         break; | ||||
|                     } | ||||
|                     if self.current_is(TokenType::DotDotDot) { | ||||
|                         values.push(self.parse_object_entry()); | ||||
|                         break; | ||||
|                     } | ||||
|                     values.push(self.parse_object_entry()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if self.done() || !self.current_is(TokenType::RBracket) { | ||||
|             return self.error("expected ']'"); | ||||
|         } | ||||
|         self.step_and_node(Expr::Object(values)) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_array(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         todo!() | ||||
|     fn parse_object_entry(&mut self) -> Node<ObjectEntry> { | ||||
|         if self.done() { | ||||
|             return self.node(ObjectEntry::Error("expected object entry".to_string())); | ||||
|         } | ||||
|         match self.current().token_type { | ||||
|             TokenType::DotDotDot => { | ||||
|                 let expr = self.parse_spread(); | ||||
|                 self.node(ObjectEntry::Spread(Box::new(expr))) | ||||
|             } | ||||
|             TokenType::String => { | ||||
|                 let key = self.parse_string(); | ||||
|                 if self.done() || !self.current_is(TokenType::Colon) { | ||||
|                     return self.node(ObjectEntry::Error("expected ':'".to_string())); | ||||
|                 } | ||||
|                 self.step(); | ||||
|                 let value = self.parse_expr(); | ||||
|                 self.node(ObjectEntry::Pair { | ||||
|                     key: Box::new(key), | ||||
|                     value: Box::new(value), | ||||
|                 }) | ||||
|             } | ||||
|             _ => self.node(ObjectEntry::Error("expected object entry".to_string())), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn parse_function(&mut self) -> Result<Node<Expr>, ParserError> { | ||||
|         todo!() | ||||
|     fn parse_array(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let mut values = Vec::<Node<Expr>>::new(); | ||||
|         if !self.done() && !self.current_is(TokenType::RBracket) { | ||||
|             if self.current_is(TokenType::DotDotDot) { | ||||
|                 values.push(self.parse_spread()); | ||||
|             } else { | ||||
|                 values.push(self.parse_expr()); | ||||
|                 while !self.done() && self.current_is(TokenType::Comma) { | ||||
|                     self.step(); | ||||
|                     if self.done() || self.current_is(TokenType::RBracket) { | ||||
|                         break; | ||||
|                     } | ||||
|                     if self.current_is(TokenType::DotDotDot) { | ||||
|                         values.push(self.parse_spread()); | ||||
|                         break; | ||||
|                     } | ||||
|                     values.push(self.parse_expr()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if self.done() || !self.current_is(TokenType::RBracket) { | ||||
|             return self.error("expected ']'"); | ||||
|         } | ||||
|         self.step_and_node(Expr::Array(values)) | ||||
|     } | ||||
| 
 | ||||
|     fn parse_if(&mut self) -> Node<Expr> { | ||||
|         self.step(); | ||||
|         let condition = self.parse_expr(); | ||||
|         if self.done() || !self.current_is(TokenType::LBrace) { | ||||
|             return self.error("expected '{'"); | ||||
|         } | ||||
|         let truthy = self.parse_block(); | ||||
|         let mut falsy = None; | ||||
|         if !self.done() && self.current_is(TokenType::Else) { | ||||
|             self.step(); | ||||
|             if self.done() || !self.current_is(TokenType::LBrace) { | ||||
|                 return self.error("expected '{'"); | ||||
|             } | ||||
|             falsy = Some(self.parse_block()); | ||||
|         } | ||||
|         return self.node(Expr::If { | ||||
|             condition: Box::new(condition), | ||||
|             truthy: Box::new(truthy), | ||||
|             falsy: falsy.map(Box::new), | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     fn token_string(&self, token: &Token) -> String { | ||||
|         self.text[token.pos.index..token.pos.index + token.length].to_string() | ||||
|     } | ||||
| 
 | ||||
|     fn step_and_ok_node<T>(&mut self, value: T) -> Result<Node<T>, ParserError> { | ||||
|         self.step(); | ||||
|         self.ok_node(value) | ||||
|     } | ||||
| 
 | ||||
|     fn ok_node<T>(&self, value: T) -> Result<Node<T>, ParserError> { | ||||
|         Ok(Node { | ||||
|             value, | ||||
|             pos: self.tokens.pos(), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn step_and_node<T>(&mut self, value: T) -> Node<T> { | ||||
|         self.step(); | ||||
|         self.node(value) | ||||
|         self.step_and(self.node(value)) | ||||
|     } | ||||
| 
 | ||||
|     fn node<T>(&self, value: T) -> Node<T> { | ||||
| @ -400,11 +710,8 @@ where | ||||
|         value | ||||
|     } | ||||
| 
 | ||||
|     fn error(&self, message: &str) -> Result<Node<Expr>, ParserError> { | ||||
|         Err(ParserError { | ||||
|             pos: self.tokens.pos(), | ||||
|             message: message.to_string(), | ||||
|         }) | ||||
|     fn error(&self, message: &str) -> Node<Expr> { | ||||
|         self.node(Expr::Error(message.to_string())) | ||||
|     } | ||||
| 
 | ||||
|     fn done(&self) -> bool { | ||||
| @ -423,3 +730,48 @@ where | ||||
|         self.current_token = self.tokens.next(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn parse_string_value(text: &str) -> Result<String, String> { | ||||
|     let mut input = text.chars().peekable(); | ||||
|     let mut value = String::new(); | ||||
|     input.next().ok_or_else(|| "invalid string".to_string())?; | ||||
|     while !matches!(input.peek(), Some('"')) { | ||||
|         value.push(unescape_char_value(&mut input)?) | ||||
|     } | ||||
|     Ok(value) | ||||
| } | ||||
| 
 | ||||
| fn unescape_char_value(input: &mut Peekable<Chars>) -> Result<char, String> { | ||||
|     let step_and = |input2: &mut Peekable<Chars>, value: char| { | ||||
|         input2.next().ok_or("invalid string".to_string())?; | ||||
|         Ok(value) | ||||
|     }; | ||||
|     if matches!(input.peek(), Some('\\')) { | ||||
|         input.next().ok_or("invalid string".to_string())?; | ||||
|         match input.peek() { | ||||
|             Some('t') => step_and(input, '\t'), | ||||
|             Some('r') => step_and(input, '\r'), | ||||
|             Some('n') => step_and(input, '\n'), | ||||
|             Some('0') => step_and(input, '\0'), | ||||
|             Some('x') => { | ||||
|                 input.next().ok_or("invalid string".to_string())?; | ||||
|                 let mut value = String::new(); | ||||
|                 for _ in 0..2 { | ||||
|                     value.push( | ||||
|                         input | ||||
|                             .next() | ||||
|                             .ok_or_else(|| "invalid escape sequence".to_string())?, | ||||
|                     ); | ||||
|                 } | ||||
|                 let int_value = value | ||||
|                     .parse::<u8>() | ||||
|                     .map_err(|error| format!("invalid char code: {}", error.to_string()))?; | ||||
|                 char::from_u32(int_value.into()).ok_or_else(|| "invalid char code".to_string()) | ||||
|             } | ||||
|             Some(_) => input.next().ok_or_else(|| "invalid string".to_string()), | ||||
|             None => Err("invalid escape sequence".to_string()), | ||||
|         } | ||||
|     } else { | ||||
|         input.next().ok_or("invalid string".to_string()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -74,6 +74,9 @@ pub enum TokenType { | ||||
|     Colon, | ||||
|     Semicolon, | ||||
|     Ampersand, | ||||
|     DotDot, | ||||
|     DotDotDot, | ||||
|     EqualLessThan, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user