Add list parsing

This commit is contained in:
Jeff 2024-08-04 21:31:18 -04:00
parent bd491c014d
commit 161e99a2dd
3 changed files with 97 additions and 6 deletions

View File

@ -65,6 +65,18 @@ impl<'a> Lexer<'a> {
self.position += 1;
(Token::Equal, (self.position - 1, self.position))
}
'[' => {
self.position += 1;
(Token::LeftSquareBrace, (self.position - 1, self.position))
}
']' => {
self.position += 1;
(Token::RightSquareBrace, (self.position - 1, self.position))
}
',' => {
self.position += 1;
(Token::Comma, (self.position - 1, self.position))
}
_ => (Token::Eof, (self.position, self.position)),
}
} else {
@ -165,6 +177,20 @@ impl From<ParseIntError> for LexError {
mod tests {
use super::*;
#[test]
fn square_braces() {
let input = "[]";
assert_eq!(
lex(input),
Ok(vec![
(Token::LeftSquareBrace, (0, 1)),
(Token::RightSquareBrace, (1, 2)),
(Token::Eof, (2, 2)),
])
)
}
#[test]
fn small_float() {
let input = "1.23";

View File

@ -29,6 +29,7 @@ pub enum Operation {
Assign(Box<(Instruction, Instruction)>),
Constant(Value),
Identifier(Identifier),
List(Vec<Instruction>),
Multiply(Box<(Instruction, Instruction)>),
}
@ -137,7 +138,41 @@ impl<'src> Parser<'src> {
(left_span.0, right_span.1),
))
} else {
Err(ParseError::ExpectedClosingParenthesis)
Err(ParseError::ExpectedClosingParenthesis {
actual: self.current.0.clone(),
span: self.current.1,
})
}
}
(Token::LeftSquareBrace, left_span) => {
self.next_token()?;
let mut instructions = Vec::new();
loop {
if let (Token::RightSquareBrace, right_span) = self.current {
self.next_token()?;
return Ok(Instruction::new(
Operation::List(instructions),
(left_span.0, right_span.1),
));
}
if let (Token::Comma, _) = self.current {
self.next_token()?;
continue;
}
if let Ok(instruction) = self.parse_instruction(0) {
instructions.push(instruction);
} else {
return Err(ParseError::ExpectedClosingSquareBrace {
actual: self.current.0.clone(),
span: self.current.1,
});
}
}
}
_ => Err(ParseError::UnexpectedToken(self.current.0.clone())),
@ -145,10 +180,10 @@ impl<'src> Parser<'src> {
}
fn current_precedence(&self) -> u8 {
match self.current {
(Token::Equal, _) => 3,
(Token::Plus, _) => 1,
(Token::Star, _) => 2,
match self.current.0 {
Token::Equal => 3,
Token::Plus => 1,
Token::Star => 2,
_ => 0,
}
}
@ -156,8 +191,9 @@ impl<'src> Parser<'src> {
#[derive(Debug, PartialEq, Clone)]
pub enum ParseError {
ExpectedClosingParenthesis { actual: Token, span: Span },
ExpectedClosingSquareBrace { actual: Token, span: Span },
LexError(LexError),
ExpectedClosingParenthesis,
UnexpectedToken(Token),
}
@ -172,6 +208,32 @@ mod tests {
use super::*;
#[test]
fn list() {
let input = "[1, 2]";
assert_eq!(
parse(input),
Ok(Instruction::new(
Operation::List(vec![
Instruction::new(Operation::Constant(Value::integer(1)), (1, 2)),
Instruction::new(Operation::Constant(Value::integer(2)), (4, 5)),
]),
(0, 6)
))
);
}
#[test]
fn empty_list() {
let input = "[]";
assert_eq!(
parse(input),
Ok(Instruction::new(Operation::List(vec![]), (0, 2)))
);
}
#[test]
fn float() {
let input = "42.0";

View File

@ -2,6 +2,7 @@ use crate::Identifier;
#[derive(Debug, PartialEq, Clone)]
pub enum Token {
Comma,
Eof,
Equal,
Identifier(Identifier),
@ -10,5 +11,7 @@ pub enum Token {
Star,
LeftParenthesis,
RightParenthesis,
LeftSquareBrace,
RightSquareBrace,
Float(f64),
}