From 3c8b9d7ff28aca1a304c0648ee4289482eb125ac Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Wed, 4 Jan 2017 19:26:19 -0500 Subject: [PATCH] Add unquote on , and unquote-splicing on ,@ --- src/parser.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/parser.rs b/src/parser.rs index f58743a..d03ebb5 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -213,6 +213,35 @@ pub fn parse_expression(input: &str, start_loc: usize) -> ParseResult err, } } + Some(',') => { + if input[1..].chars().next() == Some('@') { + match parse_expression(&input[2..], start_loc + 2) { + Done(rest, result) => { + let span = *result.get_loc(); + let quote_span = (0, 2).offset(start_loc); + Done(rest, + Sexp::List(vec![ + Sexp::Sym("unquote-splicing".into(), quote_span), + result + ], quote_span.union(&span))) + } + err => err, + } + } else { + match parse_expression(&input[1..], start_loc + 1) { + Done(rest, result) => { + let span = *result.get_loc(); + let quote_span = (0, 1).offset(start_loc); + Done(rest, + Sexp::List(vec![ + Sexp::Sym("unquote".into(), quote_span), + result + ], quote_span.union(&span))) + } + err => err, + } + } + } Some(_) => parse_symbol(input, start_loc), None => unreachable!(), } @@ -534,6 +563,52 @@ mod test { Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (1, 1)))); } + #[test] + fn test_parse_expr_unquote() { + assert_eq!(parse_expression(",a", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("unquote".into(), (0, 1)), + Sexp::Sym("a".into(), (1, 2)), + ], (0, 2)))); + assert_eq!(parse_expression(",1", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("unquote".into(), (0, 1)), + Sexp::Int(1, (1, 2)), + ], (0, 2)))); + assert_eq!(parse_expression(", (1 2 3)", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("unquote".into(), (0, 1)), + Sexp::List(vec![ + Sexp::Int(1, (3, 4)), + Sexp::Int(2, (5, 6)), + Sexp::Int(3, (7, 8)), + ], (2, 9)), + ], (0, 9)))); + assert_eq!(parse_expression("`,a", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("quasiquote".into(), (0, 1)), + Sexp::List(vec![ + Sexp::Sym("unquote".into(), (1, 2)), + Sexp::Sym("a".into(), (2, 3)), + ], (1, 3)), + ], (0, 3)))); + assert_eq!(parse_expression("`(,@a)", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("quasiquote".into(), (0, 1)), + Sexp::List(vec![ + Sexp::List(vec![ + Sexp::Sym("unquote-splicing".into(), (2, 4)), + Sexp::Sym("a".into(), (4, 5)), + ], (2, 5)), + ], (1, 6)), + ], (0, 6)))); + + assert_eq!(parse_expression(",", 0), + Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (1, 1)))); + assert_eq!(parse_expression(",@", 0), + Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (2, 2)))); + } + #[test] fn test_parse_list() { assert_eq!(parse_list("()", 0), -- 2.43.2