diff --git a/src/ast.rs b/src/ast.rs index 974d05a..d37c9b2 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -8,6 +8,7 @@ pub struct Node { #[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>), - Object(Vec), + Object(Vec>), Tuple(Vec>), + If { + condition: Box>, + truthy: Box>, + falsy: Option>>, + }, + Member { subject: Box>, value: String, @@ -39,11 +46,44 @@ pub enum Expr { left: Box>, right: Box>, }, + + Assign { + assign_type: AssignType, + subject: Box>, + value: Box>, + }, + Let { + subject: Node, + value: Option>>, + }, + Continue, + Break, + While { + condition: Box>, + body: Box>, + }, + Return(Option>>), + Function { + name: String, + parameters: Vec>, + body: Box>, + }, + Block { + statements: Vec>, + value: Option>>, + }, + + Spread(Box>), } #[derive(Debug)] pub enum ObjectEntry { - Pair(Box>, Box), + Error(String), + Pair { + key: Box>, + value: Box>, + }, + Spread(Box>), } #[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>), +} diff --git a/src/lexer.rs b/src/lexer.rs index 898c264..4e45450 100644 --- a/src/lexer.rs +++ b/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) } diff --git a/src/main.rs b/src/main.rs index 9c63157..9f9c0df 100644 --- a/src/main.rs +++ b/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); diff --git a/src/parser.rs b/src/parser.rs index 345ab56..231f94f 100644 --- a/src/parser.rs +++ b/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, ParserError> { + pub fn parse_top_level_statements(&mut self) -> Vec> { + let mut statements = Vec::>::new(); + while !self.done() { + statements.push(self.parse_statement()); + } + statements + } + + fn parse_block(&mut self) -> Node { + self.step(); + let mut statements = Vec::>::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 { + 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 { + 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::>::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 { + 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 { + 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 { + 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 { + self.step_and_node(Expr::Continue) + } + + fn parse_continue(&mut self) -> Node { + self.step_and_node(Expr::Continue) + } + + fn parse_let(&mut self) -> Node { + 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 { + 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 { + self.step(); + let inner = self.parse_expr(); + self.node(Expr::Spread(Box::new(inner))) + } + + pub fn parse_expr(&mut self) -> Node { self.parse_prec_or() } - fn parse_prec_or(&mut self) -> Result, ParserError> { - let mut left = self.parse_prec_and()?; + fn parse_prec_or(&mut self) -> Node { + 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, ParserError> { - let mut left = self.parse_prec_equal_inequal()?; + fn parse_prec_and(&mut self) -> Node { + 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, ParserError> { - let mut left = self.parse_prec_lt_lte_gt_gte_in()?; + fn parse_prec_equal_inequal(&mut self) -> Node { + 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, ParserError> { - let mut left = self.parse_prec_add_subtract()?; + fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Node { + 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, ParserError> { - let mut left = self.parse_prec_multiply_divide_modulo()?; + fn parse_prec_add_subtract(&mut self) -> Node { + 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, ParserError> { - let mut left = self.parse_prec_unary()?; + fn parse_prec_multiply_divide_modulo(&mut self) -> Node { + 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, ParserError> { + fn parse_prec_unary(&mut self) -> Node { 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, ParserError> { - let left = self.parse_prec_member_index_call()?; + fn parse_prec_exponentiate(&mut self) -> Node { + 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, ParserError> { - let mut subject = self.parse_operand()?; + fn parse_prec_member_index_call(&mut self) -> Node { + 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::>::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, ParserError> { + fn parse_operand(&mut self) -> Node { 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::().expect("valid f64"), - )) + self.step_and_node(Expr::Float(value_string.parse::().expect("valid f64"))) } else { - self.ok_node(Expr::Int((value_string).parse::().expect("valid i64"))) + self.node(Expr::Int((value_string).parse::().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::() .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, ParserError> { + fn parse_string(&mut self) -> Node { + 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 { 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, ParserError> { - todo!() + fn parse_object(&mut self) -> Node { + self.step(); + let mut values = Vec::>::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, ParserError> { - todo!() + fn parse_object_entry(&mut self) -> Node { + 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, ParserError> { - todo!() + fn parse_array(&mut self) -> Node { + self.step(); + let mut values = Vec::>::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 { + 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(&mut self, value: T) -> Result, ParserError> { - self.step(); - self.ok_node(value) - } - - fn ok_node(&self, value: T) -> Result, ParserError> { - Ok(Node { - value, - pos: self.tokens.pos(), - }) - } - fn step_and_node(&mut self, value: T) -> Node { - self.step(); - self.node(value) + self.step_and(self.node(value)) } fn node(&self, value: T) -> Node { @@ -400,11 +710,8 @@ where value } - fn error(&self, message: &str) -> Result, ParserError> { - Err(ParserError { - pos: self.tokens.pos(), - message: message.to_string(), - }) + fn error(&self, message: &str) -> Node { + 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 { + 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) -> Result { + let step_and = |input2: &mut Peekable, 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::() + .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()) + } +} diff --git a/src/tokens.rs b/src/tokens.rs index 05a5f17..789fbdf 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -74,6 +74,9 @@ pub enum TokenType { Colon, Semicolon, Ampersand, + DotDot, + DotDotDot, + EqualLessThan, } #[derive(Debug)]