diff --git a/src/generator/js.rs b/src/generator/js.rs index ea2730c..8c02f5d 100644 --- a/src/generator/js.rs +++ b/src/generator/js.rs @@ -93,6 +93,7 @@ fn generate_expression(expr: Expression) -> String { Expression::Bool(b) => b.to_string(), Expression::FunctionCall(name, e) => generate_function_call(name, e), Expression::Array(els) => generate_array(els), + Expression::ArrayAccess(name, expr) => generate_array_access(name, *expr), Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), } } @@ -123,6 +124,10 @@ fn generate_array(elements: Vec) -> String { out_str } +fn generate_array_access(name: String, expr: Expression) -> String { + format!("{n}[{e}]", n = name, e = generate_expression(expr)) +} + fn generate_conditional( expr: Expression, if_state: Statement, @@ -166,6 +171,7 @@ fn generate_function_call(func: String, args: Vec) -> String { Expression::Char(c) => c.to_string(), Expression::Int(i) => i.to_string(), Expression::Bool(v) => v.to_string(), + Expression::ArrayAccess(name, expr) => generate_array_access(name, *expr), Expression::FunctionCall(n, a) => generate_function_call(n, a), Expression::Str(s) | Expression::Variable(s) => s, Expression::Array(_) => todo!(), diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index e170b4c..8e30d57 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -54,6 +54,8 @@ pub enum Expression { Array(Vec), FunctionCall(String, Vec), Variable(String), + /// (name, index) + ArrayAccess(String, Box), BinOp(Box, BinOp, Box), } diff --git a/src/parser/rules.rs b/src/parser/rules.rs index dcb33f5..d968118 100644 --- a/src/parser/rules.rs +++ b/src/parser/rules.rs @@ -103,6 +103,9 @@ impl Parser { } else if let Ok(_) = self.peek_token(TokenKind::Assign) { let state = self.parse_assignent(Some(ident))?; Ok(state) + } else if let Ok(_) = self.peek_token(TokenKind::SquareBraceOpen) { + let expr = self.parse_array_access(Some(ident))?; + Ok(Statement::Exp(expr)) } else { let state = Statement::Exp(Expression::Variable(ident.into())); Ok(state) @@ -193,6 +196,13 @@ impl Parser { Err(_) => func_call, } } + TokenKind::SquareBraceOpen => { + let arr = self.parse_array_access(Some(val))?; + match BinOp::try_from(self.peek()?.kind) { + Ok(_) => self.parse_bin_op(Some(arr))?, + Err(_) => arr, + } + } _ => match BinOp::try_from(self.peek()?.kind) { Ok(_) => self.parse_bin_op(Some(Expression::Variable(token.raw)))?, Err(_) => Expression::Variable(val), @@ -230,6 +240,19 @@ impl Parser { Ok(Expression::Array(elements)) } + fn parse_array_access(&mut self, arr_name: Option) -> Result { + let name = match arr_name { + Some(name) => name, + None => self.next()?.raw, + }; + + self.match_token(TokenKind::SquareBraceOpen)?; + let expr = self.parse_expression()?; + self.match_token(TokenKind::SquareBraceClose)?; + + Ok(Expression::ArrayAccess(name, Box::new(expr))) + } + fn parse_while_loop(&mut self) -> Result { self.match_keyword(Keyword::While)?; let expr = self.parse_expression()?; diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 4b861c9..30e032e 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -451,3 +451,36 @@ fn test_boolean_arithmetic() { let tree = parse(tokens, Some(raw.to_string())); assert!(tree.is_ok()) } + +#[test] +fn test_array_access_in_loop() { + let raw = " + fn main() { + let x = [1, 2, 3, 4, 5] + + let i = 0 + + while i < 5 { + println(x[i]) + i = i + 1 + } + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +} + +#[test] +fn test_array_access_standalone() { + let raw = " + fn main() { + let x = [1, 2, 3, 4, 5] + + x[0] + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +}