From db1274d4c9c6a4e78cce2f225e1894a85d76c5ac Mon Sep 17 00:00:00 2001 From: ghostlyzsh Date: Fri, 2 Aug 2024 08:22:01 -0500 Subject: [PATCH] array, subscript --- kabel/grammar.ebnf | 8 +++-- kabel/src/lexer.rs | 11 +++++++ kabel/src/parser.rs | 74 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/kabel/grammar.ebnf b/kabel/grammar.ebnf index 5dfad1219b2a9754c03dcd9e9c7ce55d964ee67d..f87c4963c54aa2b93e855cb5d8fa57028ec60d99 100644 --- a/kabel/grammar.ebnf +++ b/kabel/grammar.ebnf @@ -34,9 +34,13 @@ term = factor { , ( "+" | "-" ) , factor } ; factor = unary { , ( "*" | "/" ) , unary } ; -unary = ( ( "!" | "-" ) , unary ) | primary ; +unary = ( ( "!" | "-" ) , unary ) | subscript ; -primary = identifier | member | call | number | string | group ; +subscript = primary , { "[" , expression , "]" , } + +primary = identifier | array | member | call | number | string | group ; + +array = "[" , { expression , "," ? } , "]" ; member = identifier , "." , { ( identifier | call ) , "." ? } ; diff --git a/kabel/src/lexer.rs b/kabel/src/lexer.rs index 3e0a3109f56d47cce0a8f486164f716325fc2c9f..50afd0eb97f323cd50130ef484834224685f40cd 100644 --- a/kabel/src/lexer.rs +++ b/kabel/src/lexer.rs @@ -74,6 +74,14 @@ impl Lexer { self.output.push(token!(self, TokenType::RightBrace)); self.start = self.current; } + b'[' => { + self.output.push(token!(self, TokenType::LeftSquare)); + self.start = self.current; + } + b']' => { + self.output.push(token!(self, TokenType::RightSquare)); + self.start = self.current; + } b'.' => { self.output.push(token!(self, TokenType::Period)); self.start = self.current; @@ -184,6 +192,7 @@ impl Lexer { self.read_char(); } 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(); while self.peek().is_ascii_digit() { @@ -256,6 +265,8 @@ pub enum TokenType { RightParen, LeftBrace, RightBrace, + LeftSquare, + RightSquare, Period, Comma, Semicolon, diff --git a/kabel/src/parser.rs b/kabel/src/parser.rs index 777def36f407818addb41b8e953dfc2eb4b0de28..609357379c38d0640f54449765f00c86aa5b525d 100644 --- a/kabel/src/parser.rs +++ b/kabel/src/parser.rs @@ -126,11 +126,7 @@ impl Parser { column: return_ident.column, }) } else { - return Err(unexpected_token!( - self, - "Expected ; found {}", - semicolon - )); + return Err(unexpected_token!(self, "Expected ; found {}", semicolon)); } } @@ -177,7 +173,7 @@ impl Parser { ast_type: ASTType::Break, start: break_ident.start, end: semicolon.end, - line: break_ident.line, + line: break_ident.line, column: break_ident.column, }) } else { @@ -193,7 +189,7 @@ impl Parser { ast_type: ASTType::Continue, start: continue_ident.start, end: semicolon.end, - line: continue_ident.line, + line: continue_ident.line, column: continue_ident.column, }) } else { @@ -625,7 +621,30 @@ impl Parser { } } - Ok(self.primary()?) + self.subscript() + } + pub fn subscript(&mut self) -> Result { + let mut primary = self.primary()?; + + while self.current < self.input.len() && + self.peek()?.token_type == TokenType::LeftSquare { + self.read_token()?; + let expr = self.expression()?; + let right_brace = self.read_token()?; + if let TokenType::RightSquare = right_brace.token_type { + primary = AST { + ast_type: ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)), + start: primary.start, + end: right_brace.end, + line: primary.line, + column: primary.column, + }; + } else { + return Err(unexpected_token!(self, "Expected ] found {}", right_brace)); + } + } + + Ok(primary) } pub fn primary(&mut self) -> Result { let token = self.read_token()?; @@ -667,7 +686,10 @@ impl Parser { }); } TokenType::LeftParen => { - return Ok(self.group(token)?); + return self.group(token); + } + TokenType::LeftSquare => { + return self.array(token); } _ => { return Err(unexpected_token!(self, "Unexpected token {}", token)); @@ -675,6 +697,24 @@ impl Parser { } } + pub fn array(&mut self, left_square: Token) -> Result { + let mut expressions = Vec::new(); + while self.peek()?.token_type != TokenType::RightSquare { + expressions.push(self.expression()?); + if let TokenType::Comma = self.peek()?.token_type { + self.read_token()?; + } + } + let right_square = self.read_token()?; + Ok(AST { + ast_type: ASTType::Lit(Lit::Array(expressions)), + start: left_square.start, + end: right_square.end, + line: left_square.line, + column: left_square.column, + }) + } + pub fn member(&mut self, ident: Token) -> Result { if let TokenType::Ident(first) = ident.token_type { let mut expr: AST = lit!(Ident, first, ident); @@ -823,17 +863,18 @@ pub enum ASTType { Program(Vec), // statements - Function(Box, Vec, Box), // name, args, block - Return(Option>), // expression - Loop(Box), // block - While(Box, Box), // condition, block + Function(Box, Vec, Box), // name, args, block + Return(Option>), // expression + Loop(Box), // block + While(Box, Box), // condition, block Break, Continue, - If(Box, Box, Option>), // condition, block, else/else if - Block(Vec), // statements + If(Box, Box, Option>), // condition, block, else/else if + Block(Vec), // statements // expressions - Decl(Box, Box), // identifier, expression + Decl(Box, Box), // identifier, expression + Subscript(Box, Box), Binary(Box, BinOp, Box), Unary(UnOp, Box), @@ -849,6 +890,7 @@ pub enum Lit { Ident(String), Num(f32), Str(String), + Array(Vec), } #[derive(Debug, Clone, Copy)]