From 1801afdbd0058cc9cc040b977de0d5652d65aab9 Mon Sep 17 00:00:00 2001 From: Tolmachev Igor Date: Sun, 10 May 2026 12:47:18 +0300 Subject: Remove Quote from parser Dropped to make the language simpler. --- compiler/src/ast/parser.rs | 9 --- compiler/src/ast/tests.rs | 136 +-------------------------------------------- compiler/src/lex/lexer.rs | 6 +- compiler/src/lex/tests.rs | 63 --------------------- compiler/src/lex/token.rs | 1 - 5 files changed, 2 insertions(+), 213 deletions(-) (limited to 'compiler') diff --git a/compiler/src/ast/parser.rs b/compiler/src/ast/parser.rs index 33b36be..bb4e0ce 100644 --- a/compiler/src/ast/parser.rs +++ b/compiler/src/ast/parser.rs @@ -119,15 +119,6 @@ where self.consume(); return Err(Spanned::new(Error::UnexpectedRightPar, span)); } - Token::Quote => { - self.consume(); - let quote = Spanned::new(Expr::Atom(Atom::Symbol("quote".into())), span); - let expr = self.parse_expr()?; - Spanned::new( - Expr::List(vec![quote, expr]), - Span::new(span.start, self.last_token_span.end), - ) - } Token::Number(number) => { self.consume(); let atom = parse_number(number).map_err(|e| Spanned::new(e, span))?; diff --git a/compiler/src/ast/tests.rs b/compiler/src/ast/tests.rs index 8905427..505b075 100644 --- a/compiler/src/ast/tests.rs +++ b/compiler/src/ast/tests.rs @@ -1,4 +1,4 @@ -use std::{fmt::Debug, iter::repeat_n, rc::Rc}; +use std::{fmt::Debug, iter::repeat_n}; use crate::{ ast::{Atom, Error, Expr, Parser, parser::MAX_DEPTH, tests::E::*}, @@ -263,53 +263,6 @@ fn test_lists() { } } -fn quote(expr: E) -> E { - List(vec![Sym("quote"), expr]) -} - -#[test] -fn test_quote() { - let cases = vec![ - // 'x -> (quote x) - (vec![Quote, Symbol("x")], vec![quote(Sym("x"))]), - // '42 -> (quote 42) - (vec![Quote, Number("42")], vec![quote(Int(42))]), - // '() -> (quote nil) - (vec![Quote, LeftPar, RightPar], vec![quote(Nil)]), - // ''x -> (quote (quote x)) - ( - vec![Quote, Quote, Symbol("x")], - vec![quote(quote(Sym("x")))], - ), - // '''x -> (quote (quote (quote x))) - ( - vec![Quote, Quote, Quote, Symbol("x")], - vec![quote(quote(quote(Sym("x"))))], - ), - // '(1 2) -> (quote (1 2)) - ( - vec![Quote, LeftPar, Number("1"), Number("2"), RightPar], - vec![quote(List(vec![Int(1), Int(2)]))], - ), - // (list 'a 'b) -> (list (quote a) (quote b)) - ( - vec![ - LeftPar, - Symbol("list"), - Quote, - Symbol("a"), - Quote, - Symbol("b"), - RightPar, - ], - vec![List(vec![Sym("list"), quote(Sym("a")), quote(Sym("b"))])], - ), - ]; - for (tokens, expected) in cases { - assert_eq!(parse(tokens.clone()), expected, "input: {tokens:?}"); - } -} - #[test] fn test_top_level() { let cases = vec![ @@ -344,8 +297,6 @@ fn test_unexpected_right_par() { vec![RightPar], vec![Number("1"), RightPar], vec![LeftPar, Symbol("a"), RightPar, RightPar], - vec![Quote, RightPar], - vec![LeftPar, Quote, Quote, RightPar], ]; for tokens in cases { assert_eq!( @@ -372,24 +323,6 @@ fn test_unclosed_left_par() { } } -#[test] -fn test_unexpected_eof_after_quote() { - let cases = vec![ - vec![Quote], - vec![Quote, Quote], - vec![Symbol("a"), Quote], - vec![LeftPar, Quote], - vec![Quote, LeftPar, Quote], - ]; - for tokens in cases { - assert_eq!( - parse_err(tokens.clone()), - Error::UnexpectedEof, - "input: {tokens:?}" - ); - } -} - #[test] fn test_invalid_integer() { let cases = vec![ @@ -552,63 +485,6 @@ fn test_span_empty_list_covers_parens() { assert_eq!(prog[0].span, sp((1, 0, 0), (1, 2, 2)), "input: {tokens:?}"); } -#[test] -fn test_span_quote_atom() { - // 'x -> outer = [0..2]; Sym(quote) = [0..1]; x = [1..2] - let q = sp((1, 0, 0), (1, 1, 1)); - let x = sp((1, 1, 1), (1, 2, 2)); - let tokens = vec![tsp(Quote, q), tsp(Symbol("x"), x)]; - let prog = parse_sp(tokens.clone()); - - assert_eq!(prog[0].span, sp((1, 0, 0), (1, 2, 2)), "input: {tokens:?}"); - - if let Expr::List(items) = &prog[0].inner { - assert_eq!( - items[0].inner, - Expr::Atom(Atom::Symbol(Rc::from("quote"))), - "input: {tokens:?}", - ); - assert_eq!(items[0].span, q, "input: {tokens:?}"); - assert_eq!(items[1].span, x, "input: {tokens:?}"); - } else { - panic!("expected list, input: {tokens:?}"); - } -} - -#[test] -fn test_span_quote_of_list() { - // '(quote x) - // 0 1 2..7 8 9 10 - let q = sp((1, 0, 0), (1, 1, 1)); - let lp = sp((1, 1, 1), (1, 2, 2)); - let q_sym = sp((1, 2, 2), (1, 7, 7)); - let x_sym = sp((1, 8, 8), (1, 9, 9)); - let rp = sp((1, 9, 9), (1, 10, 10)); - - let tokens = vec![ - tsp(Quote, q), - tsp(LeftPar, lp), - tsp(Symbol("quote"), q_sym), - tsp(Symbol("x"), x_sym), - tsp(RightPar, rp), - ]; - let prog = parse_sp(tokens.clone()); - - let outer = &prog[0]; // (quote (quote x)) - assert_eq!(outer.span, sp((1, 0, 0), (1, 10, 10)), "input: {tokens:?}"); - - if let Expr::List(items) = &outer.inner { - assert_eq!(items[0].span, q, "input: {tokens:?}"); - assert_eq!( - items[1].span, - sp((1, 1, 1), (1, 10, 10)), - "input: {tokens:?}" - ); - } else { - panic!("expected list, input: {tokens:?}"); - } -} - #[test] fn test_error_span_unexpected_right_par() { let s = sp((1, 5, 5), (1, 6, 6)); @@ -663,16 +539,6 @@ fn test_error_span_unclosed_left_par_nested() { assert_eq!(err.span, inner, "input: {tokens:?}"); } -#[test] -fn test_error_span_unexpected_eof_after_quote() { - let q = sp((1, 0, 0), (1, 1, 1)); - let tokens = vec![tsp(Quote, q)]; - let err = parse_sp_err(tokens.clone()); - - assert_eq!(err.inner, Error::UnexpectedEof, "input: {tokens:?}"); - assert_eq!(err.span, q, "input: {tokens:?}"); -} - #[test] fn test_error_span_unclosed_string() { let s = sp((1, 0, 0), (1, 7, 7)); diff --git a/compiler/src/lex/lexer.rs b/compiler/src/lex/lexer.rs index 801d382..6efbca0 100644 --- a/compiler/src/lex/lexer.rs +++ b/compiler/src/lex/lexer.rs @@ -4,7 +4,7 @@ use crate::{ }; fn is_terminator(ch: char) -> bool { - ch.is_whitespace() || matches!(ch, '(' | ')' | '\'' | '"' | ';') + ch.is_whitespace() || matches!(ch, '(' | ')' | '"' | ';') } pub struct Lexer<'a> { @@ -128,10 +128,6 @@ impl<'a> Iterator for Lexer<'a> { self.consume(); Token::RightPar } - '\'' => { - self.consume(); - Token::Quote - } // Number ch if ch.is_ascii_digit() diff --git a/compiler/src/lex/tests.rs b/compiler/src/lex/tests.rs index 2d872a2..d0ed658 100644 --- a/compiler/src/lex/tests.rs +++ b/compiler/src/lex/tests.rs @@ -37,24 +37,6 @@ fn test_parens() { } } -#[test] -fn test_quote() { - let cases = vec![ - ("'", vec![Quote]), - ("'a", vec![Quote, Symbol("a")]), - ("''a", vec![Quote, Quote, Symbol("a")]), - ("'()", vec![Quote, LeftPar, RightPar]), - ( - "'(1 2)", - vec![Quote, LeftPar, Number("1"), Number("2"), RightPar], - ), - ("(' )", vec![LeftPar, Quote, RightPar]), - ]; - for (code, tokens) in cases { - assert_eq!(tokenize(code), tokens); - } -} - #[test] fn test_numbers() { let cases = vec![ @@ -83,7 +65,6 @@ fn test_strings() { (r#""hello""#, vec![String("hello")]), (r#""hello world""#, vec![String("hello world")]), (r#""(not a list)""#, vec![String("(not a list)")]), - (r#""'not a quote""#, vec![String("'not a quote")]), (r#""; not a comment""#, vec![String("; not a comment")]), (r#"" spaces ""#, vec![String(" spaces ")]), ]; @@ -96,7 +77,6 @@ fn test_strings() { fn test_string_escapes() { let cases = vec![ (r#""line\nbreak""#, vec![String(r"line\nbreak")]), - (r#""with \"quotes\"""#, vec![String(r#"with \"quotes\""#)]), (r#""\\""#, vec![String(r"\\")]), ("\"single\\\nline\"", vec![String("single\\\nline")]), ]; @@ -169,7 +149,6 @@ fn test_no_separators() { ("(foo)", vec![LeftPar, Symbol("foo"), RightPar]), ("(1)", vec![LeftPar, Number("1"), RightPar]), ("(a)b", vec![LeftPar, Symbol("a"), RightPar, Symbol("b")]), - ("'(a)", vec![Quote, LeftPar, Symbol("a"), RightPar]), (r#"("s")"#, vec![LeftPar, String("s"), RightPar]), ]; for (code, tokens) in cases { @@ -211,23 +190,6 @@ fn test_expressions() { "(+ 1 2)", vec![LeftPar, Symbol("+"), Number("1"), Number("2"), RightPar], ), - ( - "(if (= x 0) 'zero 'nonzero)", - vec![ - LeftPar, - Symbol("if"), - LeftPar, - Symbol("="), - Symbol("x"), - Number("0"), - RightPar, - Quote, - Symbol("zero"), - Quote, - Symbol("nonzero"), - RightPar, - ], - ), ( r#"(print "hello, world")"#, vec![LeftPar, Symbol("print"), String("hello, world"), RightPar], @@ -248,17 +210,6 @@ fn test_expressions() { RightPar, ], ), - ( - "'(1 2 3)", - vec![ - Quote, - LeftPar, - Number("1"), - Number("2"), - Number("3"), - RightPar, - ], - ), ]; for (code, tokens) in cases { assert_eq!(tokenize(code), tokens); @@ -367,17 +318,3 @@ fn test_span_after_comment() { let s = spans("; cm\nfoo"); assert_eq!(s, vec![(Pos::new(2, 0, 5), Pos::new(2, 3, 8))]); } - -#[test] -fn test_span_after_quote() { - // 'hello - // 0123456 - let s = spans("'hello"); - assert_eq!( - s, - vec![ - (Pos::new(1, 0, 0), Pos::new(1, 1, 1)), - (Pos::new(1, 1, 1), Pos::new(1, 6, 6)) - ] - ); -} diff --git a/compiler/src/lex/token.rs b/compiler/src/lex/token.rs index 2d07885..910c8ff 100644 --- a/compiler/src/lex/token.rs +++ b/compiler/src/lex/token.rs @@ -2,7 +2,6 @@ pub enum Token<'a> { LeftPar, RightPar, - Quote, Number(&'a str), String(&'a str), UnclosedString(&'a str), -- cgit v1.3