aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/ast/parser.rs9
-rw-r--r--compiler/src/ast/tests.rs136
-rw-r--r--compiler/src/lex/lexer.rs6
-rw-r--r--compiler/src/lex/tests.rs63
-rw-r--r--compiler/src/lex/token.rs1
5 files changed, 2 insertions, 213 deletions
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
119 self.consume(); 119 self.consume();
120 return Err(Spanned::new(Error::UnexpectedRightPar, span)); 120 return Err(Spanned::new(Error::UnexpectedRightPar, span));
121 } 121 }
122 Token::Quote => {
123 self.consume();
124 let quote = Spanned::new(Expr::Atom(Atom::Symbol("quote".into())), span);
125 let expr = self.parse_expr()?;
126 Spanned::new(
127 Expr::List(vec![quote, expr]),
128 Span::new(span.start, self.last_token_span.end),
129 )
130 }
131 Token::Number(number) => { 122 Token::Number(number) => {
132 self.consume(); 123 self.consume();
133 let atom = parse_number(number).map_err(|e| Spanned::new(e, span))?; 124 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 @@
1use std::{fmt::Debug, iter::repeat_n, rc::Rc}; 1use std::{fmt::Debug, iter::repeat_n};
2 2
3use crate::{ 3use crate::{
4 ast::{Atom, Error, Expr, Parser, parser::MAX_DEPTH, tests::E::*}, 4 ast::{Atom, Error, Expr, Parser, parser::MAX_DEPTH, tests::E::*},
@@ -263,53 +263,6 @@ fn test_lists() {
263 } 263 }
264} 264}
265 265
266fn quote(expr: E) -> E {
267 List(vec![Sym("quote"), expr])
268}
269
270#[test]
271fn test_quote() {
272 let cases = vec![
273 // 'x -> (quote x)
274 (vec![Quote, Symbol("x")], vec![quote(Sym("x"))]),
275 // '42 -> (quote 42)
276 (vec![Quote, Number("42")], vec![quote(Int(42))]),
277 // '() -> (quote nil)
278 (vec![Quote, LeftPar, RightPar], vec![quote(Nil)]),
279 // ''x -> (quote (quote x))
280 (
281 vec![Quote, Quote, Symbol("x")],
282 vec![quote(quote(Sym("x")))],
283 ),
284 // '''x -> (quote (quote (quote x)))
285 (
286 vec![Quote, Quote, Quote, Symbol("x")],
287 vec![quote(quote(quote(Sym("x"))))],
288 ),
289 // '(1 2) -> (quote (1 2))
290 (
291 vec![Quote, LeftPar, Number("1"), Number("2"), RightPar],
292 vec![quote(List(vec![Int(1), Int(2)]))],
293 ),
294 // (list 'a 'b) -> (list (quote a) (quote b))
295 (
296 vec![
297 LeftPar,
298 Symbol("list"),
299 Quote,
300 Symbol("a"),
301 Quote,
302 Symbol("b"),
303 RightPar,
304 ],
305 vec![List(vec![Sym("list"), quote(Sym("a")), quote(Sym("b"))])],
306 ),
307 ];
308 for (tokens, expected) in cases {
309 assert_eq!(parse(tokens.clone()), expected, "input: {tokens:?}");
310 }
311}
312
313#[test] 266#[test]
314fn test_top_level() { 267fn test_top_level() {
315 let cases = vec![ 268 let cases = vec![
@@ -344,8 +297,6 @@ fn test_unexpected_right_par() {
344 vec![RightPar], 297 vec![RightPar],
345 vec![Number("1"), RightPar], 298 vec![Number("1"), RightPar],
346 vec![LeftPar, Symbol("a"), RightPar, RightPar], 299 vec![LeftPar, Symbol("a"), RightPar, RightPar],
347 vec![Quote, RightPar],
348 vec![LeftPar, Quote, Quote, RightPar],
349 ]; 300 ];
350 for tokens in cases { 301 for tokens in cases {
351 assert_eq!( 302 assert_eq!(
@@ -373,24 +324,6 @@ fn test_unclosed_left_par() {
373} 324}
374 325
375#[test] 326#[test]
376fn test_unexpected_eof_after_quote() {
377 let cases = vec![
378 vec![Quote],
379 vec![Quote, Quote],
380 vec![Symbol("a"), Quote],
381 vec![LeftPar, Quote],
382 vec![Quote, LeftPar, Quote],
383 ];
384 for tokens in cases {
385 assert_eq!(
386 parse_err(tokens.clone()),
387 Error::UnexpectedEof,
388 "input: {tokens:?}"
389 );
390 }
391}
392
393#[test]
394fn test_invalid_integer() { 327fn test_invalid_integer() {
395 let cases = vec![ 328 let cases = vec![
396 "99999999999999999999", 329 "99999999999999999999",
@@ -553,63 +486,6 @@ fn test_span_empty_list_covers_parens() {
553} 486}
554 487
555#[test] 488#[test]
556fn test_span_quote_atom() {
557 // 'x -> outer = [0..2]; Sym(quote) = [0..1]; x = [1..2]
558 let q = sp((1, 0, 0), (1, 1, 1));
559 let x = sp((1, 1, 1), (1, 2, 2));
560 let tokens = vec![tsp(Quote, q), tsp(Symbol("x"), x)];
561 let prog = parse_sp(tokens.clone());
562
563 assert_eq!(prog[0].span, sp((1, 0, 0), (1, 2, 2)), "input: {tokens:?}");
564
565 if let Expr::List(items) = &prog[0].inner {
566 assert_eq!(
567 items[0].inner,
568 Expr::Atom(Atom::Symbol(Rc::from("quote"))),
569 "input: {tokens:?}",
570 );
571 assert_eq!(items[0].span, q, "input: {tokens:?}");
572 assert_eq!(items[1].span, x, "input: {tokens:?}");
573 } else {
574 panic!("expected list, input: {tokens:?}");
575 }
576}
577
578#[test]
579fn test_span_quote_of_list() {
580 // '(quote x)
581 // 0 1 2..7 8 9 10
582 let q = sp((1, 0, 0), (1, 1, 1));
583 let lp = sp((1, 1, 1), (1, 2, 2));
584 let q_sym = sp((1, 2, 2), (1, 7, 7));
585 let x_sym = sp((1, 8, 8), (1, 9, 9));
586 let rp = sp((1, 9, 9), (1, 10, 10));
587
588 let tokens = vec![
589 tsp(Quote, q),
590 tsp(LeftPar, lp),
591 tsp(Symbol("quote"), q_sym),
592 tsp(Symbol("x"), x_sym),
593 tsp(RightPar, rp),
594 ];
595 let prog = parse_sp(tokens.clone());
596
597 let outer = &prog[0]; // (quote (quote x))
598 assert_eq!(outer.span, sp((1, 0, 0), (1, 10, 10)), "input: {tokens:?}");
599
600 if let Expr::List(items) = &outer.inner {
601 assert_eq!(items[0].span, q, "input: {tokens:?}");
602 assert_eq!(
603 items[1].span,
604 sp((1, 1, 1), (1, 10, 10)),
605 "input: {tokens:?}"
606 );
607 } else {
608 panic!("expected list, input: {tokens:?}");
609 }
610}
611
612#[test]
613fn test_error_span_unexpected_right_par() { 489fn test_error_span_unexpected_right_par() {
614 let s = sp((1, 5, 5), (1, 6, 6)); 490 let s = sp((1, 5, 5), (1, 6, 6));
615 let tokens = vec![tsp(RightPar, s)]; 491 let tokens = vec![tsp(RightPar, s)];
@@ -664,16 +540,6 @@ fn test_error_span_unclosed_left_par_nested() {
664} 540}
665 541
666#[test] 542#[test]
667fn test_error_span_unexpected_eof_after_quote() {
668 let q = sp((1, 0, 0), (1, 1, 1));
669 let tokens = vec![tsp(Quote, q)];
670 let err = parse_sp_err(tokens.clone());
671
672 assert_eq!(err.inner, Error::UnexpectedEof, "input: {tokens:?}");
673 assert_eq!(err.span, q, "input: {tokens:?}");
674}
675
676#[test]
677fn test_error_span_unclosed_string() { 543fn test_error_span_unclosed_string() {
678 let s = sp((1, 0, 0), (1, 7, 7)); 544 let s = sp((1, 0, 0), (1, 7, 7));
679 let tokens = vec![tsp(UnclosedString("oops"), s)]; 545 let tokens = vec![tsp(UnclosedString("oops"), s)];
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::{
4}; 4};
5 5
6fn is_terminator(ch: char) -> bool { 6fn is_terminator(ch: char) -> bool {
7 ch.is_whitespace() || matches!(ch, '(' | ')' | '\'' | '"' | ';') 7 ch.is_whitespace() || matches!(ch, '(' | ')' | '"' | ';')
8} 8}
9 9
10pub struct Lexer<'a> { 10pub struct Lexer<'a> {
@@ -128,10 +128,6 @@ impl<'a> Iterator for Lexer<'a> {
128 self.consume(); 128 self.consume();
129 Token::RightPar 129 Token::RightPar
130 } 130 }
131 '\'' => {
132 self.consume();
133 Token::Quote
134 }
135 131
136 // Number 132 // Number
137 ch if ch.is_ascii_digit() 133 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
@@ -38,24 +38,6 @@ fn test_parens() {
38} 38}
39 39
40#[test] 40#[test]
41fn test_quote() {
42 let cases = vec![
43 ("'", vec![Quote]),
44 ("'a", vec![Quote, Symbol("a")]),
45 ("''a", vec![Quote, Quote, Symbol("a")]),
46 ("'()", vec![Quote, LeftPar, RightPar]),
47 (
48 "'(1 2)",
49 vec![Quote, LeftPar, Number("1"), Number("2"), RightPar],
50 ),
51 ("(' )", vec![LeftPar, Quote, RightPar]),
52 ];
53 for (code, tokens) in cases {
54 assert_eq!(tokenize(code), tokens);
55 }
56}
57
58#[test]
59fn test_numbers() { 41fn test_numbers() {
60 let cases = vec![ 42 let cases = vec![
61 ("0", vec![Number("0")]), 43 ("0", vec![Number("0")]),
@@ -83,7 +65,6 @@ fn test_strings() {
83 (r#""hello""#, vec![String("hello")]), 65 (r#""hello""#, vec![String("hello")]),
84 (r#""hello world""#, vec![String("hello world")]), 66 (r#""hello world""#, vec![String("hello world")]),
85 (r#""(not a list)""#, vec![String("(not a list)")]), 67 (r#""(not a list)""#, vec![String("(not a list)")]),
86 (r#""'not a quote""#, vec![String("'not a quote")]),
87 (r#""; not a comment""#, vec![String("; not a comment")]), 68 (r#""; not a comment""#, vec![String("; not a comment")]),
88 (r#"" spaces ""#, vec![String(" spaces ")]), 69 (r#"" spaces ""#, vec![String(" spaces ")]),
89 ]; 70 ];
@@ -96,7 +77,6 @@ fn test_strings() {
96fn test_string_escapes() { 77fn test_string_escapes() {
97 let cases = vec![ 78 let cases = vec![
98 (r#""line\nbreak""#, vec![String(r"line\nbreak")]), 79 (r#""line\nbreak""#, vec![String(r"line\nbreak")]),
99 (r#""with \"quotes\"""#, vec![String(r#"with \"quotes\""#)]),
100 (r#""\\""#, vec![String(r"\\")]), 80 (r#""\\""#, vec![String(r"\\")]),
101 ("\"single\\\nline\"", vec![String("single\\\nline")]), 81 ("\"single\\\nline\"", vec![String("single\\\nline")]),
102 ]; 82 ];
@@ -169,7 +149,6 @@ fn test_no_separators() {
169 ("(foo)", vec![LeftPar, Symbol("foo"), RightPar]), 149 ("(foo)", vec![LeftPar, Symbol("foo"), RightPar]),
170 ("(1)", vec![LeftPar, Number("1"), RightPar]), 150 ("(1)", vec![LeftPar, Number("1"), RightPar]),
171 ("(a)b", vec![LeftPar, Symbol("a"), RightPar, Symbol("b")]), 151 ("(a)b", vec![LeftPar, Symbol("a"), RightPar, Symbol("b")]),
172 ("'(a)", vec![Quote, LeftPar, Symbol("a"), RightPar]),
173 (r#"("s")"#, vec![LeftPar, String("s"), RightPar]), 152 (r#"("s")"#, vec![LeftPar, String("s"), RightPar]),
174 ]; 153 ];
175 for (code, tokens) in cases { 154 for (code, tokens) in cases {
@@ -212,23 +191,6 @@ fn test_expressions() {
212 vec![LeftPar, Symbol("+"), Number("1"), Number("2"), RightPar], 191 vec![LeftPar, Symbol("+"), Number("1"), Number("2"), RightPar],
213 ), 192 ),
214 ( 193 (
215 "(if (= x 0) 'zero 'nonzero)",
216 vec![
217 LeftPar,
218 Symbol("if"),
219 LeftPar,
220 Symbol("="),
221 Symbol("x"),
222 Number("0"),
223 RightPar,
224 Quote,
225 Symbol("zero"),
226 Quote,
227 Symbol("nonzero"),
228 RightPar,
229 ],
230 ),
231 (
232 r#"(print "hello, world")"#, 194 r#"(print "hello, world")"#,
233 vec![LeftPar, Symbol("print"), String("hello, world"), RightPar], 195 vec![LeftPar, Symbol("print"), String("hello, world"), RightPar],
234 ), 196 ),
@@ -248,17 +210,6 @@ fn test_expressions() {
248 RightPar, 210 RightPar,
249 ], 211 ],
250 ), 212 ),
251 (
252 "'(1 2 3)",
253 vec![
254 Quote,
255 LeftPar,
256 Number("1"),
257 Number("2"),
258 Number("3"),
259 RightPar,
260 ],
261 ),
262 ]; 213 ];
263 for (code, tokens) in cases { 214 for (code, tokens) in cases {
264 assert_eq!(tokenize(code), tokens); 215 assert_eq!(tokenize(code), tokens);
@@ -367,17 +318,3 @@ fn test_span_after_comment() {
367 let s = spans("; cm\nfoo"); 318 let s = spans("; cm\nfoo");
368 assert_eq!(s, vec![(Pos::new(2, 0, 5), Pos::new(2, 3, 8))]); 319 assert_eq!(s, vec![(Pos::new(2, 0, 5), Pos::new(2, 3, 8))]);
369} 320}
370
371#[test]
372fn test_span_after_quote() {
373 // 'hello
374 // 0123456
375 let s = spans("'hello");
376 assert_eq!(
377 s,
378 vec![
379 (Pos::new(1, 0, 0), Pos::new(1, 1, 1)),
380 (Pos::new(1, 1, 1), Pos::new(1, 6, 6))
381 ]
382 );
383}
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 @@
2pub enum Token<'a> { 2pub enum Token<'a> {
3 LeftPar, 3 LeftPar,
4 RightPar, 4 RightPar,
5 Quote,
6 Number(&'a str), 5 Number(&'a str),
7 String(&'a str), 6 String(&'a str),
8 UnclosedString(&'a str), 7 UnclosedString(&'a str),