Browse Source

Add array access syntax

github-actions
Garrit Franke 3 years ago
parent
commit
ac07e43719
  1. 6
      src/generator/js.rs
  2. 2
      src/parser/node_type.rs
  3. 23
      src/parser/rules.rs
  4. 33
      src/parser/tests.rs

6
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<Expression>) -> 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<Expression>) -> 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!(),

2
src/parser/node_type.rs

@ -54,6 +54,8 @@ pub enum Expression {
Array(Vec<Expression>),
FunctionCall(String, Vec<Expression>),
Variable(String),
/// (name, index)
ArrayAccess(String, Box<Expression>),
BinOp(Box<Expression>, BinOp, Box<Expression>),
}

23
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<String>) -> Result<Expression, String> {
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<Statement, String> {
self.match_keyword(Keyword::While)?;
let expr = self.parse_expression()?;

33
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())
}

Loading…
Cancel
Save