Add tests and clean up
This commit is contained in:
parent
cc188a233b
commit
5d7122aefa
@ -1,16 +1,5 @@
|
|||||||
use crate::{Identifier, Span, Token};
|
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> {
|
pub fn lex(input: &str) -> Result<Vec<(Token, Span)>, LexError> {
|
||||||
let mut lexer = Lexer::new(input);
|
let mut lexer = Lexer::new(input);
|
||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
@ -130,3 +119,85 @@ impl<'a> Lexer<'a> {
|
|||||||
Ok((token, (start_pos, self.position)))
|
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,
|
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)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Add(Box<(Instruction, Instruction)>),
|
Add(Box<(Instruction, Instruction)>),
|
||||||
@ -13,19 +20,6 @@ pub enum Instruction {
|
|||||||
Multiply(Box<(Instruction, 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> {
|
pub struct Parser<'src> {
|
||||||
lexer: Lexer<'src>,
|
lexer: Lexer<'src>,
|
||||||
current: (Token, Span),
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{identifier::Identifier, lex::lex, Value};
|
|
||||||
|
|
||||||
use super::{Instruction, Lexer, Parser, Token};
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add() {
|
fn add() {
|
||||||
let input = "1 + 2";
|
let input = "1 + 2";
|
||||||
let lexer = Lexer::new(input);
|
|
||||||
let mut parser = Parser::new(lexer);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parser.parse(),
|
parse(input),
|
||||||
Ok((
|
Ok((
|
||||||
Instruction::Add(Box::new((
|
Instruction::Add(Box::new((
|
||||||
Instruction::Constant(Value::integer(1)),
|
Instruction::Constant(Value::integer(1)),
|
||||||
@ -164,11 +168,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn multiply() {
|
fn multiply() {
|
||||||
let input = "1 * 2";
|
let input = "1 * 2";
|
||||||
let lexer = Lexer::new(input);
|
|
||||||
let mut parser = Parser::new(lexer);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parser.parse(),
|
parse(input),
|
||||||
Ok((
|
Ok((
|
||||||
Instruction::Multiply(Box::new((
|
Instruction::Multiply(Box::new((
|
||||||
Instruction::Constant(Value::integer(1)),
|
Instruction::Constant(Value::integer(1)),
|
||||||
@ -184,26 +186,7 @@ mod tests {
|
|||||||
let input = "1 + 2 * 3";
|
let input = "1 + 2 * 3";
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lex(input),
|
parse(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(),
|
|
||||||
Ok((
|
Ok((
|
||||||
Instruction::Add(Box::new((
|
Instruction::Add(Box::new((
|
||||||
Instruction::Constant(Value::integer(1)),
|
Instruction::Constant(Value::integer(1)),
|
||||||
@ -220,11 +203,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn assignment() {
|
fn assignment() {
|
||||||
let input = "a = 1 + 2 * 3";
|
let input = "a = 1 + 2 * 3";
|
||||||
let lexer = Lexer::new(input);
|
|
||||||
let mut parser = Parser::new(lexer);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parser.parse(),
|
parse(input),
|
||||||
Ok((
|
Ok((
|
||||||
Instruction::Assign(Box::new((
|
Instruction::Assign(Box::new((
|
||||||
Instruction::Identifier(Identifier::new("a")),
|
Instruction::Identifier(Identifier::new("a")),
|
||||||
|
Loading…
Reference in New Issue
Block a user