From 71a2bac16823bbefefc853981832a48d149c2aa5 Mon Sep 17 00:00:00 2001 From: ghostlyzsh Date: Sat, 3 Aug 2024 01:50:36 -0500 Subject: [PATCH] switch to keywords --- kabel/grammar.ebnf | 3 +- kabel/src/lexer.rs | 34 +++- kabel/src/parser.rs | 423 ++++++++++++++++++++++++++++++++------------ 3 files changed, 345 insertions(+), 115 deletions(-) diff --git a/kabel/grammar.ebnf b/kabel/grammar.ebnf index 7ea3f6d94ad9416147853d0a9b1b55d344079193..6a6e5c436f07620bf8115c9780826050ed823a09 100644 --- a/kabel/grammar.ebnf +++ b/kabel/grammar.ebnf @@ -22,7 +22,8 @@ expression = assignment | declaration ; declaration = "var" , identifier , "=" , expression ; -assignment = ( identifier , "=" , assignment ) | logical_or; +assignment = ( identifier , ( "=" | "+=" | "-=" | "*=" + | "/=" | "%=" | "&=" | "^=" | "|=" ) , assignment ) | logical_or; logical_or = logical_and { , "||" , logical_and } ; diff --git a/kabel/src/lexer.rs b/kabel/src/lexer.rs index 0bced9c2958dbfcf743a181db1177bb196c5cef4..9d5a90d121f6a4ef72977eda2a953fd307acb27b 100644 --- a/kabel/src/lexer.rs +++ b/kabel/src/lexer.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::{ error::{ErrorKind, KabelError}, token, @@ -11,12 +13,24 @@ pub struct Lexer { line_start: usize, column: usize, c: char, + keywords: HashMap, pub errors: Vec, pub output: Vec, } impl Lexer { pub fn new(input: String) -> Self { + let mut keywords = HashMap::new(); + keywords.insert("function".to_string(), TokenType::Function); + keywords.insert("return".to_string(), TokenType::Return); + keywords.insert("loop".to_string(), TokenType::Loop); + keywords.insert("while".to_string(), TokenType::While); + keywords.insert("for".to_string(), TokenType::For); + keywords.insert("break".to_string(), TokenType::Break); + keywords.insert("continue".to_string(), TokenType::Continue); + keywords.insert("if".to_string(), TokenType::If); + keywords.insert("else".to_string(), TokenType::Else); + keywords.insert("var".to_string(), TokenType::Var); Self { input: input.chars().collect(), start: 0, @@ -25,6 +39,7 @@ impl Lexer { line_start: 0, column: 0, c: '\0', + keywords, errors: Vec::new(), output: Vec::new(), } @@ -237,7 +252,11 @@ impl Lexer { content.push(self.c as char); self.read_char(); } - self.output.push(token!(self, TokenType::Ident(content))); + if self.keywords.contains_key(&content) { + self.output.push(token!(self, self.keywords.get(&content).unwrap().clone())); + } else { + self.output.push(token!(self, TokenType::Ident(content))); + } self.start = self.current; } else if c.is_ascii_digit() { let mut number = (c as char).to_string(); @@ -301,6 +320,19 @@ pub struct Token { #[derive(Debug, Clone, PartialEq)] pub enum TokenType { + // keywords + Function, + Return, + Loop, + While, + For, + Break, + Continue, + If, + Else, + Var, + + // characters Star, StarEqual, Slash, diff --git a/kabel/src/parser.rs b/kabel/src/parser.rs index be6893bdf0cfa1c22bf6372bb8166ca6791ee59c..025cc23aa69966edbaf28bc9c077ae1a85f5cf8c 100644 --- a/kabel/src/parser.rs +++ b/kabel/src/parser.rs @@ -1,5 +1,8 @@ use crate::{ - ast, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, unexpected_token + ast, + error::{ErrorKind, KabelError}, + lexer::{Token, TokenType}, + lit, unexpected_token, }; pub struct Parser { @@ -45,17 +48,14 @@ impl Parser { pub fn statement(&mut self) -> Result { match self.peek()?.token_type { - TokenType::Ident(ident) => match ident.as_str() { - "function" => self.function_statement(), - "return" => self.return_statement(), - "loop" => self.loop_statement(), - "while" => self.while_statement(), - "for" => self.for_statement(), - "break" => self.break_statement(), - "continue" => self.continue_statement(), - "if" => self.if_statement(), - _ => self.expression_statement(), - }, + TokenType::Function => self.function_statement(), + TokenType::Return => self.return_statement(), + TokenType::Loop => self.loop_statement(), + TokenType::While => self.while_statement(), + TokenType::For => self.for_statement(), + TokenType::Break => self.break_statement(), + TokenType::Continue => self.continue_statement(), + TokenType::If => self.if_statement(), _ => self.expression_statement(), } } @@ -76,8 +76,15 @@ impl Parser { let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; - return Ok(ast!(ASTType::Function(Box::new(lit!(Ident, name, ident)), - expressions, Box::new(block.clone())), function_ident, block)); + return Ok(ast!( + ASTType::Function( + Box::new(lit!(Ident, name, ident)), + expressions, + Box::new(block.clone()) + ), + function_ident, + block + )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } @@ -108,7 +115,11 @@ impl Parser { let expression = self.expression()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { - Ok(ast!(ASTType::Return(Some(Box::new(expression))), return_ident, semicolon)) + Ok(ast!( + ASTType::Return(Some(Box::new(expression))), + return_ident, + semicolon + )) } else { return Err(unexpected_token!(self, "Expected ; found {}", semicolon)); } @@ -117,7 +128,11 @@ impl Parser { pub fn loop_statement(&mut self) -> Result { let loop_ident = self.read_token()?; let block = self.block()?; - Ok(ast!(ASTType::Loop(Box::new(block.clone())), loop_ident, block)) + Ok(ast!( + ASTType::Loop(Box::new(block.clone())), + loop_ident, + block + )) } pub fn while_statement(&mut self) -> Result { @@ -128,7 +143,11 @@ impl Parser { let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; - return Ok(ast!(ASTType::While(Box::new(condition), Box::new(block.clone())), while_ident, block)); + return Ok(ast!( + ASTType::While(Box::new(condition), Box::new(block.clone())), + while_ident, + block + )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } @@ -166,8 +185,16 @@ impl Parser { let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; - return Ok(ast!(ASTType::For(Box::new(expression1), Box::new(expression2), - Box::new(expression3), Box::new(block.clone())), for_ident, block)); + return Ok(ast!( + ASTType::For( + Box::new(expression1), + Box::new(expression2), + Box::new(expression3), + Box::new(block.clone()) + ), + for_ident, + block + )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } @@ -212,35 +239,40 @@ impl Parser { let block = self.block()?; if self.current < self.input.len() { let else_ident = self.read_token()?; - if let TokenType::Ident(content) = else_ident.token_type { - if content == "else" { - if let TokenType::LeftBrace = self.peek()?.token_type { - let else_block = self.block()?; - return Ok(ast!(ASTType::If(Box::new(condition), Box::new(block.clone()), - Some(Box::new(else_block.clone()))), if_ident, else_block)); - } - let else_if_ident = self.peek()?; - if let TokenType::Ident(content) = else_if_ident.token_type { - if content == "if" { - let else_if = self.if_statement()?; - return Ok(ast!(ASTType::If(Box::new(condition), Box::new(block.clone()), - Some(Box::new(else_if.clone()))), if_ident, else_if)); - } else { - return Err(unexpected_token!( - self, - "Expected if found {}", - else_if_ident - )); - } - } - return Err(unexpected_token!(self, "Unexpected token {}", else_ident)); - } else { - self.current -= 1; + if let TokenType::Else = else_ident.token_type { + if let TokenType::LeftBrace = self.peek()?.token_type { + let else_block = self.block()?; + return Ok(ast!( + ASTType::If( + Box::new(condition), + Box::new(block.clone()), + Some(Box::new(else_block.clone())) + ), + if_ident, + else_block + )); } + let else_if_ident = self.peek()?; + if let TokenType::If = else_if_ident.token_type { + let else_if = self.if_statement()?; + return Ok(ast!( + ASTType::If( + Box::new(condition), + Box::new(block.clone()), + Some(Box::new(else_if.clone())) + ), + if_ident, + else_if + )); + } + return Err(unexpected_token!(self, "Unexpected token {}", else_ident)); } } - return Ok(ast!(ASTType::If(Box::new(condition), Box::new(block.clone()), - None), if_ident, block)); + return Ok(ast!( + ASTType::If(Box::new(condition), Box::new(block.clone()), None), + if_ident, + block + )); } else { return Err(unexpected_token!(self, "Expected ) found {}", right_paren)); } @@ -285,10 +317,8 @@ impl Parser { } pub fn expression(&mut self) -> Result { - if let TokenType::Ident(name) = self.peek()?.token_type { - if name == "var" { - return self.declaration(); - } + if let TokenType::Var = self.peek()?.token_type { + return self.declaration(); } let assignment = self.assignment()?; Ok(assignment) @@ -301,7 +331,11 @@ impl Parser { let equal = self.read_token()?; if let TokenType::Equal = equal.token_type { let expr = self.expression()?; - return Ok(ast!(ASTType::Decl(Box::new(lit!(Ident, name, ident)), Box::new(expr.clone())), var, expr)); + return Ok(ast!( + ASTType::Decl(Box::new(lit!(Ident, name, ident)), Box::new(expr.clone())), + var, + expr + )); } else { return Err(unexpected_token!(self, "Expected = found {}", equal)); } @@ -321,11 +355,16 @@ impl Parser { self.current -= 1; return self.logical_or(); } - if let TokenType::Equal | TokenType::PlusEqual - | TokenType::MinusEqual | TokenType::StarEqual - | TokenType::SlashEqual | TokenType::PercentEqual - | TokenType::AndEqual | TokenType::CaretEqual - | TokenType::OrEqual = self.peek()?.token_type { + if let TokenType::Equal + | TokenType::PlusEqual + | TokenType::MinusEqual + | TokenType::StarEqual + | TokenType::SlashEqual + | TokenType::PercentEqual + | TokenType::AndEqual + | TokenType::CaretEqual + | TokenType::OrEqual = self.peek()?.token_type + { let binop = self.read_token()?; let expr = self.assignment()?; if binop.token_type == TokenType::Equal { @@ -340,32 +379,95 @@ impl Parser { line: ident.line, column: ident.column, });*/ - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::Asn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::Asn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::PlusEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::AddAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::AddAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::MinusEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::SubAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::SubAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::StarEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::MulAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::MulAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::SlashEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::DivAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::DivAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::PercentEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::ModAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::ModAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::AndEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::AndAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::AndAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else if binop.token_type == TokenType::CaretEqual { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::XorAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::XorAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } else { - return Ok(ast!(ASTType::Binary(Box::new(lit!(Ident, name, ident)), - BinOp::OrAsn, Box::new(expr.clone())), ident, expr)); + return Ok(ast!( + ASTType::Binary( + Box::new(lit!(Ident, name, ident)), + BinOp::OrAsn, + Box::new(expr.clone()) + ), + ident, + expr + )); } } self.current -= 1; @@ -381,8 +483,11 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::OrOr { self.read_token()?; let right = self.logical_and()?; - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Or, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Or, Box::new(right.clone())), + left, + right + ); } Ok(left) @@ -393,8 +498,11 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::AndAnd { self.read_token()?; let right = self.bit_and()?; - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::And, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::And, Box::new(right.clone())), + left, + right + ); } Ok(left) @@ -405,8 +513,15 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::And { self.read_token()?; let right = self.bit_xor()?; - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::BitAnd, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary( + Box::new(left.clone()), + BinOp::BitAnd, + Box::new(right.clone()) + ), + left, + right + ); } Ok(left) @@ -417,8 +532,15 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::Caret { self.read_token()?; let right = self.bit_or()?; - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::BitXor, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary( + Box::new(left.clone()), + BinOp::BitXor, + Box::new(right.clone()) + ), + left, + right + ); } Ok(left) @@ -429,8 +551,15 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::Or { self.read_token()?; let right = self.equality()?; - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::BitOr, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary( + Box::new(left.clone()), + BinOp::BitOr, + Box::new(right.clone()) + ), + left, + right + ); } Ok(left) @@ -445,11 +574,17 @@ impl Parser { let binop = self.read_token()?; let right = self.comparison()?; if binop.token_type == TokenType::EqualEqual { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Eq, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Eq, Box::new(right.clone())), + left, + right + ); } else { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Ne, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Ne, Box::new(right.clone())), + left, + right + ); } } @@ -468,17 +603,29 @@ impl Parser { let binop = self.read_token()?; let right = self.term()?; if binop.token_type == TokenType::Less { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Ls, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Ls, Box::new(right.clone())), + left, + right + ); } else if binop.token_type == TokenType::LessEqual { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Le, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Le, Box::new(right.clone())), + left, + right + ); } else if binop.token_type == TokenType::Greater { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Gr, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Gr, Box::new(right.clone())), + left, + right + ); } else { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Ge, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Ge, Box::new(right.clone())), + left, + right + ); } } @@ -496,11 +643,17 @@ impl Parser { let right = self.factor()?; if binop.token_type == TokenType::Plus { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Add, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Add, Box::new(right.clone())), + left, + right + ); } else { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Sub, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Sub, Box::new(right.clone())), + left, + right + ); } } Ok(left) @@ -517,14 +670,23 @@ impl Parser { let right = self.unary()?; if binop.token_type == TokenType::Star { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Mul, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Mul, Box::new(right.clone())), + left, + right + ); } else if binop.token_type == TokenType::Slash { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Div, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Div, Box::new(right.clone())), + left, + right + ); } else { - left = ast!(ASTType::Binary(Box::new(left.clone()), BinOp::Mod, - Box::new(right.clone())), left, right); + left = ast!( + ASTType::Binary(Box::new(left.clone()), BinOp::Mod, Box::new(right.clone())), + left, + right + ); } } Ok(left) @@ -534,9 +696,17 @@ impl Parser { let token = self.read_token()?; let unary = self.unary()?; if token.token_type == TokenType::Bang { - return Ok(ast!(ASTType::Unary(UnOp::Not, Box::new(unary.clone())), token, unary)); + return Ok(ast!( + ASTType::Unary(UnOp::Not, Box::new(unary.clone())), + token, + unary + )); } else { - return Ok(ast!(ASTType::Unary(UnOp::Neg, Box::new(unary.clone())), token, unary)); + return Ok(ast!( + ASTType::Unary(UnOp::Neg, Box::new(unary.clone())), + token, + unary + )); } } @@ -550,7 +720,11 @@ impl Parser { let expr = self.expression()?; let right_brace = self.read_token()?; if let TokenType::RightSquare = right_brace.token_type { - primary = ast!(ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)), primary, right_brace); + primary = ast!( + ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)), + primary, + right_brace + ); } else { return Err(unexpected_token!(self, "Expected ] found {}", right_brace)); } @@ -600,7 +774,11 @@ impl Parser { } } let right_square = self.read_token()?; - Ok(ast!(ASTType::Lit(Lit::Array(expressions)), left_square, right_square)) + Ok(ast!( + ASTType::Lit(Lit::Array(expressions)), + left_square, + right_square + )) } pub fn member(&mut self, ident: Token) -> Result { @@ -613,14 +791,25 @@ impl Parser { if self.current < self.input.len() { if let TokenType::LeftParen = self.peek()?.token_type { let call = self.call(child)?; - expr = ast!(ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())), expr, call); + expr = ast!( + ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())), + expr, + call + ); if self.current >= self.input.len() { break; } continue; } } - expr = ast!(ASTType::Member(Box::new(expr.clone()), Box::new(lit!(Ident, child_str, child))), expr, child); + expr = ast!( + ASTType::Member( + Box::new(expr.clone()), + Box::new(lit!(Ident, child_str, child)) + ), + expr, + child + ); } else { return Err(unexpected_token!(self, "Unexpected token {}", child)); } @@ -644,7 +833,11 @@ impl Parser { } let right_paren = self.read_token()?; if let TokenType::Ident(name) = ident.token_type { - return Ok(ast!(ASTType::Call(Box::new(lit!(Ident, name, ident)), expressions), ident, right_paren)); + return Ok(ast!( + ASTType::Call(Box::new(lit!(Ident, name, ident)), expressions), + ident, + right_paren + )); } panic!("Call logic broke"); } @@ -663,7 +856,11 @@ impl Parser { )); } self.read_token()?; - return Ok(ast!(ASTType::Group(Box::new(expr.clone())), left_paren, right_paren)); + return Ok(ast!( + ASTType::Group(Box::new(expr.clone())), + left_paren, + right_paren + )); } if let Err(e) = right_paren { return Err(KabelError::new(