Skip to content

Commit

Permalink
feat: parse array literal
Browse files Browse the repository at this point in the history
  • Loading branch information
viddrobnic committed May 27, 2024
1 parent 3e5aacb commit a525632
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 1 deletion.
60 changes: 59 additions & 1 deletion parser/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl Parser<'_> {
range,
})?,
TokenKind::LBracket => self.parse_grouped(range)?,
TokenKind::LSquare => todo!("parse array literal"),
TokenKind::LSquare => self.parse_array_literal(range)?,
TokenKind::LCurly => todo!("parse hash map literal"),
TokenKind::If => todo!("parse if statement"),
TokenKind::While => todo!("parse while loop"),
Expand Down Expand Up @@ -322,6 +322,64 @@ impl Parser<'_> {

Ok((node.value, closing_token.range.end))
}

fn parse_array_literal(&mut self, start_range: Range) -> Result<(ast::NodeValue, Position)> {
let mut res = vec![];
let mut end = start_range.end;

let mut can_parse = true;
loop {
self.skip_eol()?;

let Some(token) = self.lexer.next() else {
return Err(Error {
kind: ErrorKind::UnexpectedEof,
range: Range {
start: start_range.start,
end,
},
});
};
let token = token?;

if token.kind == TokenKind::RSquare {
return Ok((ast::NodeValue::ArrayLiteral(res), token.range.end));
}

if !can_parse {
return Err(Error {
kind: ErrorKind::InvalidTokenKind {
expected: TokenKind::RSquare,
got: token.kind,
},
range: token.range,
});
}

let item = self.parse_node(token, Precedence::Lowest)?;
end = item.range.end;
res.push(item);

peek_token!(
self,
token_peek,
return Err(Error {
kind: ErrorKind::UnexpectedEof,
range: Range {
start: start_range.start,
end,
}
})
);

if token_peek.kind == TokenKind::Comma {
self.lexer.next();
can_parse = true;
} else {
can_parse = false;
}
}
}
}

fn token_to_infix_operator(token: &TokenKind) -> InfixOperatorKind {
Expand Down
120 changes: 120 additions & 0 deletions parser/src/parser/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,125 @@ fn grouped() -> Result<()> {
Ok(())
}

#[test]
fn array_literal() -> Result<()> {
let tests = [
(
"[]",
ast::Node {
value: ast::NodeValue::ArrayLiteral(vec![]),
range: Range {
start: Position::new(0, 0),
end: Position::new(0, 2),
},
},
),
(
"[1]",
ast::Node {
value: ast::NodeValue::ArrayLiteral(vec![ast::Node {
value: ast::NodeValue::IntegerLiteral(1),
range: Range {
start: Position::new(0, 1),
end: Position::new(0, 2),
},
}]),
range: Range {
start: Position::new(0, 0),
end: Position::new(0, 3),
},
},
),
(
"[1, 2]",
ast::Node {
value: ast::NodeValue::ArrayLiteral(vec![
ast::Node {
value: ast::NodeValue::IntegerLiteral(1),
range: Range {
start: Position::new(0, 1),
end: Position::new(0, 2),
},
},
ast::Node {
value: ast::NodeValue::IntegerLiteral(2),
range: Range {
start: Position::new(0, 4),
end: Position::new(0, 5),
},
},
]),
range: Range {
start: Position::new(0, 0),
end: Position::new(0, 6),
},
},
),
(
"[1, 2,]",
ast::Node {
value: ast::NodeValue::ArrayLiteral(vec![
ast::Node {
value: ast::NodeValue::IntegerLiteral(1),
range: Range {
start: Position::new(0, 1),
end: Position::new(0, 2),
},
},
ast::Node {
value: ast::NodeValue::IntegerLiteral(2),
range: Range {
start: Position::new(0, 4),
end: Position::new(0, 5),
},
},
]),
range: Range {
start: Position::new(0, 0),
end: Position::new(0, 7),
},
},
),
(
r#"[
1,
2,
]"#,
ast::Node {
value: ast::NodeValue::ArrayLiteral(vec![
ast::Node {
value: ast::NodeValue::IntegerLiteral(1),
range: Range {
start: Position::new(1, 20),
end: Position::new(1, 21),
},
},
ast::Node {
value: ast::NodeValue::IntegerLiteral(2),
range: Range {
start: Position::new(2, 20),
end: Position::new(2, 21),
},
},
]),
range: Range {
start: Position::new(0, 0),
end: Position::new(3, 17),
},
},
),
];

for (input, expected) in tests {
let program = parse(input)?;

assert_eq!(program.statements.len(), 1);
assert_eq!(program.statements[0], expected);
}

Ok(())
}

#[test]
fn precedence() -> Result<()> {
let tests = [
Expand All @@ -417,6 +536,7 @@ fn precedence() -> Result<()> {
("-1 + 1 * 2 % 3 / 4", "((-1) + (((1 * 2) % 3) / 4))"),
("1 + -2", "(1 + (-2))"),
("1 * (2 + 3)", "(1 * (2 + 3))"),
("[1 + 2, 3 + 4 * 5]", "[(1 + 2), (3 + (4 * 5))]"),
];

for (input, expected) in tests {
Expand Down

0 comments on commit a525632

Please sign in to comment.