From ecf54b84962360cd464ea69aa5a71963f5785cc7 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Fri, 5 Jun 2020 13:36:11 +0200 Subject: [PATCH] Set up foundation for parser unit testing and added test_var() and test_precedence() tests. --- kalk/src/ast.rs | 4 +-- kalk/src/lexer.rs | 4 +-- kalk/src/parser.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/kalk/src/ast.rs b/kalk/src/ast.rs index d9b4e25..93347e4 100644 --- a/kalk/src/ast.rs +++ b/kalk/src/ast.rs @@ -2,14 +2,14 @@ use crate::lexer::TokenKind; use crate::parser::Unit; use std::mem; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Stmt { VarDecl(String, Box), FnDecl(String, Vec, Box), Expr(Box), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Expr { Binary(Box, TokenKind, Box), Unary(TokenKind, Box), diff --git a/kalk/src/lexer.rs b/kalk/src/lexer.rs index 970d15a..63e4574 100644 --- a/kalk/src/lexer.rs +++ b/kalk/src/lexer.rs @@ -1,6 +1,6 @@ use std::str; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum TokenKind { Unknown, Literal, @@ -25,7 +25,7 @@ pub enum TokenKind { EOF, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Token { pub kind: TokenKind, pub value: String, diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index 6250a43..5e5cd81 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -7,7 +7,6 @@ use crate::{ use rug::Float; pub struct Context { - //angle_unit: Unit, tokens: Vec, pos: usize, symbol_table: SymbolTable, @@ -300,3 +299,81 @@ fn consume<'a>(context: &'a mut Context, kind: TokenKind) -> Result<&'a Token, S fn is_at_end(context: &mut Context) -> bool { context.pos >= context.tokens.len() || compare_enums(&peek(context).kind, &TokenKind::EOF) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::lexer::{Token, TokenKind::*}; + + fn parse(tokens: Vec) -> Stmt { + let mut context = Context::new(); + context.tokens = tokens; + + parse_stmt(&mut context).unwrap() + } + + fn token(kind: TokenKind, value: &str) -> Token { + Token { + kind, + value: value.into(), + } + } + + fn literal(value: &str) -> Box { + Box::new(Expr::Literal(value.into())) + } + + fn var(identifier: &str) -> Box { + Box::new(Expr::Var(identifier.into())) + } + + fn binary(left: Box, op: TokenKind, right: Box) -> Box { + Box::new(Expr::Binary(left, op, right)) + } + fn group(expr: Box) -> Box { + Box::new(Expr::Group(expr)) + } + + #[test] + fn test_var() { + // x + let tokens = vec![token(Identifier, "x"), token(EOF, "")]; + + assert_eq!(parse(tokens), Stmt::Expr(var("x"))); + } + + #[test] + fn test_precedence() { + // 1+2*(3-4/5) + let tokens = vec![ + token(Literal, "1"), + token(Plus, ""), + token(Literal, "2"), + token(Star, ""), + token(OpenParenthesis, ""), + token(Literal, "3"), + token(Minus, ""), + token(Literal, "4"), + token(Slash, ""), + token(Literal, "5"), + token(ClosedParenthesis, ""), + ]; + + assert_eq!( + parse(tokens), + Stmt::Expr(binary( + literal("1"), + Plus, + binary( + literal("2"), + Star, + group(binary( + literal("3"), + Minus, + binary(literal("4"), Slash, literal("5")) + )) + ) + )) + ); + } +}