1use std::{
2 borrow::Cow,
3 path::PathBuf,
4 rc::Rc,
5 result,
6 sync::atomic::{AtomicUsize, Ordering},
7};
8
9use serde::{Deserialize, Serialize};
10
11use crate::{
12 ast::{
13 self, parse_begin, parse_define, parse_if, parse_lambda, parse_let, parse_new_let,
14 parse_require, parse_set, parse_single_argument, Atom, ExprKind, List, Macro, PatternPair,
15 SyntaxRules, Vector, BEGIN, DEFINE, IF, LAMBDA, LAMBDA_FN, LAMBDA_SYMBOL, LET, PLAIN_LET,
16 QUASIQUOTE, QUASISYNTAX, QUOTE, RAW_UNQUOTE, RAW_UNQUOTE_SPLICING, RAW_UNSYNTAX,
17 RAW_UNSYNTAX_SPLICING, REQUIRE, RETURN, SET, SYNTAX_QUOTE, UNQUOTE, UNQUOTE_SPLICING,
18 },
19 interner::InternedString,
20 lexer::{OwnedTokenStream, ToOwnedString, TokenStream},
21 span::Span,
22 tokens::{Paren, ParenMod, Token, TokenType},
23};
24
25#[derive(
26 Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
27)]
28#[repr(C)]
29pub struct SourceId(pub u32);
30
31impl SourceId {
32 pub const fn none() -> Option<Self> {
33 None
34 }
35}
36
37pub static SYNTAX_OBJECT_ID: AtomicUsize = AtomicUsize::new(0);
39
40#[derive(
45 Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
46)]
47pub struct SyntaxObjectId(pub u32);
48
49impl SyntaxObjectId {
50 #[inline]
51 pub fn fresh() -> Self {
52 SyntaxObjectId(SYNTAX_OBJECT_ID.fetch_add(1, Ordering::Relaxed) as _)
53 }
60}
61
62impl From<SyntaxObjectId> for u32 {
63 fn from(value: SyntaxObjectId) -> Self {
64 value.0
65 }
66}
67
68impl std::fmt::Display for SyntaxObjectId {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 write!(f, "{self:?}")
71 }
72}
73
74#[derive(
75 Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
76)]
77pub struct ListId(usize);
78
79#[derive(
80 Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
81)]
82pub struct FunctionId(usize);
83
84#[derive(Serialize, Deserialize)]
90pub struct RawSyntaxObject<T> {
91 pub ty: T,
92 pub span: Span,
93 pub syntax_object_id: SyntaxObjectId,
94 pub unresolved: bool,
129 pub introduced_via_macro: bool,
130}
131
132impl<T: Clone> Clone for RawSyntaxObject<T> {
133 fn clone(&self) -> Self {
134 Self {
135 ty: self.ty.clone(),
136 span: self.span,
137 syntax_object_id: SyntaxObjectId::fresh(),
138 unresolved: self.unresolved,
139 introduced_via_macro: self.introduced_via_macro,
140 }
141 }
142}
143
144impl<T: std::fmt::Debug> std::fmt::Debug for RawSyntaxObject<T> {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 f.debug_struct("RawSyntaxObject")
147 .field("ty", &self.ty)
148 .field("span", &self.span)
149 .finish()
150 }
151}
152
153impl<T: std::hash::Hash> std::hash::Hash for RawSyntaxObject<T> {
156 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
157 self.ty.hash(state);
158 self.span.hash(state);
159 }
160}
161
162pub type SyntaxObject = RawSyntaxObject<TokenType<InternedString>>;
163
164impl PartialEq for SyntaxObject {
165 fn eq(&self, other: &Self) -> bool {
166 self.ty == other.ty
167 }
168}
169
170impl SyntaxObject {
171 pub fn new(ty: TokenType<InternedString>, span: Span) -> Self {
172 SyntaxObject {
173 ty,
174 span,
175 syntax_object_id: SyntaxObjectId::fresh(),
177 unresolved: false,
178 introduced_via_macro: false,
179 }
180 }
181
182 pub fn default(ty: TokenType<InternedString>) -> Self {
183 SyntaxObject {
184 ty,
185 span: Span::new(0, 0, SourceId::none()),
186 syntax_object_id: SyntaxObjectId::fresh(),
188 unresolved: false,
189 introduced_via_macro: false,
190 }
191 }
192
193 pub fn set_span(&mut self, span: Span) {
194 self.span = span
195 }
196
197 pub fn from_token_with_source(
198 val: &Token<'_, InternedString>,
199 _source: &Option<Rc<PathBuf>>,
200 ) -> Self {
201 SyntaxObject {
202 ty: val.ty.clone(),
203 span: val.span,
204 syntax_object_id: SyntaxObjectId::fresh(),
205 unresolved: false,
206 introduced_via_macro: false,
207 }
208 }
209}
210
211impl From<&Token<'_, InternedString>> for SyntaxObject {
212 fn from(val: &Token<'_, InternedString>) -> SyntaxObject {
213 SyntaxObject::new(val.ty.clone(), val.span)
214 }
215}
216
217#[derive(Clone, Debug, PartialEq)]
218pub enum ParseError {
219 Unexpected(TokenType<String>, Span, Option<Rc<PathBuf>>),
220 UnexpectedEOF(Option<Rc<PathBuf>>),
221 UnexpectedChar(char, Span, Option<Rc<PathBuf>>),
222 IncompleteString(String, Span, Option<Rc<PathBuf>>),
223 SyntaxError(String, Span, Option<Rc<PathBuf>>),
224 ArityMismatch(String, Span, Option<Rc<PathBuf>>),
225}
226
227impl std::fmt::Display for ParseError {
228 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229 match self {
230 ParseError::Unexpected(l, _, _) => write!(f, "Parse: Unexpected token: {:?}", l),
231 ParseError::UnexpectedEOF(_) => write!(f, "Parse: Unexpected EOF"),
232 ParseError::UnexpectedChar(l, _, _) => {
233 write!(f, "Parse: Unexpected character: {:?}", l)
234 }
235 ParseError::IncompleteString(l, _, _) => write!(f, "Parse: Incomplete String: {}", l),
236 ParseError::SyntaxError(l, _, _) => write!(f, "Parse: Syntax Error: {}", l),
237 ParseError::ArityMismatch(l, _, _) => write!(f, "Parse: Arity mismatch: {}", l),
238 }
239 }
240}
241
242impl std::error::Error for ParseError {}
243
244impl ParseError {
245 pub fn span(&self) -> Option<Span> {
246 match self {
247 ParseError::Unexpected(_, s, _) => Some(*s),
249 ParseError::UnexpectedEOF(_) => None,
250 ParseError::UnexpectedChar(_, s, _) => Some(*s),
251 ParseError::IncompleteString(_, s, _) => Some(*s),
252 ParseError::SyntaxError(_, s, _) => Some(*s),
253 ParseError::ArityMismatch(_, s, _) => Some(*s),
254 }
255 }
256
257 pub fn set_source(self, source: Option<Rc<PathBuf>>) -> Self {
258 use ParseError::*;
259 match self {
260 ParseError::Unexpected(l, s, _) => Unexpected(l, s, source),
261 ParseError::UnexpectedEOF(_) => UnexpectedEOF(source),
262 ParseError::UnexpectedChar(l, s, _) => UnexpectedChar(l, s, source),
263 ParseError::IncompleteString(l, s, _) => IncompleteString(l, s, source),
264 ParseError::SyntaxError(l, s, _) => SyntaxError(l, s, source),
265 ParseError::ArityMismatch(l, s, _) => ArityMismatch(l, s, source),
266 }
267 }
268}
269
270pub struct InternString;
271
272impl ToOwnedString<InternedString> for InternString {
273 fn own(&self, s: Cow<str>) -> InternedString {
274 (&*s).into()
275 }
276}
277
278pub struct Parser<'a> {
280 tokenizer: OwnedTokenStream<'a, InternedString, InternString>,
281 quote_stack: Vec<usize>,
282 quasiquote_depth: isize,
283 quote_context: bool,
284 shorthand_quote_stack: Vec<usize>,
285 source_name: Option<Rc<PathBuf>>,
286 context: Vec<ParsingContext>,
287 comment_buffer: Vec<&'a str>,
288 collecting_comments: bool,
289 keep_lists: bool,
290}
291
292#[derive(Debug, Copy, Clone, PartialEq)]
293enum ParsingContext {
294 Quote(usize),
296 QuoteTick(usize),
298 Unquote(usize),
300 UnquoteTick(usize),
302 Quasiquote(usize),
304 QuasiquoteTick(usize),
306 UnquoteSplicing(usize),
308 UnquoteSplicingTick(usize),
310}
311
312impl<'a> Parser<'a> {
313 pub fn parse(expr: &str) -> Result<Vec<ExprKind>> {
314 Parser::new(expr, SourceId::none()).collect()
315 }
316
317 pub fn parse_without_lowering(expr: &str) -> Result<Vec<ExprKind>> {
318 Parser::new(expr, SourceId::none())
319 .without_lowering()
320 .collect()
321 }
322
323 pub fn offset(&self) -> usize {
324 self.tokenizer.offset()
325 }
326}
327
328pub type Result<T> = result::Result<T, ParseError>;
329
330fn tokentype_error_to_parse_error(t: &Token<'_, InternedString>) -> ParseError {
331 if let TokenType::Error = t.ty {
332 if t.source.starts_with('\"') {
333 ParseError::IncompleteString(t.source.to_string(), t.span, None)
334 } else {
335 ParseError::UnexpectedChar(t.source.chars().next().unwrap(), t.span, None)
336 }
337 } else {
338 ParseError::UnexpectedEOF(None)
339 }
340}
341
342impl<'a> Parser<'a> {
343 pub fn new(input: &'a str, source_id: Option<SourceId>) -> Self {
344 Parser {
345 tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
346 quote_stack: Vec::new(),
347 quasiquote_depth: 0,
348 quote_context: false,
349 shorthand_quote_stack: Vec::new(),
350 source_name: None,
351 context: Vec::new(),
352 comment_buffer: Vec::new(),
353 collecting_comments: false,
354 keep_lists: false,
355 }
356 }
357
358 pub fn without_lowering(mut self) -> Self {
359 self.keep_lists = true;
360 self
361 }
362
363 pub fn new_flat(input: &'a str, source_id: Option<SourceId>) -> Self {
364 Parser {
365 tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
366 quote_stack: Vec::new(),
367 quasiquote_depth: 0,
368 quote_context: false,
369 shorthand_quote_stack: Vec::new(),
370 source_name: None,
371 context: Vec::new(),
372 comment_buffer: Vec::new(),
373 collecting_comments: false,
374 keep_lists: true,
375 }
376 }
377
378 pub fn new_from_source(
379 input: &'a str,
380 source_name: PathBuf,
381 source_id: Option<SourceId>,
382 ) -> Self {
383 Parser {
384 tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
385 quote_stack: Vec::new(),
386 quasiquote_depth: 0,
387 quote_context: false,
388 shorthand_quote_stack: Vec::new(),
389 source_name: Some(Rc::from(source_name)),
390 context: Vec::new(),
391 comment_buffer: Vec::new(),
392 collecting_comments: false,
393 keep_lists: false,
394 }
395 }
396
397 pub fn doc_comment_parser(input: &'a str, source_id: Option<SourceId>) -> Self {
399 Parser {
400 tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
401 quote_stack: Vec::new(),
402 quasiquote_depth: 0,
403 quote_context: false,
404 shorthand_quote_stack: Vec::new(),
405 source_name: None,
406 context: Vec::new(),
407 comment_buffer: Vec::new(),
408 collecting_comments: false,
409 keep_lists: false,
410 }
411 }
412
413 fn construct_quote(&mut self, val: ExprKind, span: Span) -> ExprKind {
414 ExprKind::Quote(Box::new(ast::Quote::new(
415 val,
416 SyntaxObject::new(TokenType::Quote, span),
417 )))
418 }
419
420 fn _expand_reader_macro(
421 &mut self,
422 token: TokenType<InternedString>,
423 val: ExprKind,
424 span: Span,
425 ) -> ExprKind {
426 let q = ExprKind::Atom(Atom::new(SyntaxObject::new(token, span)));
427
428 ExprKind::List(List::new(vec![q, val]))
429 }
430
431 fn construct_quote_vec(&mut self, val: ExprKind, span: Span) -> Vec<ExprKind> {
432 let q = {
435 let rc_val = TokenType::Quote;
436 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
437 };
441
442 vec![q, val]
443 }
444
445 fn construct_syntax(&mut self, val: ExprKind, span: Span) -> ExprKind {
447 let q = {
448 let rc_val = TokenType::Identifier(*SYNTAX_QUOTE);
449 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
450 };
451
452 ExprKind::List(List::new(vec![q, val]))
453 }
454
455 fn construct_quasiquote_syntax(&mut self, val: ExprKind, span: Span) -> ExprKind {
457 let q = {
458 let rc_val = TokenType::Identifier(*QUASISYNTAX);
459 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
460 };
461
462 ExprKind::List(List::new(vec![q, val]))
463 }
464
465 fn construct_quasiunquote_syntax(&mut self, val: ExprKind, span: Span) -> ExprKind {
466 let q = {
467 let rc_val = TokenType::Identifier(*RAW_UNSYNTAX);
468 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
469 };
470
471 ExprKind::List(List::new(vec![q, val]))
472 }
473
474 fn construct_quasiunquote_syntax_splicing(&mut self, val: ExprKind, span: Span) -> ExprKind {
475 let q = {
476 let rc_val = TokenType::Identifier(*RAW_UNSYNTAX_SPLICING);
477 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
478 };
479
480 ExprKind::List(List::new(vec![q, val]))
481 }
482
483 fn construct_quasiquote(&mut self, val: ExprKind, span: Span) -> ExprKind {
485 let q = {
486 let rc_val = TokenType::Identifier(*QUASIQUOTE);
487 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
488 };
489
490 ExprKind::List(List::new(vec![q, val]))
491 }
492
493 fn construct_unquote(&mut self, val: ExprKind, span: Span) -> ExprKind {
495 let q = {
496 let rc_val = TokenType::Identifier(*UNQUOTE);
497 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
498 };
499
500 ExprKind::List(List::new(vec![q, val]))
501 }
502
503 fn construct_raw_unquote(&mut self, val: ExprKind, span: Span) -> ExprKind {
504 let q = {
505 let rc_val = TokenType::Identifier(*RAW_UNQUOTE);
507 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
508 };
509
510 ExprKind::List(List::new(vec![q, val]))
511 }
512 fn construct_unquote_splicing(&mut self, val: ExprKind, span: Span) -> ExprKind {
514 let q = {
515 let rc_val = TokenType::Identifier(*UNQUOTE_SPLICING);
516 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
517 };
518
519 ExprKind::List(List::new(vec![q, val]))
520 }
521
522 fn construct_raw_unquote_splicing(&mut self, val: ExprKind, span: Span) -> ExprKind {
524 let q = {
525 let rc_val = TokenType::Identifier(*RAW_UNQUOTE_SPLICING);
526 ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
527 };
528
529 ExprKind::List(List::new(vec![q, val]))
530 }
531
532 fn increment_quasiquote_context_if_not_in_quote_context(&mut self) {
533 if !self.quote_context {
535 self.quasiquote_depth += 1;
536 }
537 }
538
539 fn decrement_quasiquote_context_if_not_in_quote_context(&mut self) {
540 if !self.quote_context {
542 self.quasiquote_depth -= 1;
543 }
544 }
545
546 fn maybe_lower(&self, exprs: Vec<ExprKind>) -> Result<ExprKind> {
547 if self.keep_lists {
548 Ok(ExprKind::List(List::new(exprs)))
549 } else {
550 ExprKind::try_from(exprs)
551 }
552 }
553
554 fn maybe_lower_frame(&self, frame: Frame, close: Span) -> Result<ExprKind> {
555 frame.build_expr(close, |exprs| self.maybe_lower(exprs))
556 }
557
558 fn read_from_tokens(
559 &mut self,
560 (open, paren, paren_mod): (Span, Paren, Option<ParenMod>),
561 ) -> Result<ExprKind> {
562 let mut stack: Vec<Frame> = Vec::new();
563
564 let mut current_frame = Frame {
565 open,
566 paren,
567 paren_mod,
568 exprs: vec![],
569 dot: None,
570 comment: 0,
571 };
572
573 self.quote_stack = Vec::new();
574
575 while let Some(token) = self.tokenizer.next() {
579 match token.ty {
580 TokenType::Dot => {
581 if current_frame.dot.is_some() {
582 return Err(ParseError::SyntaxError(
583 "improper lists can only have a single dot".into(),
584 token.span,
585 None,
586 ));
587 } else if current_frame.exprs.is_empty() {
588 return Err(ParseError::SyntaxError(
589 "improper lists must have a car element before the dot".into(),
590 token.span,
591 None,
592 ));
593 } else if current_frame.paren_mod.is_some() {
594 let paren_mod = current_frame.paren_mod.unwrap();
595 let object = match paren_mod {
596 ParenMod::Vector => "vector",
597 ParenMod::Bytes => "bytevector",
598 };
599
600 return Err(ParseError::SyntaxError(
601 format!("{object} literals cannot contain dots"),
602 token.span,
603 None,
604 ));
605 } else if current_frame.comment > 0 {
606 return Err(ParseError::SyntaxError(
607 "commented-out datum cannot start with a dot".into(),
608 token.span,
609 None,
610 ));
611 } else {
612 current_frame.dot = Some((current_frame.exprs.len(), token.span));
613 }
614 }
615 TokenType::Comment => {
616 }
619 TokenType::DatumComment => {
620 current_frame.comment += 1;
621 }
622 TokenType::Error => return Err(tokentype_error_to_parse_error(&token)), TokenType::QuoteSyntax => {
625 let quote_inner = self
626 .next()
627 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
628 .map(|x| self.construct_syntax(x, token.span))?;
629
630 current_frame.push(quote_inner)?
631 }
632
633 TokenType::QuasiQuoteSyntax => {
634 let quote_inner = self
635 .next()
636 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
637 .map(|x| self.construct_quasiquote_syntax(x, token.span))?;
638
639 current_frame.push(quote_inner)?
640 }
641
642 TokenType::UnquoteSyntax => {
643 let quote_inner = self
644 .next()
645 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
646 .map(|x| self.construct_quasiunquote_syntax(x, token.span))?;
647
648 current_frame.push(quote_inner)?
649 }
650
651 TokenType::UnquoteSpliceSyntax => {
652 let quote_inner = self
653 .next()
654 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
655 .map(|x| self.construct_quasiunquote_syntax_splicing(x, token.span))?;
656
657 current_frame.push(quote_inner)?
658 }
659
660 TokenType::QuoteTick => {
661 self.shorthand_quote_stack.push(stack.len());
664
665 let last_context = self.quote_context;
666
667 if self.quasiquote_depth == 0 {
668 self.quote_context = true;
669 }
670
671 self.context.push(ParsingContext::QuoteTick(stack.len()));
674
675 let quote_inner = self
676 .next()
677 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
678 .map(|x| {
679 self.construct_quote(x, token.span)
681 });
685 self.shorthand_quote_stack.pop();
687
688 self.quote_context = last_context;
689
690 let popped_value = self.context.pop();
698
699 if let Some(popped) = popped_value {
700 debug_assert!(matches!(popped, ParsingContext::QuoteTick(_)))
702 }
703
704 current_frame.push(quote_inner?)?;
705 }
706 TokenType::Unquote => {
707 self.decrement_quasiquote_context_if_not_in_quote_context();
711
712 self.context.push(ParsingContext::UnquoteTick(stack.len()));
713
714 let quote_inner = self
715 .next()
716 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
717 .map(|x| {
718 if self.quasiquote_depth == 0 && !self.quote_context {
721 self.construct_raw_unquote(x, token.span)
722 } else {
723 self.construct_unquote(x, token.span)
724 }
725 });
726
727 let popped_value = self.context.pop();
728
729 self.increment_quasiquote_context_if_not_in_quote_context();
730
731 if let Some(popped) = popped_value {
732 debug_assert!(matches!(popped, ParsingContext::UnquoteTick(_)))
733 }
734 current_frame.push(quote_inner?)?;
736 }
737 TokenType::QuasiQuote => {
738 self.increment_quasiquote_context_if_not_in_quote_context();
741
742 self.context
743 .push(ParsingContext::QuasiquoteTick(stack.len()));
744
745 let quote_inner = self
746 .next()
747 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
748 .map(|x| self.construct_quasiquote(x, token.span));
749
750 let popped_value = self.context.pop();
757
758 self.decrement_quasiquote_context_if_not_in_quote_context();
759
760 if let Some(popped) = popped_value {
761 debug_assert!(matches!(popped, ParsingContext::QuasiquoteTick(_)))
762 }
763
764 current_frame.push(quote_inner?)?;
765 }
766 TokenType::UnquoteSplice => {
767 self.decrement_quasiquote_context_if_not_in_quote_context();
770
771 self.context
772 .push(ParsingContext::UnquoteSplicingTick(stack.len()));
773
774 let quote_inner = self
775 .next()
776 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
777 .map(|x| {
778 if self.quasiquote_depth == 0 && !self.quote_context {
779 self.construct_raw_unquote_splicing(x, token.span)
780 } else {
781 self.construct_unquote_splicing(x, token.span)
782 }
783 });
784
785 let popped_value = self.context.pop();
788
789 self.increment_quasiquote_context_if_not_in_quote_context();
790
791 if let Some(popped) = popped_value {
792 debug_assert!(matches!(popped, ParsingContext::UnquoteSplicingTick(_)))
793 }
794
795 current_frame.push(quote_inner?)?;
797 }
798 TokenType::OpenParen(paren, paren_mod) => {
799 stack.push(current_frame);
800
801 current_frame = Frame {
802 open: token.span,
803 paren_mod,
804 exprs: vec![],
805 dot: None,
806 paren,
807 comment: 0,
808 };
809 }
810 TokenType::CloseParen(paren) => {
811 let close = token.span;
812 if paren != current_frame.paren {
816 return Err(ParseError::Unexpected(
817 TokenType::CloseParen(paren),
818 token.span,
819 self.source_name.clone(),
820 ));
821 }
822
823 if let Some(mut prev_frame) = stack.pop() {
824 match prev_frame
825 .exprs
826 .first_mut()
827 .and_then(|x| x.atom_identifier_mut())
828 {
829 Some(ident) if *ident == *UNQUOTE => {
830 if self.quasiquote_depth == 0 && !self.quote_context {
832 *ident = *RAW_UNQUOTE;
833 }
834 self.increment_quasiquote_context_if_not_in_quote_context();
835
836 }
838 Some(ident) if *ident == *QUASIQUOTE => {
839 self.decrement_quasiquote_context_if_not_in_quote_context();
840
841 }
843 Some(ident) if *ident == *UNQUOTE_SPLICING => {
844 if self.quasiquote_depth == 0 && !self.quote_context {
847 *ident = *RAW_UNQUOTE_SPLICING;
848 }
849 self.increment_quasiquote_context_if_not_in_quote_context();
850
851 }
853 _ => {}
854 }
855
856 match self.context.last().copied() {
857 Some(ParsingContext::Quote(last_quote_index))
861 | Some(ParsingContext::Quasiquote(last_quote_index)) => {
862 if stack.len() <= last_quote_index {
863 self.context.pop();
864 }
865
866 match current_frame.exprs.first() {
867 Some(ExprKind::Atom(Atom {
868 syn:
869 SyntaxObject {
870 ty: TokenType::Quote,
871 ..
872 },
873 })) => match self.context.last() {
874 Some(
875 ParsingContext::Quasiquote(_)
876 | ParsingContext::QuasiquoteTick(_)
877 | ParsingContext::Quote(_)
878 | ParsingContext::QuoteTick(_),
879 ) => prev_frame.push(current_frame.to_expr(close)?)?,
880 _ => {
881 prev_frame.push(
882 self.maybe_lower_frame(current_frame, close)?,
883 )?;
884 }
885 },
886 _ => {
887 prev_frame.push(current_frame.to_expr(close)?)?
890 }
891 }
892 }
893
894 Some(ParsingContext::QuoteTick(_))
895 | Some(ParsingContext::QuasiquoteTick(_)) => {
896 match current_frame.exprs.first() {
897 Some(ExprKind::Atom(Atom {
898 syn:
899 SyntaxObject {
900 ty: TokenType::Quote,
901 ..
902 },
903 })) => {
904 prev_frame
906 .push(self.maybe_lower_frame(current_frame, close)?)?;
907 }
908 _ => {
909 prev_frame.push(current_frame.to_expr(close)?)?
917 }
918 }
919 }
920
921 Some(ParsingContext::UnquoteTick(_))
924 | Some(ParsingContext::UnquoteSplicingTick(_)) => {
925 prev_frame.push(self.maybe_lower_frame(current_frame, close)?)?;
941 }
942
943 Some(ParsingContext::Unquote(last_quote_index))
944 | Some(ParsingContext::UnquoteSplicing(last_quote_index)) => {
945 if stack.len() <= last_quote_index {
956 self.context.pop();
959 }
960
961 prev_frame.push(self.maybe_lower_frame(current_frame, close)?)?;
962 }
963
964 _ => prev_frame.push(self.maybe_lower_frame(current_frame, close)?)?,
966 }
967
968 current_frame = prev_frame;
970 } else {
971 match self.context.last() {
978 Some(ParsingContext::QuoteTick(_))
979 | Some(ParsingContext::QuasiquoteTick(_)) => {
980 return current_frame.to_expr(close);
983 }
984 Some(ParsingContext::Quote(x)) if *x > 0 => {
985 self.context.pop();
986
987 return current_frame.to_expr(close);
988 }
989 Some(ParsingContext::Quote(0)) => {
990 self.context.pop();
991
992 return self.maybe_lower_frame(current_frame, close);
993 }
994 _ => {
995 if self.quasiquote_depth > 0 {
1000 if current_frame
1003 .exprs
1004 .first()
1005 .map(|x| x.define_syntax_ident())
1006 .unwrap_or_default()
1007 {
1008 return self.maybe_lower_frame(current_frame, close);
1009 }
1010
1011 return current_frame.to_expr(close);
1014 }
1015
1016 return self.maybe_lower_frame(current_frame, close);
1017 }
1018 }
1019 }
1020 }
1021
1022 _ => {
1023 if let TokenType::Quote = &token.ty {
1024 self.quote_stack.push(stack.len());
1026 }
1027
1028 if current_frame.exprs.is_empty() {
1033 match &token.ty {
1034 TokenType::Quote => {
1035 if self.context == [ParsingContext::QuoteTick(0)] {
1036 self.context.push(ParsingContext::Quote(1))
1037 } else {
1038 self.context.push(ParsingContext::Quote(stack.len()))
1039 }
1040
1041 }
1043 TokenType::Identifier(ident) if *ident == *UNQUOTE => {
1044 self.context.push(ParsingContext::Unquote(stack.len()));
1047 self.decrement_quasiquote_context_if_not_in_quote_context();
1048 }
1049 TokenType::Identifier(ident) if *ident == *QUASIQUOTE => {
1050 self.context.push(ParsingContext::Quasiquote(stack.len()));
1053 self.increment_quasiquote_context_if_not_in_quote_context();
1054 }
1055 TokenType::Identifier(ident) if *ident == *UNQUOTE_SPLICING => {
1056 self.context
1057 .push(ParsingContext::UnquoteSplicing(stack.len()));
1058 self.decrement_quasiquote_context_if_not_in_quote_context();
1059 }
1060 _ => {}
1061 }
1062
1063 }
1065
1066 let atom = Atom::new(SyntaxObject::from_token_with_source(
1069 &token,
1070 &self.source_name.clone(),
1071 ));
1072
1073 current_frame.push(ExprKind::Atom(atom))?
1074 }
1075 }
1076 }
1077
1078 Err(ParseError::UnexpectedEOF(self.source_name.clone()))
1079 }
1080}
1081
1082fn wrap_in_doc_function(expr: ExprKind, comment: String) -> ExprKind {
1083 ExprKind::List(List::new(vec![
1086 ExprKind::ident("@doc"),
1087 ExprKind::string_lit(comment),
1088 expr,
1089 ]))
1090}
1091
1092impl<'a> Parser<'a> {
1093 fn get_next_and_maybe_wrap_in_doc(&mut self) -> Option<Result<ExprKind>> {
1094 let mut datum_comments = vec![];
1095
1096 macro_rules! maybe_return {
1097 ($value:expr) => {{
1098 let value = $value;
1099
1100 if value.is_ok() {
1101 if datum_comments.len() > 0 {
1102 let _ = datum_comments.pop();
1103
1104 continue;
1105 }
1106 }
1107
1108 return Some(value);
1109 }};
1110 }
1111
1112 while let Some(res) = self.tokenizer.next() {
1113 match res.ty {
1114 TokenType::Comment => {
1115 if self.comment_buffer.is_empty()
1116 && !self.collecting_comments
1117 && res.source().trim_start_matches(';').starts_with("@doc")
1118 {
1119 self.collecting_comments = true;
1120
1121 continue;
1122 }
1123
1124 if self.collecting_comments {
1125 let doc_line = res.source().trim_start_matches(';');
1126
1127 if doc_line.starts_with("@doc") {
1129 self.comment_buffer.clear();
1132 continue;
1133 }
1134
1135 let line = doc_line
1138 .strip_prefix(" ")
1139 .unwrap_or(doc_line)
1140 .trim_end_matches(['\n', '\r']);
1141 self.comment_buffer.push(line);
1142 }
1143
1144 continue;
1145 }
1146
1147 TokenType::DatumComment => {
1148 datum_comments.push(res.span);
1149 }
1150
1151 TokenType::QuoteSyntax => {
1153 let value = self
1154 .next()
1155 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1156 .map(|x| self.construct_syntax(x, res.span));
1157
1158 maybe_return![value];
1159 }
1160
1161 TokenType::QuasiQuoteSyntax => {
1162 let value = self
1163 .next()
1164 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1165 .map(|x| self.construct_quasiquote_syntax(x, res.span));
1166
1167 maybe_return![value];
1168 }
1169
1170 TokenType::UnquoteSyntax => {
1171 let quote_inner = self
1172 .next()
1173 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1174 .map(|x| self.construct_quasiunquote_syntax(x, res.span));
1175
1176 maybe_return!(quote_inner);
1177 }
1178
1179 TokenType::UnquoteSpliceSyntax => {
1180 let quote_inner = self
1181 .next()
1182 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1183 .map(|x| self.construct_quasiunquote_syntax_splicing(x, res.span));
1184
1185 maybe_return!(quote_inner);
1186 }
1187
1188 TokenType::QuoteTick => {
1189 self.shorthand_quote_stack.push(0);
1191
1192 let last = self.quote_context;
1193
1194 if self.quasiquote_depth == 0 {
1195 self.quote_context = true;
1196 }
1197
1198 self.context.push(ParsingContext::QuoteTick(0));
1202
1203 let value = self
1204 .next()
1205 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1206 .map(|x| self.construct_quote_vec(x, res.span));
1207
1208 self.shorthand_quote_stack.pop();
1209
1210 let popped_value = self.context.pop();
1211
1212 if let Some(popped) = popped_value {
1213 debug_assert!(matches!(popped, ParsingContext::QuoteTick(_)))
1215 }
1216
1217 self.quote_context = last;
1218
1219 maybe_return!(match value {
1225 Ok(v) => {
1226 self.maybe_lower(v)
1229 }
1230 Err(e) => Err(e),
1231 });
1232 }
1233
1234 TokenType::Unquote => {
1235 self.context.push(ParsingContext::UnquoteTick(0));
1237
1238 self.decrement_quasiquote_context_if_not_in_quote_context();
1239
1240 let value = self
1241 .next()
1242 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1243 .map(|x| {
1244 if self.quasiquote_depth == 0 && !self.quote_context {
1246 self.construct_raw_unquote(x, res.span)
1247 } else {
1248 self.construct_unquote(x, res.span)
1249 }
1250 });
1251
1252 let popped_value = self.context.pop();
1253
1254 self.increment_quasiquote_context_if_not_in_quote_context();
1255
1256 if let Some(popped) = popped_value {
1257 debug_assert!(matches!(popped, ParsingContext::UnquoteTick(_)))
1258 }
1259 maybe_return!(value);
1262 }
1263
1264 TokenType::UnquoteSplice => {
1265 self.context.push(ParsingContext::UnquoteSplicingTick(0));
1267
1268 self.decrement_quasiquote_context_if_not_in_quote_context();
1269
1270 let value = self
1271 .next()
1272 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1273 .map(|x| {
1274 if self.quasiquote_depth == 0 && !self.quote_context {
1275 self.construct_raw_unquote_splicing(x, res.span)
1276 } else {
1277 self.construct_unquote_splicing(x, res.span)
1278 }
1279 });
1280
1281 let popped_value = self.context.pop();
1282
1283 self.increment_quasiquote_context_if_not_in_quote_context();
1284
1285 if let Some(popped) = popped_value {
1286 debug_assert!(matches!(popped, ParsingContext::UnquoteSplicingTick(_)))
1287 }
1288
1289 maybe_return!(value);
1292 }
1293 TokenType::QuasiQuote => {
1295 self.context.push(ParsingContext::QuasiquoteTick(0));
1296
1297 self.increment_quasiquote_context_if_not_in_quote_context();
1298
1299 let value = self
1300 .next()
1301 .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1302 .map(|x| self.construct_quasiquote(x, res.span));
1303
1304 let popped_value = self.context.pop();
1305
1306 if let Some(popped) = popped_value {
1307 debug_assert!(matches!(popped, ParsingContext::QuasiquoteTick(_)))
1308 }
1309
1310 self.decrement_quasiquote_context_if_not_in_quote_context();
1311
1312 maybe_return![value];
1313 }
1314
1315 TokenType::OpenParen(paren, paren_mod) => {
1316 let value = self
1317 .read_from_tokens((res.span, paren, paren_mod))
1318 .map_err(|err| err.set_source(self.source_name.clone()));
1319
1320 maybe_return![value];
1324 }
1325 TokenType::CloseParen(paren) => {
1326 maybe_return!(Err(ParseError::Unexpected(
1327 TokenType::CloseParen(paren),
1328 res.span,
1329 self.source_name.clone(),
1330 )))
1331 }
1332 TokenType::Error => maybe_return!(Err(tokentype_error_to_parse_error(&res))),
1333 _ => {
1334 maybe_return![Ok(ExprKind::Atom(Atom::new(SyntaxObject::from(&res))))];
1335 }
1336 };
1337 }
1338
1339 if !datum_comments.is_empty() {
1340 return Some(Err(ParseError::SyntaxError(
1341 "unfinished commented-out expression".into(),
1342 datum_comments.pop().unwrap(),
1343 None,
1344 )));
1345 }
1346
1347 None
1349 }
1350}
1351
1352impl<'a> Iterator for Parser<'a> {
1353 type Item = Result<ExprKind>;
1354
1355 fn next(&mut self) -> Option<Self::Item> {
1357 if self.quote_stack.is_empty()
1358 && self.shorthand_quote_stack.is_empty()
1359 && self.context.is_empty()
1360 {
1361 self.quasiquote_depth = 0;
1362 self.comment_buffer.clear();
1363 }
1364
1365 self.get_next_and_maybe_wrap_in_doc().map(|res| {
1366 if self.comment_buffer.is_empty() || !self.context.is_empty() {
1367 res
1368 } else {
1369 self.collecting_comments = false;
1371 res.map(|x| {
1372 let result = wrap_in_doc_function(
1374 x,
1375 self.comment_buffer.drain(..).collect::<Vec<_>>().join("\n"),
1376 );
1377
1378 result
1379 })
1380 }
1381 })
1382 }
1383}
1384
1385pub fn lower_syntax_rules(expr: ExprKind) -> Result<SyntaxRules> {
1387 let mut value_iter = expr.into_list().into_iter();
1388 let syn = value_iter
1389 .next()
1390 .unwrap()
1391 .into_atom_syntax_object()
1392 .unwrap();
1393
1394 let syntax_vec = if let Some(ExprKind::List(l)) = value_iter.next() {
1395 l.args
1396 } else {
1397 return Err(ParseError::SyntaxError(
1398 "syntax-rules expects a list of new syntax forms used in the macro".to_string(),
1399 syn.span,
1400 None,
1401 ));
1402 };
1403
1404 let mut pairs = Vec::new();
1405 let rest: Vec<_> = value_iter.collect();
1406
1407 for pair in rest {
1408 if let ExprKind::List(l) = pair {
1409 if l.args.len() != 2 {
1410 return Err(ParseError::SyntaxError(
1411 "syntax-rules requires only one pattern to one body".to_string(),
1412 syn.span,
1413 None,
1414 ));
1415 }
1416
1417 let mut pair_iter = l.args.into_iter();
1418 let pair_object =
1419 PatternPair::new(pair_iter.next().unwrap(), pair_iter.next().unwrap());
1420 pairs.push(pair_object);
1421 } else {
1422 return Err(ParseError::SyntaxError(
1423 "syntax-rules requires pattern to expressions to be in a list".to_string(),
1424 syn.span,
1425 None,
1426 ));
1427 }
1428 }
1429
1430 Ok(SyntaxRules::new(syntax_vec, pairs, syn))
1431}
1432
1433pub fn lower_macro_and_require_definitions(expr: ExprKind) -> Result<ExprKind> {
1435 let as_list = expr.list();
1436
1437 if as_list.map(List::is_define_syntax).unwrap_or_default()
1439 && as_list
1440 .unwrap()
1441 .get(2)
1442 .and_then(ExprKind::list)
1443 .map(List::is_syntax_rules)
1444 .unwrap_or_default()
1445 {
1446 let mut value_iter = expr.into_list().into_iter();
1447
1448 let define_syntax = value_iter.next().unwrap();
1449
1450 let name = value_iter.next().unwrap();
1451 let syntax = lower_syntax_rules(value_iter.next().unwrap())?;
1452
1453 return Ok(ExprKind::Macro(Box::new(Macro::new(
1454 name,
1455 Box::new(syntax),
1456 define_syntax.into_atom_syntax_object().unwrap(),
1457 ))));
1458 }
1459
1460 if as_list.map(List::is_require).unwrap_or_default() {
1461 let mut raw = expr.into_list().args;
1462
1463 let syn = raw.remove(0).into_atom_syntax_object().unwrap();
1464
1465 if raw.is_empty() {
1466 return Err(ParseError::ArityMismatch(
1467 "require expects at least one identifier or string".to_string(),
1468 syn.span,
1469 None,
1470 ));
1471 }
1472
1473 return Ok(ExprKind::Require(Box::new(ast::Require::new(raw, syn))));
1474 }
1475
1476 let mut expr = expr;
1477
1478 if let Some(first) = expr
1485 .list_mut()
1486 .and_then(|x| x.args.first_mut().and_then(|x| x.atom_syntax_object_mut()))
1487 {
1488 if first.ty == TokenType::DefineSyntax {
1489 first.ty = TokenType::Identifier("define-syntax".into());
1490 }
1491 }
1492
1493 Ok(expr)
1494}
1495
1496struct ASTLowerPass {
1497 quote_depth: usize,
1498}
1499
1500impl ASTLowerPass {
1501 fn lower(&mut self, expr: &mut ExprKind) -> Result<()> {
1502 match expr {
1503 ExprKind::List(ref mut value) => {
1504 if value.is_quote() {
1505 self.quote_depth += 1;
1507 }
1508
1509 for expr in value.args.iter_mut() {
1518 self.lower(expr)?;
1519 }
1520
1521 if value.is_quote() {
1522 self.quote_depth -= 1;
1523 }
1524
1525 if let Some(f) = value.args.first_mut().and_then(|x| {
1526 if let ExprKind::Atom(a) = x {
1527 if a.syn.ty == TokenType::DefineSyntax {
1528 a.syn.ty = TokenType::Identifier("define-syntax".into());
1529 }
1530
1531 Some(x.clone())
1532 } else {
1533 None
1534 }
1535 }) {
1536 match f {
1537 ExprKind::Atom(a) if self.quote_depth == 0 && value.is_quote() => {
1538 match &a.syn.ty {
1539 TokenType::Quote => {
1540 *expr = parse_single_argument(
1541 std::mem::take(&mut value.args).into_iter(),
1542 a.syn.clone(),
1543 "quote",
1544 |expr, syn| ast::Quote::new(expr, syn).into(),
1545 )?;
1546
1547 Ok(())
1548 }
1549 _ => unreachable!(),
1550 }
1551 }
1552 ExprKind::Atom(a) if self.quote_depth == 0 => {
1553 let value = std::mem::replace(value, List::new(vec![]));
1554
1555 *expr = match &a.syn.ty {
1556 TokenType::If => {
1557 parse_if(value.args_proper(TokenType::If)?.into_iter(), a.syn)
1558 }
1559 TokenType::Identifier(expr) if *expr == *IF => {
1560 parse_if(value.args_proper(TokenType::If)?.into_iter(), a.syn)
1561 }
1562
1563 TokenType::Define => parse_define(
1564 value.args_proper(TokenType::Define)?.into_iter(),
1565 a.syn,
1566 ),
1567 TokenType::Identifier(expr) if *expr == *DEFINE => parse_define(
1568 value.args_proper(TokenType::Define)?.into_iter(),
1569 a.syn,
1570 ),
1571
1572 TokenType::Let => parse_let(
1573 value.args_proper(TokenType::Let)?.into_iter(),
1574 a.syn.clone(),
1575 ),
1576 TokenType::Identifier(expr) if *expr == *LET => {
1577 parse_let(value.args_proper(TokenType::Let)?.into_iter(), a.syn)
1578 }
1579
1580 TokenType::TestLet => parse_new_let(
1582 value.args_proper(TokenType::TestLet)?.into_iter(),
1583 a.syn,
1584 ),
1585 TokenType::Identifier(expr) if *expr == *PLAIN_LET => {
1586 parse_new_let(
1587 value.args_proper(TokenType::TestLet)?.into_iter(),
1588 a.syn,
1589 )
1590 }
1591
1592 TokenType::Quote => parse_single_argument(
1593 value.args_proper(TokenType::Quote)?.into_iter(),
1594 a.syn,
1595 "quote",
1596 |expr, syn| ast::Quote::new(expr, syn).into(),
1597 ),
1598 TokenType::Identifier(expr) if *expr == *QUOTE => {
1599 parse_single_argument(
1600 value.args_proper(TokenType::Quote)?.into_iter(),
1601 a.syn,
1602 "quote",
1603 |expr, syn| ast::Quote::new(expr, syn).into(),
1604 )
1605 }
1606
1607 TokenType::Return => parse_single_argument(
1608 value.args_proper(TokenType::Return)?.into_iter(),
1609 a.syn,
1610 "return!",
1611 |expr, syn| ast::Return::new(expr, syn).into(),
1612 ),
1613 TokenType::Identifier(expr) if *expr == *RETURN => {
1614 parse_single_argument(
1615 value.args_proper(TokenType::Return)?.into_iter(),
1616 a.syn,
1617 "return!",
1618 |expr, syn| ast::Return::new(expr, syn).into(),
1619 )
1620 }
1621
1622 TokenType::Require => {
1623 parse_require(&a, value.args_proper(TokenType::Require)?)
1624 }
1625 TokenType::Identifier(expr) if *expr == *REQUIRE => {
1626 parse_require(&a, value.args_proper(TokenType::Require)?)
1627 }
1628
1629 TokenType::Set => parse_set(&a, value.args_proper(TokenType::Set)?),
1630 TokenType::Identifier(expr) if *expr == *SET => {
1631 parse_set(&a, value.args_proper(TokenType::Set)?)
1632 }
1633
1634 TokenType::Begin => {
1635 parse_begin(a, value.args_proper(TokenType::Begin)?)
1636 }
1637 TokenType::Identifier(expr) if *expr == *BEGIN => {
1638 parse_begin(a, value.args_proper(TokenType::Begin)?)
1639 }
1640
1641 TokenType::Lambda => {
1642 parse_lambda(a, value.args_proper(TokenType::Lambda)?)
1643 }
1644 TokenType::Identifier(expr)
1645 if *expr == *LAMBDA
1646 || *expr == *LAMBDA_FN
1647 || *expr == *LAMBDA_SYMBOL =>
1648 {
1649 parse_lambda(a, value.args_proper(TokenType::Lambda)?)
1650 }
1651
1652 _ => Ok(ExprKind::List(value)),
1653 }?;
1654
1655 Ok(())
1656 }
1657 _ => Ok(()),
1658 }
1659 } else {
1660 Ok(())
1661 }
1662 }
1663 ExprKind::Atom(_) => Ok(()),
1664 ExprKind::If(iff) => {
1665 self.lower(&mut iff.test_expr)?;
1666 self.lower(&mut iff.then_expr)?;
1667 self.lower(&mut iff.else_expr)?;
1668 Ok(())
1669 }
1670 ExprKind::Let(l) => {
1671 for (left, right) in l.bindings.iter_mut() {
1672 self.lower(left)?;
1673 self.lower(right)?;
1674 }
1675
1676 self.lower(&mut l.body_expr)?;
1677
1678 Ok(())
1679 }
1680 ExprKind::Define(d) => {
1681 self.lower(&mut d.name)?;
1682 self.lower(&mut d.body)?;
1683
1684 Ok(())
1685 }
1686
1687 ExprKind::LambdaFunction(f) => {
1688 for arg in f.args.iter_mut() {
1689 self.lower(arg)?;
1690 }
1691
1692 self.lower(&mut f.body)?;
1693
1694 Ok(())
1695 }
1696 ExprKind::Begin(b) => {
1697 for expr in b.exprs.iter_mut() {
1698 self.lower(expr)?;
1699 }
1700
1701 Ok(())
1702 }
1703 ExprKind::Return(r) => {
1711 self.lower(&mut r.expr)?;
1712 Ok(())
1713 }
1714 ExprKind::Quote(_) => Ok(()),
1719 ExprKind::Macro(_) => Ok(()),
1720 ExprKind::SyntaxRules(_) => Ok(()),
1721 ExprKind::Set(s) => {
1722 self.lower(&mut s.variable)?;
1723 self.lower(&mut s.expr)?;
1724
1725 Ok(())
1726 }
1727 ExprKind::Require(_) => Ok(()),
1733 ExprKind::Vector(v) => {
1734 for arg in &mut v.args {
1735 self.lower(arg)?;
1736 }
1737
1738 Ok(())
1739 }
1740 }
1741 }
1742}
1743
1744pub fn lower_entire_ast(expr: &mut ExprKind) -> Result<()> {
1746 ASTLowerPass { quote_depth: 0 }.lower(expr)
1747}
1748
1749struct Frame {
1750 open: Span,
1751 paren: Paren,
1752 paren_mod: Option<ParenMod>,
1753 exprs: Vec<ExprKind>,
1754 dot: Option<(usize, Span)>,
1755 comment: u8,
1756}
1757
1758impl Frame {
1759 fn to_expr(self, close: Span) -> Result<ExprKind> {
1760 self.build_expr(close, |exprs| Ok(List::new(exprs).into()))
1761 }
1762
1763 fn build_expr(
1764 self,
1765 close: Span,
1766 builder: impl FnOnce(Vec<ExprKind>) -> Result<ExprKind>,
1767 ) -> Result<ExprKind> {
1768 if self.comment > 0 {
1769 return Err(ParseError::SyntaxError(
1770 "invalid datum comment".into(),
1771 self.open,
1772 None,
1773 ));
1774 }
1775
1776 if let Some(paren_mod) = self.paren_mod {
1777 let bytes = matches!(paren_mod, ParenMod::Bytes);
1778
1779 return Ok(Vector {
1780 args: self.exprs,
1781 bytes,
1782 span: Span::merge(self.open, close),
1783 }
1784 .into());
1785 };
1786
1787 let improper = self.improper()?;
1788
1789 let mut expr = builder(self.exprs)?;
1790
1791 match &mut expr {
1792 ExprKind::List(list) => {
1793 list.location = Span::merge(self.open, close);
1794
1795 if improper {
1796 list.make_improper();
1797 }
1798 }
1799 _ if improper => todo!(),
1800 _ => {}
1801 };
1802
1803 Ok(expr.into())
1804 }
1805
1806 fn push(&mut self, expr: ExprKind) -> Result<()> {
1807 if let Some((idx, _)) = self.dot {
1808 debug_assert!(!self.exprs.is_empty());
1809
1810 if idx != self.exprs.len() {
1811 debug_assert_eq!(idx + 1, self.exprs.len());
1812
1813 return Err(ParseError::SyntaxError(
1814 "improper list must have a single cdr".to_owned(),
1815 expr.span().unwrap_or_default(),
1816 None,
1817 ));
1818 }
1819 }
1820
1821 let valid_for_bytes = match (self.paren_mod, &expr) {
1822 (Some(ParenMod::Bytes), ExprKind::Atom(atom)) if atom.byte().is_some() => true,
1823 (Some(ParenMod::Bytes), _) => false,
1824 _ => true,
1825 };
1826
1827 if !valid_for_bytes {
1828 return Err(ParseError::SyntaxError(
1829 "bytevector literals can only contain integer literals in the 0-255 range".into(),
1830 expr.span().unwrap_or_default(),
1831 None,
1832 ));
1833 }
1834
1835 if self.comment > 0 {
1836 self.comment -= 1;
1837
1838 return Ok(());
1839 }
1840
1841 self.exprs.push(expr);
1842
1843 Ok(())
1844 }
1845
1846 fn improper(&self) -> Result<bool> {
1847 match self.dot {
1848 Some((idx, _)) if idx + 1 == self.exprs.len() => Ok(true),
1849 Some((idx, span)) => {
1850 debug_assert_eq!(idx, self.exprs.len());
1851
1852 return Err(ParseError::SyntaxError(
1853 "improper list must have a single cdr".into(),
1854 span,
1855 None,
1856 ));
1857 }
1858 None => Ok(false),
1859 }
1860 }
1861}
1862
1863#[cfg(test)]
1864mod parser_tests {
1865 use super::*;
1867 use crate::parser::ast::{Begin, Define, If, LambdaFunction, Quote, Return};
1868 use crate::tokens::{Paren, RealLiteral};
1869 use crate::visitors::Eraser;
1870 use crate::{parser::ast::ExprKind, tokens::IntLiteral};
1871
1872 fn atom(ident: &str) -> ExprKind {
1873 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::Identifier(
1874 ident.into(),
1875 ))))
1876 }
1877
1878 fn int(num: isize) -> ExprKind {
1879 ExprKind::Atom(Atom::new(SyntaxObject::default(
1880 IntLiteral::Small(num).into(),
1881 )))
1882 }
1883
1884 fn character(c: char) -> ExprKind {
1885 ExprKind::Atom(Atom::new(SyntaxObject::default(
1886 TokenType::CharacterLiteral(c),
1887 )))
1888 }
1889
1890 #[test]
1891 fn check_quote_parsing() {
1892 println!("{:?}", Parser::parse("'(a b 'c)"));
1893 }
1894
1895 fn parses(s: &str) {
1896 let a: Result<Vec<_>> = Parser::new(s, SourceId::none()).collect();
1897 a.unwrap();
1898 }
1899
1900 fn parse_err(s: &str) -> ParseError {
1901 let a: Result<Vec<_>> = Parser::new(s, SourceId::none()).collect();
1902 a.unwrap_err()
1903 }
1904
1905 fn assert_parse(s: &str, result: &[ExprKind]) {
1906 let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1907 let mut a = a.unwrap();
1908
1909 let mut eraser = Eraser;
1910
1911 eraser.visit_many(&mut a);
1912
1913 assert_eq!(a.as_slice(), result);
1914 }
1915
1916 fn assert_parse_err(s: &str, err: ParseError) {
1917 let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1918 assert_eq!(a, Err(err));
1919 }
1920
1921 fn assert_syntax_err(s: &str, expected: &str) {
1922 let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1923 let Err(ParseError::SyntaxError(err, _, _)) = a else {
1924 panic!("expected syntax error, got {a:?}");
1925 };
1926
1927 assert_eq!(err, expected);
1928 }
1929
1930 fn assert_parse_is_err(s: &str) {
1931 let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1932 assert!(a.is_err());
1933 }
1934
1935 #[test]
1936 fn check_resulting_parsing() {
1937 let expr = r#"`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)"#;
1938
1939 let a: Result<Vec<ExprKind>> = Parser::new(expr, SourceId::none()).collect();
1940 let a = a.unwrap();
1941
1942 println!("{}", a[0]);
1943 }
1944
1945 #[test]
1946 fn check_double_unquote_parsing() {
1947 let expr = r#"(let ([name1 'x] [name2 'y]) `(a `(b ,,name1 ,',name2 d) e))"#;
1948
1949 let a: Result<Vec<ExprKind>> = Parser::new(expr, SourceId::none()).collect();
1950 let a = a.unwrap();
1951
1952 println!("{}", a[0]);
1953 }
1954
1955 #[test]
1956 fn check_parser_with_doc_comments() {
1957 let expr = r#"
1958 ;;@doc
1959 ;; This is a fancy cool comment, that I want to attach to a top level definition!
1960 ;; This is the second line of the comment, I want this attached as well!
1961 ;; Macro for creating a new struct, in the form of:
1962 ;; `(struct <struct-name> (fields ...) options ...)`
1963 ;; The options can consist of the following:
1964 ;;
1965 ;; Single variable options (those which their presence indicates #true)
1966 ;; - #:mutable
1967 ;; - #:transparent
1968 ;;
1969 ;; Other options must be presented as key value pairs, and will get stored
1970 ;; in the struct instance. They will also be bound to the variable
1971 ;; ___<struct-name>-options___ in the same lexical environment where the
1972 ;; struct was defined. For example:
1973 ;;
1974 ;; (Applesauce (a b c) #:mutable #:transparent #:unrecognized-option 1234)
1975 ;;
1976 ;; Will result in the value `___Applesauce-options___` like so:
1977 ;; (hash #:mutable #true #:transparent #true #:unrecognized-option 1234)
1978 ;;
1979 ;; By default, structs are immutable, which means setter functions will not
1980 ;; be generated. Also by default, structs are not transparent, which means
1981 ;; printing them will result in an opaque struct that does not list the fields
1982 (define foo 12345)
1983 "#;
1984
1985 let parser = Parser::doc_comment_parser(expr, SourceId::none());
1986
1987 let result: Result<Vec<_>> = parser.collect();
1988
1989 println!("{:?}", result.unwrap());
1990 }
1991
1992 #[test]
1993 fn parses_make_struct() {
1994 parses("(define make-struct (lambda (struct-name fields) (map (lambda (field) (list (quote define) (concat-symbols struct-name field) (quote (lambda (this) (vector-ref this 0))))) fields)))")
1995 }
1996
1997 #[test]
1998 fn parses_quasiquote() {
1999 parses(r#"(quasiquote ((unquote x) xs ...)) "#);
2000 }
2001
2002 #[test]
2003 fn parse_syntax_rules() {
2004 parses(
2005 r#"
2006 (syntax-rules (unquote unquote-splicing)
2007 ((quasiquote ((unquote x) xs ...)) (cons x (quasiquote (xs ...))))
2008 ((quasiquote ((unquote-splicing x))) (append (list x) '()))
2009 ((quasiquote ((unquote-splicing x) xs ...)) (append x (quasiquote (xs ...))))
2010 ((quasiquote (unquote x)) x)
2011 ((quasiquote (x)) '(x))
2012 ((quasiquote (x xs ...)) (cons (quasiquote x) (quasiquote (xs ...))))
2013 ((quasiquote x) 'x))
2014 "#,
2015 );
2016 }
2017
2018 #[test]
2019 fn parse_define_syntax() {
2020 parses(
2021 r#"
2022 (define-syntax quasiquote
2023 (syntax-rules (unquote unquote-splicing)
2024 ((quasiquote ((unquote x) xs ...)) (cons x (quasiquote (xs ...))))
2025 ((quasiquote ((unquote-splicing x))) (append (list x) '()))
2026 ((quasiquote ((unquote-splicing x) xs ...)) (append x (quasiquote (xs ...))))
2027 ((quasiquote (unquote x)) x)
2028 ((quasiquote (x)) '(x))
2029 ((quasiquote (x xs ...)) (cons (quasiquote x) (quasiquote (xs ...))))
2030 ((quasiquote x) 'x)))
2031 "#,
2032 );
2033 }
2034
2035 #[test]
2036 fn parse_quote() {
2037 parses("(displayln (match '(lambda y z) '(x y z)))")
2039 }
2040
2041 #[test]
2042 fn parse_unicode() {
2043 assert_parse("#\\¡", &[character('¡')]);
2044 assert_parse("#\\u{b}", &[character('\u{b}')]);
2045 }
2046
2047 #[test]
2048 fn parse_more_unicode() {
2049 assert_parse("#\\u{a0}", &[character('\u{a0}')]);
2050 }
2051
2052 #[test]
2053 fn parse_strange_characters() {
2054 assert_parse("#\\^", &[character('^')]);
2055 }
2056
2057 #[test]
2058 fn parse_character_sequence() {
2059 assert_parse(
2060 "#\\¡ #\\SPACE #\\g",
2061 &[character('¡'), character(' '), character('g')],
2062 )
2063 }
2064
2065 #[test]
2066 fn parse_character_sequence_inside_if() {
2067 assert_parse(
2068 "(if #\\¡ #\\SPACE #\\g)",
2069 &[ExprKind::If(Box::new(If::new(
2070 character('¡'),
2071 character(' '),
2072 character('g'),
2073 SyntaxObject::default(TokenType::If),
2074 )))],
2075 )
2076 }
2077
2078 #[test]
2079 fn parse_close_paren_character() {
2080 assert_parse("#\\)", &[character(')')]);
2081 assert_parse("#\\]", &[character(']')])
2082 }
2083
2084 #[test]
2085 fn parse_open_paren_character() {
2086 assert_parse("#\\(", &[character('(')])
2087 }
2088
2089 #[test]
2090 fn test_error() {
2091 assert_parse_err("(", ParseError::UnexpectedEOF(None));
2092 assert_parse_err("(abc", ParseError::UnexpectedEOF(None));
2093 assert_parse_err("(ab 1 2", ParseError::UnexpectedEOF(None));
2094 assert_parse_err("((((ab 1 2) (", ParseError::UnexpectedEOF(None));
2095 assert!(matches!(
2096 parse_err("())"),
2097 ParseError::Unexpected(TokenType::CloseParen(Paren::Round), _, None),
2098 ));
2099 assert_parse_err("() ((((", ParseError::UnexpectedEOF(None));
2100 assert!(matches!(
2101 parse_err("')"),
2102 ParseError::Unexpected(TokenType::CloseParen(Paren::Round), _, None),
2103 ));
2104 assert!(matches!(
2105 parse_err("(')"),
2106 ParseError::Unexpected(TokenType::CloseParen(Paren::Round), _, None),
2107 ));
2108 assert_parse_err("('", ParseError::UnexpectedEOF(None));
2109 assert!(matches!(
2110 parse_err(r#""abc"#),
2111 ParseError::IncompleteString(_, _, None),
2112 ));
2113 assert!(matches!(
2114 parse_err("(]"),
2115 ParseError::Unexpected(TokenType::CloseParen(Paren::Square), _, None)
2116 ));
2117 }
2118
2119 #[test]
2120 fn quote_multiple_args_should_err() {
2121 assert_parse_is_err("(quote a b c)");
2122 }
2123
2124 #[test]
2125 fn test_let_should_err() {
2126 assert_parse_is_err("(let)");
2127 assert_parse_is_err("(let (a) 10)");
2128 }
2129
2130 #[test]
2131 fn test_if_should_err() {
2132 assert_parse_is_err("(if)");
2133 assert_parse_is_err("(if 1)");
2134 assert_parse_is_err("(if 1 2 3 4)");
2136 }
2137
2138 #[test]
2139 fn test_define_should_err() {
2140 assert_parse_is_err("(define)");
2141 assert_parse_is_err("(define blagh)");
2142 assert_parse_is_err("(define test 1 2)");
2143 assert_parse_is_err("(define () test");
2144 }
2145
2146 #[test]
2147 fn test_lambda_should_err() {
2148 assert_parse_is_err("(lambda)");
2149 assert_parse_is_err("(lambda (x))");
2150 }
2151
2152 #[test]
2153 fn test_empty() {
2154 assert_parse("", &[]);
2155 assert_parse("()", &[ExprKind::List(List::new(vec![]))]);
2156 }
2157
2158 #[test]
2159 fn test_empty_quote_inside_if() {
2160 assert_parse(
2161 "(if #\\¡ (quote ()) #\\g)",
2162 &[ExprKind::If(Box::new(If::new(
2163 character('¡'),
2164 ExprKind::Quote(
2165 Quote::new(
2166 List::new(vec![]).into(),
2167 SyntaxObject::default(TokenType::Quote),
2168 )
2169 .into(),
2170 ),
2171 character('g'),
2172 SyntaxObject::default(TokenType::If),
2173 )))],
2174 )
2175 }
2176
2177 #[test]
2178 fn test_empty_quote() {
2179 assert_parse(
2180 "'()",
2181 &[ExprKind::Quote(
2182 Quote::new(
2183 List::new(vec![]).into(),
2184 SyntaxObject::default(TokenType::Quote),
2185 )
2186 .into(),
2187 )],
2188 )
2189 }
2190
2191 #[test]
2192 fn test_empty_quote_nested() {
2193 assert_parse(
2194 "(list '())",
2195 &[ExprKind::List(List::new(vec![
2196 atom("list"),
2197 ExprKind::Quote(
2198 Quote::new(
2199 List::new(vec![]).into(),
2200 SyntaxObject::default(TokenType::Quote),
2201 )
2202 .into(),
2203 ),
2204 ]))],
2205 )
2206 }
2207
2208 #[test]
2209 fn test_multi_parse_simple() {
2210 assert_parse("a b +", &[atom("a"), atom("b"), atom("+")]);
2211 }
2212
2213 #[test]
2214 fn test_multi_parse_complicated() {
2215 assert_parse(
2216 "a b (funcall 1 (+ 2 3.5))",
2217 &[
2218 atom("a"),
2219 atom("b"),
2220 ExprKind::List(List::new(vec![
2221 atom("funcall"),
2222 int(1),
2223 ExprKind::List(List::new(vec![
2224 atom("+"),
2225 int(2),
2226 ExprKind::Atom(Atom::new(SyntaxObject::default(
2227 RealLiteral::Float(3.5).into(),
2228 ))),
2229 ])),
2230 ])),
2231 ],
2232 )
2233 }
2234 #[test]
2235 fn test_parse_simple() {
2236 assert_parse(
2237 "(+ 1 2 3) (- 4 3)",
2238 &[
2239 ExprKind::List(List::new(vec![atom("+"), int(1), int(2), int(3)])),
2240 ExprKind::List(List::new(vec![atom("-"), int(4), int(3)])),
2241 ],
2242 );
2243 }
2244
2245 #[test]
2246 fn test_parse_nested() {
2247 assert_parse(
2248 "(+ 1 (foo (bar 2 3)))",
2249 &[ExprKind::List(List::new(vec![
2250 atom("+"),
2251 int(1),
2252 ExprKind::List(List::new(vec![
2253 atom("foo"),
2254 ExprKind::List(List::new(vec![atom("bar"), int(2), int(3)])),
2255 ])),
2256 ]))],
2257 );
2258 assert_parse(
2259 "(+ 1 (+ 2 3) (foo (bar 2 3)))",
2260 &[ExprKind::List(List::new(vec![
2261 atom("+"),
2262 int(1),
2263 ExprKind::List(List::new(vec![atom("+"), int(2), int(3)])),
2264 ExprKind::List(List::new(vec![
2265 atom("foo"),
2266 ExprKind::List(List::new(vec![atom("bar"), int(2), int(3)])),
2267 ])),
2268 ]))],
2269 );
2270 }
2271
2272 #[test]
2273 fn test_if() {
2274 assert_parse(
2275 "(+ 1 (if 2 3 4) (foo (+ (bar 1 1) 3) 5))",
2276 &[ExprKind::List(List::new(vec![
2277 atom("+"),
2278 int(1),
2279 ExprKind::If(Box::new(If::new(
2280 int(2),
2281 int(3),
2282 int(4),
2283 SyntaxObject::default(TokenType::If),
2284 ))),
2285 ExprKind::List(List::new(vec![
2286 atom("foo"),
2287 ExprKind::List(List::new(vec![
2288 atom("+"),
2289 ExprKind::List(List::new(vec![atom("bar"), int(1), int(1)])),
2290 int(3),
2291 ])),
2292 int(5),
2293 ])),
2294 ]))],
2295 );
2296 }
2297
2298 #[test]
2299 fn test_quote() {
2300 assert_parse(
2301 "(quote (if 1 2))",
2302 &[ExprKind::Quote(Box::new(Quote::new(
2303 ExprKind::List(List::new(vec![
2304 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2305 int(1),
2306 int(2),
2307 ])),
2308 SyntaxObject::default(TokenType::Quote),
2309 )))],
2310 )
2311 }
2312
2313 #[test]
2314 fn test_quote_shorthand() {
2315 assert_parse(
2316 "'(if 1 2)",
2317 &[ExprKind::Quote(Box::new(Quote::new(
2318 ExprKind::List(List::new(vec![
2319 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2320 int(1),
2321 int(2),
2322 ])),
2323 SyntaxObject::default(TokenType::Quote),
2324 )))],
2325 )
2326 }
2327
2328 #[test]
2329 fn test_quote_nested() {
2330 assert_parse(
2331 "(quote (if (if 1 2) 3))",
2332 &[ExprKind::Quote(Box::new(Quote::new(
2333 ExprKind::List(List::new(vec![
2334 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2335 ExprKind::List(List::new(vec![
2336 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2337 int(1),
2338 int(2),
2339 ])),
2340 int(3),
2341 ])),
2342 SyntaxObject::default(TokenType::Quote),
2343 )))],
2344 )
2345 }
2346
2347 #[test]
2348 fn test_quote_shorthand_nested() {
2349 assert_parse(
2350 "'(if (if 1 2) 3)",
2351 &[ExprKind::Quote(Box::new(Quote::new(
2352 ExprKind::List(List::new(vec![
2353 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2354 ExprKind::List(List::new(vec![
2355 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2356 int(1),
2357 int(2),
2358 ])),
2359 int(3),
2360 ])),
2361 SyntaxObject::default(TokenType::Quote),
2362 )))],
2363 )
2364 }
2365
2366 #[test]
2367 fn test_quote_shorthand_multiple_exprs() {
2368 assert_parse(
2369 "'(if (if 1 2) 3) (+ 1 (if 2 3 4) (foo (+ (bar 1 1) 3) 5))",
2370 &[
2371 ExprKind::Quote(Box::new(Quote::new(
2372 ExprKind::List(List::new(vec![
2373 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2374 ExprKind::List(List::new(vec![
2375 ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2376 int(1),
2377 int(2),
2378 ])),
2379 int(3),
2380 ])),
2381 SyntaxObject::default(TokenType::Quote),
2382 ))),
2383 ExprKind::List(List::new(vec![
2384 atom("+"),
2385 int(1),
2386 ExprKind::If(Box::new(If::new(
2387 int(2),
2388 int(3),
2389 int(4),
2390 SyntaxObject::default(TokenType::If),
2391 ))),
2392 ExprKind::List(List::new(vec![
2393 atom("foo"),
2394 ExprKind::List(List::new(vec![
2395 atom("+"),
2396 ExprKind::List(List::new(vec![atom("bar"), int(1), int(1)])),
2397 int(3),
2398 ])),
2399 int(5),
2400 ])),
2401 ])),
2402 ],
2403 )
2404 }
2405
2406 #[test]
2407 fn test_quote_inner() {
2408 assert_parse(
2409 "'(applesauce 'one)",
2410 &[ExprKind::Quote(Box::new(Quote::new(
2411 ExprKind::List(List::new(vec![
2412 atom("applesauce"),
2413 ExprKind::Quote(Box::new(Quote::new(
2414 atom("one"),
2415 SyntaxObject::default(TokenType::Quote),
2416 ))),
2417 ])),
2418 SyntaxObject::default(TokenType::Quote),
2419 )))],
2420 )
2421 }
2422
2423 #[test]
2424 fn test_quote_inner_without_shorthand() {
2425 assert_parse(
2426 "(quote (applesauce 'one))",
2427 &[ExprKind::Quote(Box::new(Quote::new(
2428 ExprKind::List(List::new(vec![
2429 atom("applesauce"),
2430 ExprKind::Quote(Box::new(Quote::new(
2431 atom("one"),
2432 SyntaxObject::default(TokenType::Quote),
2433 ))),
2434 ])),
2435 SyntaxObject::default(TokenType::Quote),
2436 )))],
2437 )
2438 }
2439
2440 #[test]
2441 fn test_quasiquote_shorthand() {
2442 assert_parse(
2443 "`(+ 1 2)",
2444 &[ExprKind::List(List::new(vec![
2445 atom("quasiquote"),
2446 ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2447 ]))],
2448 )
2449 }
2450
2451 #[test]
2452 fn test_quasiquote_normal() {
2453 assert_parse(
2454 "(quasiquote (+ 1 2))",
2455 &[ExprKind::List(List::new(vec![
2456 atom("quasiquote"),
2457 ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2458 ]))],
2459 )
2460 }
2461
2462 #[test]
2463 fn test_unquote_shorthand() {
2464 assert_parse(
2465 ",(+ 1 2)",
2466 &[ExprKind::List(List::new(vec![
2467 atom("unquote"),
2468 ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2469 ]))],
2470 )
2471 }
2472
2473 #[test]
2474 fn test_unquote_normal() {
2475 assert_parse(
2476 "(unquote (+ 1 2))",
2477 &[ExprKind::List(List::new(vec![
2478 atom("unquote"),
2479 ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2480 ]))],
2481 )
2482 }
2483
2484 #[test]
2485 fn test_unquote_splicing_shorthand() {
2486 assert_parse(
2487 ",@(+ 1 2)",
2488 &[ExprKind::List(List::new(vec![
2489 atom("unquote-splicing"),
2490 ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2491 ]))],
2492 )
2493 }
2494
2495 #[test]
2496 fn test_unquote_splicing_normal() {
2497 assert_parse(
2498 "(unquote-splicing (+ 1 2))",
2499 &[ExprKind::List(List::new(vec![
2500 atom("unquote-splicing"),
2501 ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2502 ]))],
2503 )
2504 }
2505
2506 #[test]
2507 fn test_define_simple() {
2508 assert_parse(
2509 "(define a 10)",
2510 &[ExprKind::Define(Box::new(Define::new(
2511 atom("a"),
2512 int(10),
2513 SyntaxObject::default(TokenType::Define),
2514 )))],
2515 )
2516 }
2517
2518 #[test]
2519 fn test_define_func_simple() {
2520 assert_parse(
2521 "(define (foo x) (+ x 10))",
2522 &[ExprKind::Define(Box::new(Define::new(
2523 atom("foo"),
2524 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2525 vec![atom("x")],
2526 ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
2527 SyntaxObject::default(TokenType::Lambda),
2528 ))),
2529 SyntaxObject::default(TokenType::Define),
2530 )))],
2531 )
2532 }
2533
2534 #[test]
2535 fn test_define_func_multiple_args() {
2536 assert_parse(
2537 "(define (foo x y z) (+ x 10))",
2538 &[ExprKind::Define(Box::new(Define::new(
2539 atom("foo"),
2540 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2541 vec![atom("x"), atom("y"), atom("z")],
2542 ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
2543 SyntaxObject::default(TokenType::Lambda),
2544 ))),
2545 SyntaxObject::default(TokenType::Define),
2546 )))],
2547 )
2548 }
2549
2550 #[test]
2551 fn test_define_func_multiple_args_multiple_body_exprs() {
2552 assert_parse(
2553 "(define (foo x y z) (+ x 10) (+ y 20) (+ z 30))",
2554 &[ExprKind::Define(Box::new(Define::new(
2555 atom("foo"),
2556 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2557 vec![atom("x"), atom("y"), atom("z")],
2558 ExprKind::Begin(Box::new(Begin::new(
2559 vec![
2560 ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
2561 ExprKind::List(List::new(vec![atom("+"), atom("y"), int(20)])),
2562 ExprKind::List(List::new(vec![atom("+"), atom("z"), int(30)])),
2563 ],
2564 SyntaxObject::default(TokenType::Begin),
2565 ))),
2566 SyntaxObject::default(TokenType::Lambda),
2567 ))),
2568 SyntaxObject::default(TokenType::Define),
2569 )))],
2570 )
2571 }
2572
2573 #[test]
2574 fn test_recursive_function() {
2575 assert_parse(
2576 "(define (test) (define (foo) (bar)) (define (bar) (foo)))",
2577 &[ExprKind::Define(Box::new(Define::new(
2578 atom("test"),
2579 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2580 vec![],
2581 ExprKind::Begin(Box::new(Begin::new(
2582 vec![
2583 ExprKind::Define(Box::new(Define::new(
2584 atom("foo"),
2585 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2586 vec![],
2587 ExprKind::List(List::new(vec![atom("bar")])),
2588 SyntaxObject::default(TokenType::Lambda),
2589 ))),
2590 SyntaxObject::default(TokenType::Define),
2591 ))),
2592 ExprKind::Define(Box::new(Define::new(
2593 atom("bar"),
2594 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2595 vec![],
2596 ExprKind::List(List::new(vec![atom("foo")])),
2597 SyntaxObject::default(TokenType::Lambda),
2598 ))),
2599 SyntaxObject::default(TokenType::Define),
2600 ))),
2601 ],
2602 SyntaxObject::default(TokenType::Begin),
2603 ))),
2604 SyntaxObject::default(TokenType::Lambda),
2605 ))),
2606 SyntaxObject::default(TokenType::Define),
2607 )))],
2608 )
2609 }
2610
2611 #[test]
2612 fn test_return_normal() {
2613 assert_parse(
2614 "(return! 10)",
2615 &[ExprKind::Return(Box::new(Return::new(
2616 int(10),
2617 SyntaxObject::default(TokenType::Return),
2618 )))],
2619 )
2620 }
2621
2622 #[test]
2623 fn test_begin() {
2624 assert_parse(
2625 "(begin 1 2 3)",
2626 &[ExprKind::Begin(Box::new(Begin::new(
2627 vec![int(1), int(2), int(3)],
2628 SyntaxObject::default(TokenType::Begin),
2629 )))],
2630 )
2631 }
2632
2633 #[test]
2634 fn test_lambda_function() {
2635 assert_parse(
2636 "(lambda (x) 10)",
2637 &[ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2638 vec![atom("x")],
2639 int(10),
2640 SyntaxObject::default(TokenType::Lambda),
2641 )))],
2642 )
2643 }
2644
2645 #[test]
2646 fn test_lambda_function_with_rest() {
2647 assert_parse(
2648 "(lambda (x . y) 10)",
2649 &[ExprKind::LambdaFunction(Box::new(
2650 LambdaFunction::new_maybe_rest(
2651 vec![atom("x"), atom("y")],
2652 int(10),
2653 SyntaxObject::default(TokenType::Lambda),
2654 true,
2655 ),
2656 ))],
2657 )
2658 }
2659
2660 #[test]
2661 fn test_lambda_function_with_rest_only() {
2662 assert_parse(
2663 "(lambda x 10)",
2664 &[ExprKind::LambdaFunction(Box::new(
2665 LambdaFunction::new_maybe_rest(
2666 vec![atom("x")],
2667 int(10),
2668 SyntaxObject::default(TokenType::Lambda),
2669 true,
2670 ),
2671 ))],
2672 )
2673 }
2674
2675 #[test]
2676 fn test_lambda_matches_let() {
2677 assert_parse(
2678 "((lambda (a) (+ a 20)) 10)",
2679 &[ExprKind::List(List::new(vec![
2680 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2681 vec![atom("a")],
2682 ExprKind::List(List::new(vec![atom("+"), atom("a"), int(20)])),
2683 SyntaxObject::default(TokenType::Lambda),
2684 ))),
2685 int(10),
2686 ]))],
2687 );
2688 }
2689
2690 #[test]
2691 fn test_let() {
2692 assert_parse(
2693 "(let ([a 10]) (+ a 20))",
2694 &[ExprKind::List(List::new(vec![
2695 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2696 vec![atom("a")],
2697 ExprKind::List(List::new(vec![atom("+"), atom("a"), int(20)])),
2698 SyntaxObject::default(TokenType::Lambda),
2699 ))),
2700 int(10),
2701 ]))],
2702 )
2703 }
2704
2705 #[test]
2706 fn test_quote_with_inner_nested() {
2707 assert_parse(
2708 "'(#f '())",
2709 &[ExprKind::Quote(
2710 Quote::new(
2711 ExprKind::List(List::new(vec![
2712 ExprKind::Atom(Atom::new(SyntaxObject::default(
2713 TokenType::BooleanLiteral(false),
2714 ))),
2715 ExprKind::Quote(
2716 Quote::new(
2717 List::new(vec![]).into(),
2718 SyntaxObject::default(TokenType::Quote),
2719 )
2720 .into(),
2721 ),
2722 ])),
2723 SyntaxObject::default(TokenType::Quote),
2724 )
2725 .into(),
2726 )],
2727 )
2728 }
2729
2730 #[test]
2731 fn test_quote_with_inner_nested_sub_expr() {
2732 assert_parse(
2733 "(if (null? contents)
2734 '(#f '())
2735 (list (car contents) (cdr contents)))",
2736 &[ExprKind::If(Box::new(If::new(
2737 ExprKind::List(List::new(vec![atom("null?"), atom("contents")])),
2738 ExprKind::Quote(
2739 Quote::new(
2740 ExprKind::List(List::new(vec![
2741 ExprKind::Atom(Atom::new(SyntaxObject::default(
2742 TokenType::BooleanLiteral(false),
2743 ))),
2744 ExprKind::Quote(
2745 Quote::new(
2746 List::new(vec![]).into(),
2747 SyntaxObject::default(TokenType::Quote),
2748 )
2749 .into(),
2750 ),
2751 ])),
2752 SyntaxObject::default(TokenType::Quote),
2753 )
2754 .into(),
2755 ),
2756 ExprKind::List(List::new(vec![
2757 atom("list"),
2758 ExprKind::List(List::new(vec![atom("car"), atom("contents")])),
2759 ExprKind::List(List::new(vec![atom("cdr"), atom("contents")])),
2760 ])),
2761 SyntaxObject::default(TokenType::If),
2762 )))],
2763 );
2764 }
2765
2766 #[test]
2767 fn test_quote_normal_with_inner_nested_sub_expr() {
2768 assert_parse(
2769 "(if (null? contents)
2770 (quote (#f '()))
2771 (list (car contents) (cdr contents)))",
2772 &[ExprKind::If(Box::new(If::new(
2773 ExprKind::List(List::new(vec![atom("null?"), atom("contents")])),
2774 ExprKind::Quote(
2775 Quote::new(
2776 ExprKind::List(List::new(vec![
2777 ExprKind::Atom(Atom::new(SyntaxObject::default(
2778 TokenType::BooleanLiteral(false),
2779 ))),
2780 ExprKind::Quote(
2781 Quote::new(
2782 List::new(vec![]).into(),
2783 SyntaxObject::default(TokenType::Quote),
2784 )
2785 .into(),
2786 ),
2787 ])),
2788 SyntaxObject::default(TokenType::Quote),
2789 )
2790 .into(),
2791 ),
2792 ExprKind::List(List::new(vec![
2793 atom("list"),
2794 ExprKind::List(List::new(vec![atom("car"), atom("contents")])),
2795 ExprKind::List(List::new(vec![atom("cdr"), atom("contents")])),
2796 ])),
2797 SyntaxObject::default(TokenType::If),
2798 )))],
2799 );
2800 }
2801
2802 #[test]
2803 fn test_quote_with_inner_sub_expr_even_more_nested() {
2804 assert_parse(
2805 "(list
2806 (if (null? contents)
2807 '(#f '())
2808 (list (car contents) (cdr contents))))",
2809 &[ExprKind::List(List::new(vec![
2810 atom("list"),
2811 ExprKind::If(Box::new(If::new(
2812 ExprKind::List(List::new(vec![atom("null?"), atom("contents")])),
2813 ExprKind::Quote(
2814 Quote::new(
2815 ExprKind::List(List::new(vec![
2816 ExprKind::Atom(Atom::new(SyntaxObject::default(
2817 TokenType::BooleanLiteral(false),
2818 ))),
2819 ExprKind::Quote(
2820 Quote::new(
2821 List::new(vec![]).into(),
2822 SyntaxObject::default(TokenType::Quote),
2823 )
2824 .into(),
2825 ),
2826 ])),
2827 SyntaxObject::default(TokenType::Quote),
2828 )
2829 .into(),
2830 ),
2831 ExprKind::List(List::new(vec![
2832 atom("list"),
2833 ExprKind::List(List::new(vec![atom("car"), atom("contents")])),
2834 ExprKind::List(List::new(vec![atom("cdr"), atom("contents")])),
2835 ])),
2836 SyntaxObject::default(TokenType::If),
2837 ))),
2838 ]))],
2839 );
2840 }
2841
2842 #[test]
2843 fn test_define_with_datum_syntax_name() {
2844 assert_parse(
2845 "(define (datum->syntax var) (car ret-value))",
2846 &[ExprKind::Define(Box::new(Define::new(
2847 ExprKind::List(List::new(vec![atom("datum->syntax"), atom("var")])),
2848 ExprKind::List(List::new(vec![atom("car"), atom("ret-value")])),
2849 SyntaxObject::default(TokenType::Define),
2850 )))],
2851 )
2852 }
2853
2854 #[test]
2855 fn test_define_with_datum_syntax_function_name() {
2856 assert_parse(
2857 "(define ((datum->syntax var) arg) 10)",
2858 &[ExprKind::Define(Box::new(Define::new(
2859 ExprKind::List(List::new(vec![atom("datum->syntax"), atom("var")])),
2860 ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2861 vec![atom("arg")],
2862 int(10),
2863 SyntaxObject::default(TokenType::Lambda),
2864 ))),
2865 SyntaxObject::default(TokenType::Define),
2866 )))],
2867 )
2868 }
2869
2870 #[test]
2871 fn test_parse_without_lowering_ast() {
2872 let a: Result<Vec<ExprKind>> =
2873 Parser::new_flat("(define (quote a) 10) (require foo bar)", SourceId::none())
2874 .map(|x| x.and_then(lower_macro_and_require_definitions))
2875 .collect();
2876
2877 let a = a.unwrap();
2878
2879 println!("{:#?}", a);
2880 }
2881
2882 #[test]
2883 fn test_delayed_lowering() {
2884 let a: Result<Vec<ExprKind>> = Parser::new_flat(
2885 r#"
2886 ;; (define foo (quote a)) (require foo bar)
2887
2888 ;; (define (foo) (if 10 20 30))
2889
2890 ;; (define (foo) (quote (define 10 20)))
2891
2892 ;; (define foo '())
2893
2894 (define-syntax
2895 with-handler
2896 (syntax-rules
2897 ()
2898 ((with-handler handler expr)
2899 (reset
2900 (call-with-exception-handler
2901 (λ (err)
2902 (begin (handler err) (shift k (k void))))
2903 (λ ()
2904 expr))))
2905 ((with-handler handler expr ...)
2906 (reset
2907 (call-with-exception-handler
2908 (λ (err)
2909 (begin (handler err) (shift k (k void))))
2910 (λ ()
2911 (begin expr ...)))))))
2912
2913
2914
2915 "#,
2916 SourceId::none(),
2917 )
2918 .map(|x| x.and_then(lower_macro_and_require_definitions))
2919 .map(|x| {
2920 x.and_then(|mut expr| {
2921 lower_entire_ast(&mut expr)?;
2922 Ok(expr)
2923 })
2924 })
2925 .collect();
2926
2927 let a = a.unwrap();
2928
2929 println!("{:#?}", a);
2930 }
2931
2932 #[test]
2933 fn test_improper_list() {
2934 let mut pair = List::new(vec![atom("x"), atom("y")]);
2935 pair.make_improper();
2936
2937 assert_parse("(x . y)", &[ExprKind::List(pair)]);
2938
2939 assert_parse(
2940 "(x . (y . ()))",
2941 &[ExprKind::List(List::new(vec![atom("x"), atom("y")]))],
2942 )
2943 }
2944
2945 #[test]
2946 fn test_improper_list_failures() {
2947 assert_syntax_err(
2948 "(. a)",
2949 "improper lists must have a car element before the dot",
2950 );
2951 assert_syntax_err("(a .)", "improper list must have a single cdr");
2952 assert_syntax_err("(a . b . )", "improper lists can only have a single dot");
2953 assert_syntax_err("(a . b . c)", "improper lists can only have a single dot");
2954 assert_syntax_err("(a . b c)", "improper list must have a single cdr");
2955 assert_syntax_err("(a . b (c))", "improper list must have a single cdr");
2956 }
2957
2958 #[test]
2959 fn test_vectors() {
2960 assert_parse(
2961 "#(a b)",
2962 &[ExprKind::Vector(Vector {
2963 args: vec![atom("a"), atom("b")],
2964 bytes: false,
2965 span: Span::default(),
2966 })],
2967 );
2968
2969 assert_parse(
2970 "#u8(1 3)",
2971 &[ExprKind::Vector(Vector {
2972 args: vec![int(1), int(3)],
2973 bytes: true,
2974 span: Span::default(),
2975 })],
2976 );
2977 }
2978
2979 #[test]
2980 fn test_malformed_vectors() {
2981 assert_syntax_err(
2982 "#u8(#\\a)",
2983 "bytevector literals can only contain integer literals in the 0-255 range",
2984 );
2985
2986 assert_syntax_err(
2987 "#u8(())",
2988 "bytevector literals can only contain integer literals in the 0-255 range",
2989 );
2990
2991 assert_syntax_err("#u8(1 . 2)", "bytevector literals cannot contain dots");
2992
2993 assert_syntax_err("#(1 . 2)", "vector literals cannot contain dots");
2994 }
2995
2996 #[test]
2997 fn test_datum_comments() {
2998 assert_parse("#; 1 2", &[int(2)]);
2999
3000 assert_parse("#; #; #false (2) 3", &[int(3)]);
3001
3002 assert_parse("#; ,@foo 4", &[int(4)]);
3003
3004 assert_parse(
3005 "(1 #; #(a b c) 2)",
3006 &[ExprKind::List(List::new(vec![int(1), int(2)]))],
3007 )
3008 }
3009
3010 #[test]
3011 fn test_invalid_datum_comments() {
3012 assert_syntax_err("( 1 #; )", "invalid datum comment");
3013
3014 assert_syntax_err(
3015 "( 1 2 #; . b)",
3016 "commented-out datum cannot start with a dot",
3017 );
3018 }
3019}