From 803e1083bf0ec4ad9e4b4f7b6bd12587784955cb Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Wed, 4 Jan 2017 19:21:02 -0500 Subject: [PATCH] Add quasiquote with ` --- src/parser.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/parser.rs b/src/parser.rs index 2041cf6..f58743a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -200,6 +200,19 @@ pub fn parse_expression(input: &str, start_loc: usize) -> ParseResult err, } } + Some('`') => { + 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("quasiquote".into(), quote_span), + result], + quote_span.union(&span))) + } + err => err, + } + } Some(_) => parse_symbol(input, start_loc), None => unreachable!(), } @@ -480,8 +493,45 @@ mod test { Sexp::Int(3, (7, 8)), ], (2, 9)), ], (0, 9)))); + 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_expr_quasiquote() { + assert_eq!(parse_expression("`a", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("quasiquote".into(), (0, 1)), + Sexp::Sym("a".into(), (1, 2)), + ], (0, 2)))); + assert_eq!(parse_expression("`1", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("quasiquote".into(), (0, 1)), + Sexp::Int(1, (1, 2)), + ], (0, 2)))); + assert_eq!(parse_expression("` (1 2 3)", 0), + Done("", Sexp::List(vec![ + Sexp::Sym("quasiquote".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("quote".into(), (1, 2)), + Sexp::Sym("a".into(), (2, 3)), + ], (1, 3)), + ], (0, 3)))); + + assert_eq!(parse_expression("`", 0), + Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (1, 1)))); } #[test] -- 2.43.2