Add tests and clean up
This commit is contained in:
parent
cc188a233b
commit
5d7122aefa
@ -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)),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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")),
|
||||
|
Loading…
Reference in New Issue
Block a user