diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-07-30 17:46:23 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-07-30 17:46:23 +0300 |
commit | d2d4d5cffdce0ce28e59732f56a771f8fc3431de (patch) | |
tree | b3c84baa1208064632572a19a734c6f6c5240dfe /src/parse/parsetree.rs | |
parent | 69bcc7d4d306d1c8a7596ae13641ffe479d98dcc (diff) | |
download | myslip-d2d4d5cffdce0ce28e59732f56a771f8fc3431de.tar.gz myslip-d2d4d5cffdce0ce28e59732f56a771f8fc3431de.zip |
Added tests for tokens_to_ast
Diffstat (limited to 'src/parse/parsetree.rs')
-rw-r--r-- | src/parse/parsetree.rs | 140 |
1 files changed, 139 insertions, 1 deletions
diff --git a/src/parse/parsetree.rs b/src/parse/parsetree.rs index 560ebe7..6d59cf1 100644 --- a/src/parse/parsetree.rs +++ b/src/parse/parsetree.rs @@ -4,11 +4,12 @@ use nom::{ Parser, branch::alt, multi::many0, - combinator::all_consuming, bytes::complete::{tag, take_while1}, character::complete::multispace1, }; +use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*}; + #[derive(Debug,PartialEq)] pub enum Token { @@ -40,6 +41,12 @@ fn tokenize(s: &str) -> Result<Vec<Token>, String> { } } + +fn tokens_to_ast(tokens: Vec<Token>) -> Result<SExp, String> { + todo!() +} + + #[cfg(test)] mod private_parsing_tests { use super::{*, parse_token}; @@ -76,4 +83,135 @@ mod private_parsing_tests { ); } + #[test] + fn test_tokens_to_ast() { + // Syms are parsed to vars, + // and everything is wrapped in an extra layer of scons + // so that multi-expression programs can be returned + // as one single SExp. + assert_eq!( + tokens_to_ast(vec![sym("a")]), + Ok(scons(var("a"), Nil)) + ); + + // Lists are pased to scons linked lists + assert_eq!( + tokens_to_ast(vec![ + ParOpen, + sym("a"), whitespace(" "), + sym("b"), whitespace(" "), + sym("c"), whitespace(" "), + ParClose, + ]), + Ok(scons(scons(var("a"), scons(var("b"), scons(var("c"), Nil))), Nil)) + ); + + // Nesting should work. + assert_eq!( + tokens_to_ast(vec![ + ParOpen, + sym("a"), whitespace(" "), + ParOpen, + sym("b"), whitespace(" "), + sym("c"), whitespace(" "), + ParClose, whitespace(" "), + sym("d"), + ParClose + ]), + Ok( + scons(scons(var("a"), scons( + scons(var("b"), scons(var("c"), Nil)) + , scons(var("d"), Nil))), Nil) + ) + ); + + // Multiple expressions should be parseable + assert_eq!( + tokens_to_ast(vec![ + ParOpen, + sym("a"), + ParClose, + sym("b"), + ParOpen, + sym("c"), + ParClose, + ]), + Ok(scons( + scons(var("a"), Nil), + scons(var("b"), + scons(scons(var("c"), Nil), Nil)))) + ); + + // Operators are parsed correctly + assert_eq!( + tokens_to_ast(vec![ + ParOpen, + sym("+"), whitespace(" "), + sym("-"), whitespace(" "), + sym("*"), whitespace(" "), + sym("/"), + ParClose + ]), + Ok(scons( + scons(Add, + scons(Sub, + scons(Mul, + scons(Div, + Nil)))), Nil)) + ); + + // Integers are parsed correctly + assert_eq!( + tokens_to_ast(vec![Num(5)]), + Ok(scons(Int(5), Nil)) + ); + + // Nil can be parsed + assert_eq!( + tokens_to_ast(vec![ParOpen,ParClose]), + Ok(scons(Nil, Nil)) + ); + + // Quote can be parsed + assert_eq!( + tokens_to_ast(vec![ + ParOpen, + sym("quote"), whitespace(" "), + sym("a"), whitespace(" "), + sym("b"), whitespace(" ") + ]), + Ok(scons(Quote, scons(var("a"), scons(var("b"), Nil)))) + ); + } + + #[test] + fn test_tokens_to_ast_failing() { + assert!( + tokens_to_ast(vec![ParClose]).is_err(), + "Invalid parentheses should fail" + ); + assert!( + tokens_to_ast(vec![ParOpen]).is_err(), + "Invalid parentheses should fail" + ); + assert!( + tokens_to_ast(vec![ParClose, ParOpen]).is_err(), + "Invalid parentheses should fail" + ); + assert!( + tokens_to_ast(vec![ParOpen, ParOpen, ParClose]).is_err(), + "Invalid parentheses should fail" + ); + + assert!( + tokens_to_ast(vec![Num(1), sym("a")]).is_err(), + "Having a symbol starting with a number should fail." + ); + + assert!( + tokens_to_ast(vec![sym("quote"), sym("a")]).is_err(), + "There should be whitespace between quote and other symbols" + ); + } + } |