Add tests and clean up

This commit is contained in:
Jeff 2024-08-04 19:25:44 -04:00
parent cc188a233b
commit 5d7122aefa
2 changed files with 107 additions and 55 deletions

View File

@ -1,16 +1,5 @@
use crate::{Identifier, Span, Token};
#[derive(Debug, PartialEq, Clone)]
pub enum LexError {
IntegerParseError(std::num::ParseIntError),
}
impl From<std::num::ParseIntError> for LexError {
fn from(v: std::num::ParseIntError) -> Self {
Self::IntegerParseError(v)
}
}
pub fn lex(input: &str) -> Result<Vec<(Token, Span)>, LexError> {
let mut lexer = Lexer::new(input);
let mut tokens = Vec::new();
@ -130,3 +119,85 @@ impl<'a> Lexer<'a> {
Ok((token, (start_pos, self.position)))
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum LexError {
IntegerParseError(std::num::ParseIntError),
}
impl From<std::num::ParseIntError> for LexError {
fn from(v: std::num::ParseIntError) -> Self {
Self::IntegerParseError(v)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add() {
let input = "1 + 2";
assert_eq!(
lex(input),
Ok(vec![
(Token::Integer(1), (0, 1)),
(Token::Plus, (2, 3)),
(Token::Integer(2), (4, 5)),
(Token::Eof, (5, 5)),
])
)
}
#[test]
fn multiply() {
let input = "1 * 2";
assert_eq!(
lex(input),
Ok(vec![
(Token::Integer(1), (0, 1)),
(Token::Star, (2, 3)),
(Token::Integer(2), (4, 5)),
(Token::Eof, (5, 5)),
])
)
}
#[test]
fn add_and_multiply() {
let input = "1 + 2 * 3";
assert_eq!(
lex(input),
Ok(vec![
(Token::Integer(1), (0, 1)),
(Token::Plus, (2, 3)),
(Token::Integer(2), (4, 5)),
(Token::Star, (6, 7)),
(Token::Integer(3), (8, 9)),
(Token::Eof, (9, 9)),
])
);
}
#[test]
fn assignment() {
let input = "a = 1 + 2 * 3";
assert_eq!(
lex(input,),
Ok(vec![
(Token::Identifier(Identifier::new("a")), (0, 1)),
(Token::Equal, (2, 3)),
(Token::Integer(1), (4, 5)),
(Token::Plus, (6, 7)),
(Token::Integer(2), (8, 9)),
(Token::Star, (10, 11)),
(Token::Integer(3), (12, 13)),
(Token::Eof, (13, 13)),
])
);
}
}

View File

@ -4,6 +4,13 @@ use crate::{
Span, Token, Value,
};
pub fn parse(input: &str) -> Result<(Instruction, Span), ParseError> {
let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer);
parser.parse()
}
#[derive(Debug, PartialEq, Clone)]
pub enum Instruction {
Add(Box<(Instruction, Instruction)>),
@ -13,19 +20,6 @@ pub enum Instruction {
Multiply(Box<(Instruction, Instruction)>),
}
#[derive(Debug, PartialEq, Clone)]
pub enum ParseError {
LexError(LexError),
ExpectedClosingParenthesis,
UnexpectedToken(Token),
}
impl From<LexError> for ParseError {
fn from(v: LexError) -> Self {
Self::LexError(v)
}
}
pub struct Parser<'src> {
lexer: Lexer<'src>,
current: (Token, Span),
@ -137,20 +131,30 @@ impl<'src> Parser<'src> {
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum ParseError {
LexError(LexError),
ExpectedClosingParenthesis,
UnexpectedToken(Token),
}
impl From<LexError> for ParseError {
fn from(v: LexError) -> Self {
Self::LexError(v)
}
}
#[cfg(test)]
mod tests {
use crate::{identifier::Identifier, lex::lex, Value};
use super::{Instruction, Lexer, Parser, Token};
use super::*;
#[test]
fn add() {
let input = "1 + 2";
let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer);
assert_eq!(
parser.parse(),
parse(input),
Ok((
Instruction::Add(Box::new((
Instruction::Constant(Value::integer(1)),
@ -164,11 +168,9 @@ mod tests {
#[test]
fn multiply() {
let input = "1 * 2";
let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer);
assert_eq!(
parser.parse(),
parse(input),
Ok((
Instruction::Multiply(Box::new((
Instruction::Constant(Value::integer(1)),
@ -184,26 +186,7 @@ mod tests {
let input = "1 + 2 * 3";
assert_eq!(
lex(input),
Ok(vec![
(Token::Integer(1), (0, 1)),
(Token::Plus, (2, 3)),
(Token::Integer(2), (4, 5)),
(Token::Star, (6, 7)),
(Token::Integer(3), (8, 9)),
(Token::Eof, (9, 9)),
])
);
}
#[test]
fn parser() {
let input = "1 + 2 * 3";
let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer);
assert_eq!(
parser.parse(),
parse(input),
Ok((
Instruction::Add(Box::new((
Instruction::Constant(Value::integer(1)),
@ -220,11 +203,9 @@ mod tests {
#[test]
fn assignment() {
let input = "a = 1 + 2 * 3";
let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer);
assert_eq!(
parser.parse(),
parse(input),
Ok((
Instruction::Assign(Box::new((
Instruction::Identifier(Identifier::new("a")),