diff options
| author | Tolmachev Igor <me@igorek.dev> | 2026-05-10 12:47:18 +0300 |
|---|---|---|
| committer | Tolmachev Igor <me@igorek.dev> | 2026-05-10 12:47:37 +0300 |
| commit | 1801afdbd0058cc9cc040b977de0d5652d65aab9 (patch) | |
| tree | fafafb12e7d877f506e022ecb282e66cecb72bdc /compiler/src/ast | |
| parent | 160b64427d79290a59ac48c9babca064232d8dfd (diff) | |
| download | crisp-1801afdbd0058cc9cc040b977de0d5652d65aab9.tar.gz crisp-1801afdbd0058cc9cc040b977de0d5652d65aab9.zip | |
Remove Quote from parser
Dropped to make the language simpler.
Diffstat (limited to 'compiler/src/ast')
| -rw-r--r-- | compiler/src/ast/parser.rs | 9 | ||||
| -rw-r--r-- | compiler/src/ast/tests.rs | 136 |
2 files changed, 1 insertions, 144 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 @@ | |||
| 1 | use std::{fmt::Debug, iter::repeat_n, rc::Rc}; | 1 | use std::{fmt::Debug, iter::repeat_n}; |
| 2 | 2 | ||
| 3 | use crate::{ | 3 | use 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 | ||
| 266 | fn quote(expr: E) -> E { | ||
| 267 | List(vec![Sym("quote"), expr]) | ||
| 268 | } | ||
| 269 | |||
| 270 | #[test] | ||
| 271 | fn 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] |
| 314 | fn test_top_level() { | 267 | fn 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] |
| 376 | fn 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] | ||
| 394 | fn test_invalid_integer() { | 327 | fn 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] |
| 556 | fn 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] | ||
| 579 | fn 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] | ||
| 613 | fn test_error_span_unexpected_right_par() { | 489 | fn 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] |
| 667 | fn 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] | ||
| 677 | fn test_error_span_unclosed_string() { | 543 | fn 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)]; |
