Skip to main content

ruschm/parser/
parser.rs

1#![allow(dead_code)]
2use super::{
3    lexer::Lexer,
4    pair::GenericPair,
5    pair::{PairIterItem, Pairable},
6    Datum, DatumBody, DatumList, Result, SyntaxTemplateElement, Transformer,
7};
8use crate::error::ToLocated;
9use crate::{environment::LexicalScope, error::*, parser::lexer::Token};
10use crate::{interpreter::error::LogicError, parser::lexer::TokenData};
11use fmt::Display;
12use itertools::Itertools;
13use std::{collections::HashSet, fmt, mem, rc::Rc};
14use std::{
15    iter::{repeat, FromIterator, Iterator, Peekable},
16    path::PathBuf,
17};
18
19use either::Either;
20
21use super::{
22    error::SyntaxError, Primitive, SyntaxPattern, SyntaxPatternBody, SyntaxTemplate,
23    SyntaxTemplateBody, UserDefinedTransformer,
24};
25
26pub type ParseResult = Result<Option<(Statement, Option<[u32; 2]>)>>;
27
28#[derive(PartialEq, Debug, Clone)]
29pub struct LibraryDefinition(pub LibraryName, pub Vec<Located<LibraryDeclaration>>);
30impl ToLocated for LibraryDefinition {}
31#[derive(PartialEq, Debug, Clone)]
32pub enum LibraryDeclaration {
33    ImportDeclaration(Located<ImportDeclaration>),
34    Export(Vec<Located<ExportSpec>>),
35    Begin(Vec<Statement>),
36}
37impl ToLocated for LibraryDeclaration {}
38
39// r7rs:
40// ⟨library name⟩ is a list whose members are identifiers and
41// exact non-negative integers.
42#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
43pub enum LibraryNameElement {
44    Identifier(String),
45    Integer(u32),
46}
47
48impl ToLocated for LibraryNameElement {}
49
50impl Display for LibraryNameElement {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        match self {
53            LibraryNameElement::Identifier(s) => write!(f, "{}", s),
54            LibraryNameElement::Integer(i) => write!(f, "{}", i),
55        }
56    }
57}
58
59impl From<&str> for LibraryNameElement {
60    fn from(s: &str) -> Self {
61        Self::Identifier(s.to_string())
62    }
63}
64
65impl From<u32> for LibraryNameElement {
66    fn from(i: u32) -> Self {
67        Self::Integer(i)
68    }
69}
70
71#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
72pub struct LibraryName(pub Vec<LibraryNameElement>);
73
74#[macro_export]
75macro_rules! library_name {
76    ($($e:expr),+) => {
77        LibraryName(vec![$($e.into()),+])
78    };
79}
80
81impl ToLocated for LibraryName {}
82
83impl FromIterator<LibraryNameElement> for LibraryName {
84    fn from_iter<T: IntoIterator<Item = LibraryNameElement>>(iter: T) -> Self {
85        Self(iter.into_iter().collect::<Vec<_>>())
86    }
87}
88
89impl From<Vec<LibraryNameElement>> for LibraryName {
90    fn from(value: Vec<LibraryNameElement>) -> Self {
91        Self(value)
92    }
93}
94impl From<LibraryNameElement> for LibraryName {
95    fn from(value: LibraryNameElement) -> Self {
96        Self(vec![value])
97    }
98}
99
100impl Display for LibraryName {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        write!(f, "({})", self.0.iter().join(" "))
103    }
104}
105#[test]
106fn library_name_display() {
107    assert_eq!(format!("{}", library_name!("foo", 0, "bar")), "(foo 0 bar)");
108    assert_eq!(format!("{}", library_name!(1, 0, 2)), "(1 0 2)");
109}
110impl LibraryName {
111    pub fn join(self, other: impl Into<Self>) -> Self {
112        Self(
113            self.0
114                .into_iter()
115                .chain(other.into().0.into_iter())
116                .collect(),
117        )
118    }
119}
120#[test]
121fn library_name_join() {
122    assert_eq!(
123        library_name!("a", "b").join(library_name!("c")),
124        library_name!("a", "b", "c")
125    );
126    assert_eq!(
127        library_name!("a", "b").join(LibraryNameElement::Integer(0)),
128        library_name!("a", "b", 0)
129    );
130}
131
132impl LibraryName {
133    pub fn path(&self) -> PathBuf {
134        self.0
135            .iter()
136            .map(|element| PathBuf::from(format!("{}", element)))
137            .collect()
138    }
139}
140
141#[derive(PartialEq, Debug, Clone)]
142pub enum ExportSpec {
143    Direct(String),
144    Rename(String, String),
145}
146impl ToLocated for ExportSpec {}
147#[derive(PartialEq, Debug, Clone)]
148pub struct ImportDeclaration(pub Vec<ImportSet>);
149
150impl ToLocated for ImportDeclaration {}
151
152#[derive(PartialEq, Debug, Clone)]
153pub enum Statement {
154    ImportDeclaration(Located<ImportDeclaration>),
155    Definition(Definition),
156    SyntaxDefinition(SyntaxDef),
157    Expression(Expression),
158    LibraryDefinition(Located<LibraryDefinition>),
159}
160
161impl Statement {
162    pub fn location(&self) -> Option<[u32; 2]> {
163        match self {
164            Statement::ImportDeclaration(located) => located.location,
165            Statement::Definition(located) => located.location,
166            Statement::SyntaxDefinition(located) => located.location,
167            Statement::Expression(located) => located.location,
168            Statement::LibraryDefinition(located) => located.location,
169        }
170    }
171    pub fn expect_expression(self) -> Result<Expression> {
172        let location = self.location();
173        match self {
174            Self::Expression(expression) => Ok(expression),
175            _ => located_error!(
176                SyntaxError::ExpectSomething("expression".to_string(), "other".to_string()),
177                location
178            ),
179        }
180    }
181}
182
183impl Into<Statement> for Expression {
184    fn into(self) -> Statement {
185        Statement::Expression(self)
186    }
187}
188
189impl Into<Statement> for SyntaxDef {
190    fn into(self) -> Statement {
191        Statement::SyntaxDefinition(self)
192    }
193}
194
195impl Into<Statement> for Definition {
196    fn into(self) -> Statement {
197        Statement::Definition(self)
198    }
199}
200
201impl Into<Statement> for Located<ImportDeclaration> {
202    fn into(self) -> Statement {
203        Statement::ImportDeclaration(self)
204    }
205}
206
207impl Into<Statement> for Located<LibraryDefinition> {
208    fn into(self) -> Statement {
209        Statement::LibraryDefinition(self)
210    }
211}
212
213#[derive(PartialEq, Debug, Clone)]
214pub struct DefinitionBody(pub String, pub Expression);
215
216impl ToLocated for DefinitionBody {}
217
218#[derive(PartialEq, Debug, Clone)]
219pub struct SyntaxDefBody(pub String, pub UserDefinedTransformer);
220
221impl ToLocated for SyntaxDefBody {}
222
223pub type Definition = Located<DefinitionBody>;
224pub type SyntaxDef = Located<SyntaxDefBody>;
225pub type ImportSet = Located<ImportSetBody>;
226
227#[derive(PartialEq, Debug, Clone)]
228pub enum ImportSetBody {
229    Direct(Located<LibraryName>),
230    Only(Box<ImportSet>, Vec<String>),
231    Except(Box<ImportSet>, Vec<String>),
232    Prefix(Box<ImportSet>, String),
233    Rename(Box<ImportSet>, Vec<(String, String)>),
234}
235
236impl ToLocated for ImportSetBody {}
237
238pub type Expression = Located<ExpressionBody>;
239#[derive(PartialEq, Debug, Clone)]
240pub enum ExpressionBody {
241    Symbol(String),
242    Primitive(Primitive),
243    Period,
244    Assignment(String, Box<Expression>),
245    Procedure(SchemeProcedure),
246    ProcedureCall(Box<Expression>, Vec<Expression>),
247    Conditional(Box<(Expression, Expression, Option<Expression>)>),
248    Quote(Box<Datum>),
249    Datum(Datum),
250}
251
252impl From<i32> for ExpressionBody {
253    fn from(integer: i32) -> Self {
254        ExpressionBody::Datum(DatumBody::Primitive(Primitive::Integer(integer)).into())
255    }
256}
257
258impl ToLocated for ExpressionBody {}
259
260impl From<Primitive> for ExpressionBody {
261    fn from(p: Primitive) -> Self {
262        ExpressionBody::Primitive(p)
263    }
264}
265
266impl From<Primitive> for Expression {
267    fn from(p: Primitive) -> Self {
268        ExpressionBody::Primitive(p).into()
269    }
270}
271
272#[derive(PartialEq, Debug, Clone)]
273pub enum ParameterFormalsBody {
274    Name(String),                             // (lambda x ...) or (define (f . x) ...)
275    Pair(Box<GenericPair<ParameterFormals>>), // (lambda (...) ...) or (define (f ...) ...)
276}
277
278pub type ParameterFormals = Located<ParameterFormalsBody>;
279
280impl ToLocated for ParameterFormalsBody {}
281
282impl ParameterFormals {
283    pub fn new_non_located(parameters: impl Iterator<Item = String>, last: Option<String>) -> Self {
284        ParameterFormals::from_pair_iter(
285            parameters
286                .map(|s| PairIterItem::Proper(ParameterFormalsBody::Name(s).no_locate()))
287                .chain(last.into_iter().map(|last| {
288                    PairIterItem::Improper(ParameterFormalsBody::Name(last).no_locate())
289                })),
290        )
291    }
292
293    pub fn split(self) -> Result<(Vec<String>, Option<String>)> {
294        Ok(match self.data {
295            ParameterFormalsBody::Name(name) => (Vec::new(), Some(name)),
296            ParameterFormalsBody::Pair(pair) => {
297                let mut proper_list = Vec::new();
298                let mut cdr = None;
299                for item in pair.into_pair_iter() {
300                    match item {
301                        PairIterItem::Proper(ParameterFormals {
302                            data: ParameterFormalsBody::Name(fixed),
303                            ..
304                        }) => proper_list.push(fixed),
305                        PairIterItem::Improper(ParameterFormals {
306                            data: ParameterFormalsBody::Name(last),
307                            ..
308                        }) => cdr = Some(last),
309                        other => {
310                            return located_error!(
311                                SyntaxError::IllegalParameter(other.get_inside()),
312                                other.get_inside().location
313                            );
314                        }
315                    }
316                }
317                (proper_list, cdr)
318            }
319        })
320    }
321
322    pub fn len(&self) -> (usize, bool) {
323        let mut fixed = 0;
324        let variadic = self.iter_to_last(|_| fixed += 1).is_some();
325        (fixed, variadic)
326    }
327
328    pub fn as_name(&self) -> String {
329        match &self.data {
330            ParameterFormalsBody::Name(name) => name.clone(),
331            ParameterFormalsBody::Pair(_) => {
332                unreachable!("parameter name can only be a identifier")
333            }
334        }
335    }
336
337    pub fn iter_to_last(
338        &self,
339        mut visitor: impl FnMut(&ParameterFormals) -> (),
340    ) -> Option<&ParameterFormals> {
341        let mut next: Option<&ParameterFormals> = Some(self);
342        loop {
343            match next.take().map(|p| p.either_pair_ref()) {
344                Some(Either::Left(GenericPair::Some(car, cdr))) => {
345                    visitor(&car);
346                    next = Some(&cdr);
347                }
348                Some(Either::Right(improper)) => return Some(&improper),
349                None | Some(Either::Left(GenericPair::Empty)) => return None,
350            }
351        }
352    }
353
354    pub fn append(&mut self, mut x: ParameterFormals) -> Result<()> {
355        let mut next = self as *mut ParameterFormals;
356        loop {
357            match unsafe { &mut *next }.either_pair_mut() {
358                Either::Left(GenericPair::Some(_, cdr)) => {
359                    next = cdr as *mut ParameterFormals;
360                }
361                Either::Right(improper) => {
362                    return error!(LogicError::InproperList(improper.to_string()))
363                }
364                _empty => {
365                    mem::swap(&mut x, unsafe { &mut *next });
366                    break Ok(());
367                }
368            }
369        }
370    }
371}
372
373impl Pairable for ParameterFormals {
374    impl_located_pairable!(ParameterFormalsBody);
375}
376
377#[macro_export]
378macro_rules! param_fixed {
379    ($($x:expr),+) => {{
380        use $crate::error::ToLocated;
381        use $crate::parser::ParameterFormalsBody;
382        use $crate::parser::ParameterFormals;
383        use $crate::parser::pair::GenericPair;
384        use $crate::list;
385        ParameterFormals::from(list![$(ParameterFormalsBody::Name($x.to_string()).no_locate()),*])
386}};
387    () => {
388        ParameterFormals::from(list![])
389    }
390}
391
392#[macro_export]
393macro_rules! append_variadic_param {
394    ($fixed:expr, $append:expr) => {{
395        let mut pair = $fixed;
396        use $crate::error::ToLocated;
397        use $crate::parser::ParameterFormalsBody;
398        pair.append(ParameterFormalsBody::Name($append.to_string()).no_locate())?;
399        pair
400    }};
401}
402
403impl From<GenericPair<ParameterFormals>> for ParameterFormals {
404    fn from(pair: GenericPair<ParameterFormals>) -> Self {
405        ParameterFormalsBody::Pair(Box::new(pair)).no_locate()
406    }
407}
408
409impl Display for ParameterFormalsBody {
410    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
411        match self {
412            ParameterFormalsBody::Name(s) => write!(f, "{}", s),
413            ParameterFormalsBody::Pair(pair) => write!(f, "{}", pair),
414        }
415    }
416}
417
418#[test]
419fn test_parameter_formals() -> Result<()> {
420    let test_cases = vec![
421        (
422            vec!["x1".to_string(), "x2".to_string(), "x3".to_string()],
423            Some("x".to_string()),
424        ),
425        (
426            vec!["x1".to_string(), "x2".to_string(), "x3".to_string()],
427            None,
428        ),
429        (vec![], Some("x".to_string())),
430        (vec![], None),
431    ];
432
433    for (fixed, variadic) in test_cases.into_iter() {
434        let parameters =
435            ParameterFormals::new_non_located(fixed.clone().into_iter(), variadic.clone());
436        assert_eq!(parameters.split()?, (fixed.clone(), variadic.clone()));
437    }
438
439    Ok(())
440}
441
442#[derive(PartialEq, Debug, Clone)]
443pub struct SchemeProcedure(
444    pub ParameterFormals,
445    pub Vec<Definition>,
446    pub Vec<Expression>,
447);
448
449impl SchemeProcedure {
450    pub fn get_body_location(&self) -> Option<[u32; 2]> {
451        let SchemeProcedure(_, defs, exprs) = self;
452        defs.first()
453            .and_then(|d| d.location)
454            .or(exprs.first().and_then(|e| e.location))
455    }
456}
457
458impl fmt::Display for SchemeProcedure {
459    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
460        let SchemeProcedure(formals, ..) = self;
461        write!(f, "(lambda {})", formals,)
462    }
463}
464
465pub struct Parser<TokenIter: Iterator<Item = Result<Token>>> {
466    pub current: Option<Token>,
467    pub lexer: Peekable<TokenIter>,
468    pub syntax_env: Rc<LexicalScope<Transformer>>,
469    location: Option<[u32; 2]>,
470}
471
472impl<TokenIter: Iterator<Item = Result<Token>>> Iterator for Parser<TokenIter> {
473    type Item = Result<Statement>;
474    fn next(&mut self) -> Option<Self::Item> {
475        match self.parse(self.syntax_env.clone()) {
476            Ok(Some(statement)) => Some(Ok(statement)),
477            Ok(None) => None,
478            Err(e) => Some(Err(e)),
479        }
480    }
481}
482
483fn create_syntax_binding() -> Rc<LexicalScope<Transformer>> {
484    thread_local! {static BINDINGS: Rc<LexicalScope<Transformer>> = {
485            let mut parser = Parser::from_lexer_primary_syntax(Lexer::from_char_stream(
486                include_str!("grammar.sld").chars(),
487            ));
488            while parser.next().is_some() {} // force consume the parser iterator to bind all syntax.
489            parser.syntax_env
490        };
491    }
492    BINDINGS.with(|bindings| bindings.clone())
493}
494
495impl<TokenIter: Iterator<Item = Result<Token>>> Parser<TokenIter> {
496    fn from_lexer_primary_syntax(lexer: TokenIter) -> Parser<TokenIter> {
497        Self {
498            current: None,
499            lexer: lexer.peekable(),
500            syntax_env: Rc::new(LexicalScope::new()),
501            location: None,
502        }
503    }
504
505    pub fn from_lexer(lexer: TokenIter) -> Parser<TokenIter> {
506        Self {
507            current: None,
508            lexer: lexer.peekable(),
509            syntax_env: create_syntax_binding(),
510            location: None,
511        }
512    }
513
514    pub fn parse_current(
515        &mut self,
516        syntax_env: &Rc<LexicalScope<Transformer>>,
517    ) -> Result<Option<Statement>> {
518        Ok(match self.current_datum()? {
519            Some(datum) => Some(Self::transform_to_statement(datum, syntax_env)?),
520            None => None,
521        })
522    }
523
524    pub fn transform_to_statement(
525        datum: Datum,
526        syntax_env: &Rc<LexicalScope<Transformer>>,
527    ) -> Result<Statement> {
528        let location = datum.location;
529        Ok(match datum.data {
530            DatumBody::Primitive(p) => ExpressionBody::Primitive(p).locate(location).into(),
531            DatumBody::Symbol(s) => ExpressionBody::Symbol(s).locate(location).into(),
532            DatumBody::Pair(mut pair) => {
533                let first = pair.pop_proper()?;
534                match first {
535                    None => return error!(SyntaxError::EmptyCall),
536                    Some(first) => {
537                        match &first.data {
538                            DatumBody::Symbol(keyword) => match keyword.as_str() {
539                                "define" => {
540                                    Self::transform_definition(pair.into_iter(), syntax_env)?
541                                        .locate(datum.location)
542                                        .into()
543                                }
544                                "define-library" => {
545                                    Self::transform_library(pair.into_iter(), syntax_env)?
546                                        .locate(datum.location)
547                                        .into()
548                                }
549                                "lambda" => Self::transform_lambda(pair.into_iter(), syntax_env)?
550                                    .locate(datum.location)
551                                    .into(),
552                                "if" => Self::transform_condition(pair.into_iter(), syntax_env)?
553                                    .locate(datum.location)
554                                    .into(),
555                                "import" => Self::transform_import_decl(pair.into_iter())?
556                                    .locate(datum.location)
557                                    .into(),
558                                "quote" => Self::transform_quote(pair.into_iter())?
559                                    .locate(datum.location)
560                                    .into(),
561                                "set!" => Self::transform_assignment(pair.into_iter(), syntax_env)?
562                                    .locate(datum.location)
563                                    .into(),
564                                "define-syntax" => {
565                                    Self::transform_syntax_definition(pair.into_iter(), syntax_env)?
566                                        .locate(datum.location)
567                                        .into()
568                                }
569                                keyword => {
570                                    if let Some(transformer) =
571                                        syntax_env.get(&first.expect_symbol()?)
572                                    {
573                                        let remained = DatumBody::Pair(pair).locate(location);
574                                        let expanded_datum =
575                                            transformer.transform(keyword, remained)?;
576                                        Self::transform_to_statement(expanded_datum, syntax_env)?
577                                    } else {
578                                        Self::transform_procedure_call(
579                                            first,
580                                            pair.into_iter(),
581                                            syntax_env,
582                                        )?
583                                        .locate(datum.location)
584                                        .into()
585                                    }
586                                }
587                            },
588                            // Lambda expression
589                            _ => {
590                                Self::transform_procedure_call(first, pair.into_iter(), syntax_env)?
591                                    .locate(datum.location)
592                                    .into()
593                            }
594                        }
595                    }
596                }
597            }
598            other => ExpressionBody::Datum(Datum {
599                data: other,
600                location,
601            })
602            .locate(location)
603            .into(),
604        })
605    }
606
607    pub fn transform_to_expression(
608        datum: Datum,
609        syntax_env: &Rc<LexicalScope<Transformer>>,
610    ) -> Result<Expression> {
611        match Self::transform_to_statement(datum, syntax_env)? {
612            Statement::Expression(expression) => Ok(expression),
613            _ => error!(SyntaxError::ExpectSomething(
614                "expression".to_string(),
615                "other statement".to_string(),
616            )),
617        }
618    }
619
620    pub fn current_datum(&mut self) -> Result<Option<Datum>> {
621        match self.current.take() {
622            None => Ok(None),
623            Some(current) => match current {
624                Token { data, location } => Ok(match data {
625                    TokenData::Primitive(p) => Datum {
626                        data: DatumBody::Primitive(p),
627                        location,
628                    }
629                    .into(),
630                    TokenData::Identifier(a) => Datum {
631                        data: DatumBody::Symbol(a),
632                        location,
633                    }
634                    .into(),
635                    TokenData::LeftParen => Some(self.current_list_or_pair()?),
636                    TokenData::RightParen => {
637                        return located_error!(SyntaxError::UnmatchedParentheses, location)
638                    }
639                    TokenData::VecConsIntro => self.vector()?.into(),
640                    TokenData::Quote => {
641                        self.advance(1)?;
642                        self.parse_quoted()?
643                    }
644                    .into(),
645                    other => return located_error!(SyntaxError::UnexpectedToken(other), location),
646                }),
647            },
648        }
649    }
650
651    pub fn unwrap_non_end<T>(op: Option<T>) -> Result<T> {
652        op.ok_or(ErrorData::from(SyntaxError::UnexpectedEnd).no_locate())
653    }
654
655    pub fn current_list_or_pair(&mut self) -> Result<Datum> {
656        let mut head = Box::new(DatumList::Empty);
657        let mut tail = head.as_mut();
658        let list_location = self.location;
659        let mut encounter_period = false;
660        loop {
661            match self.advance_unwrap(1)? {
662                Token { data, location } => match data {
663                    TokenData::Period => {
664                        if encounter_period {
665                            return located_error!(
666                                SyntaxError::UnexpectedToken(TokenData::Period),
667                                location.clone()
668                            );
669                        }
670                        encounter_period = true;
671                        continue;
672                    }
673                    TokenData::RightParen => break,
674                    _ => {
675                        let element = Self::unwrap_non_end(self.current_datum()?)?;
676                        match tail {
677                            DatumList::Empty => {
678                                head = Box::new(DatumList::Some(
679                                    element,
680                                    Datum::from(DatumList::Empty),
681                                ));
682                                tail = head.as_mut();
683                            }
684                            DatumList::Some(_, cdr) => {
685                                if encounter_period {
686                                    *cdr = element;
687                                    self.expect_next_nth(1, TokenData::RightParen)?;
688                                    break;
689                                }
690                                assert_eq!(*cdr, Datum::from(DatumList::Empty));
691                                let new_tail =
692                                    DatumList::Some(element, Datum::from(DatumList::Empty));
693                                *cdr = Datum::from(new_tail);
694                                tail = cdr.either_pair_mut().left().unwrap();
695                            }
696                        }
697                    }
698                },
699            }
700        }
701        Ok(DatumBody::Pair(head).locate(list_location))
702    }
703
704    pub fn parse_root(&mut self) -> Result<Option<Statement>> {
705        self.parse(self.syntax_env.clone())
706    }
707
708    fn statement(&mut self, syntax_env: &Rc<LexicalScope<Transformer>>) -> Result<Statement> {
709        match self.parse_current(syntax_env)? {
710            Some(statement) => Ok(statement),
711            None => located_error!(SyntaxError::UnexpectedEnd, self.location),
712        }
713    }
714    pub fn parse(
715        &mut self,
716        syntax_env: Rc<LexicalScope<Transformer>>,
717    ) -> Result<Option<Statement>> {
718        self.advance(1)?;
719        self.parse_current(&syntax_env)
720    }
721
722    fn transform_library(
723        mut datums: impl Iterator<Item = Datum>,
724        syntax_env: &Rc<LexicalScope<Transformer>>,
725    ) -> Result<LibraryDefinition> {
726        let library_name = Self::transform_library_name(
727            Self::unwrap_non_end(datums.next())?
728                .expect_list()?
729                .into_iter(),
730        )?;
731        let library_declarations = datums
732            .map(|datum| Self::transform_library_declaration(datum, syntax_env))
733            .collect::<Result<_>>()?;
734        Ok(LibraryDefinition(library_name, library_declarations))
735    }
736
737    fn transform_library_declaration(
738        datum: Datum,
739        syntax_env: &Rc<LexicalScope<Transformer>>,
740    ) -> Result<Located<LibraryDeclaration>> {
741        let location = datum.location;
742        let mut iter = datum.expect_list()?.into_iter().peekable();
743        Ok(match &Self::unwrap_non_end(iter.peek())?.data {
744            DatumBody::Symbol(first) if first == "export" => LibraryDeclaration::Export(
745                iter.skip(1)
746                    .map(Self::transform_export_spec)
747                    .collect::<Result<_>>()?,
748            ),
749            DatumBody::Symbol(first) if first == "begin" => LibraryDeclaration::Begin(
750                iter.skip(1)
751                    .map(|datum| Self::transform_to_statement(datum, syntax_env))
752                    .collect::<Result<_>>()?,
753            ),
754            _ => LibraryDeclaration::ImportDeclaration(
755                Self::transform_import_decl(iter.skip(1))?.locate(location),
756            ),
757        }
758        .locate(location))
759    }
760
761    fn transform_export_spec(datum: Datum) -> Result<Located<ExportSpec>> {
762        Ok(match datum.data {
763            DatumBody::Symbol(ident) => ExportSpec::Direct(ident),
764            DatumBody::Pair(list) => {
765                let mut iter = list.into_iter();
766                match Self::unwrap_non_end(iter.next())? {
767                    Datum {
768                        data: DatumBody::Symbol(ident),
769                        ..
770                    } if ident == "rename" => (),
771                    o => return error!(SyntaxError::UnexpectedDatum(o)),
772                };
773                ExportSpec::Rename(
774                    Self::transform_identifier(Self::unwrap_non_end(iter.next())?)?,
775                    Self::transform_identifier(Self::unwrap_non_end(iter.next())?)?,
776                )
777            }
778            _ => return error!(SyntaxError::UnexpectedDatum(datum)),
779        }
780        .locate(datum.location))
781    }
782
783    fn transform_identifier(datum: Datum) -> Result<String> {
784        match datum.data {
785            DatumBody::Symbol(ident) => Ok(ident.clone()),
786            other => located_error!(
787                SyntaxError::ExpectSomething("identifier".to_string(), other.to_string()),
788                datum.location
789            ),
790        }
791    }
792
793    fn transform_identifier_pair(datum: Datum) -> Result<(String, String)> {
794        let mut iter = datum.expect_list()?.into_iter();
795        let car = Self::transform_identifier(Self::unwrap_non_end(iter.next())?)?;
796        let cdr = Self::transform_identifier(Self::unwrap_non_end(iter.next())?)?;
797        Ok((car, cdr))
798    }
799
800    fn expect_next_nth(&mut self, n: usize, tobe: TokenData) -> Result<()> {
801        match self.advance_unwrap(n)? {
802            Token { data, .. } if data == &tobe => Ok(()),
803            Token { data, .. } => located_error!(
804                SyntaxError::TokenMisMatch(tobe, Some(data.clone())),
805                self.location
806            ),
807        }
808    }
809
810    // a lazy parser combinator to repeat the given parser
811    fn repeat<'a, T>(
812        &'a mut self,
813        get_element: fn(&mut Self) -> Result<T>,
814    ) -> impl Iterator<Item = Result<T>> + 'a
815    where
816        T: std::fmt::Debug + 'a,
817    {
818        repeat(())
819            .map(move |_| match self.peek_next_token()?.map(|t| &t.data) {
820                Some(TokenData::RightParen) => {
821                    self.advance(1)?;
822                    Ok(None)
823                }
824                None => located_error!(SyntaxError::UnexpectedEnd, self.location),
825                _ => {
826                    self.advance(1)?;
827                    Some(get_element(self)).transpose()
828                }
829            })
830            .map(|e| e.transpose())
831            .take_while(|e| e.is_some())
832            .map(|e| e.unwrap())
833    }
834
835    fn vector(&mut self) -> Result<Datum> {
836        let vec = self.repeat(Self::datum).collect::<Result<_>>()?;
837        Ok(self.locate(DatumBody::Vector(vec)))
838    }
839
840    fn transform_formals(args: Datum) -> Result<ParameterFormals> {
841        let location = args.location;
842        Ok(match args {
843            Datum {
844                data: DatumBody::Pair(pair),
845                ..
846            } => ParameterFormalsBody::Pair(Box::new(pair.map_ok(&mut |datum| {
847                let sub_location = datum.location;
848                Ok(
849                    ParameterFormalsBody::Name(Self::transform_identifier(datum)?)
850                        .locate(sub_location),
851                )
852            })?))
853            .locate(location),
854            single => {
855                ParameterFormalsBody::Name(Self::transform_identifier(single)?).locate(location)
856            }
857        })
858    }
859
860    fn parse_quoted(&mut self) -> Result<Datum> {
861        let quote_location = self.location;
862        let inner = self.datum()?;
863        Ok(Datum {
864            location: quote_location,
865            data: DatumBody::Pair(Box::new(list![
866                Datum {
867                    data: DatumBody::Symbol("quote".to_string()),
868                    location: quote_location,
869                },
870                inner
871            ])),
872        })
873    }
874
875    fn transform_quote(mut datums: impl Iterator<Item = Datum>) -> Result<ExpressionBody> {
876        Ok(ExpressionBody::Quote(Box::new(Self::unwrap_non_end(
877            datums.next(),
878        )?)))
879    }
880
881    fn datum(&mut self) -> Result<Datum> {
882        let location = self.location;
883        Ok(match &self.advance_unwrap(0)?.data {
884            TokenData::LeftParen => self.current_list_or_pair()?,
885            TokenData::VecConsIntro => {
886                DatumBody::Vector(self.repeat(Self::datum).collect::<Result<_>>()?).locate(location)
887            }
888            TokenData::Identifier(symbol) => DatumBody::Symbol(symbol.clone()).locate(location),
889            TokenData::Primitive(p) => DatumBody::Primitive(p.clone()).locate(location),
890            other => return located_error!(SyntaxError::UnexpectedToken(other.clone()), location),
891        })
892    }
893
894    fn transform_lambda(
895        mut datums: impl Iterator<Item = Datum>,
896        syntax_env: &Rc<LexicalScope<Transformer>>,
897    ) -> Result<ExpressionBody> {
898        let formals = Self::transform_formals(Self::unwrap_non_end(datums.next())?)?;
899        let lambda_syntax_env = Rc::new(LexicalScope::new_child(syntax_env.clone()));
900        let (definitions, expressions) =
901            Self::transform_procedure_body(datums, &lambda_syntax_env)?;
902        Ok(ExpressionBody::Procedure(SchemeProcedure(
903            formals,
904            definitions,
905            expressions,
906        )))
907    }
908
909    fn transform_procedure_body(
910        datums: impl Iterator<Item = Datum>,
911        syntax_env: &Rc<LexicalScope<Transformer>>,
912    ) -> Result<(Vec<Definition>, Vec<Expression>)> {
913        let mut definitions = vec![];
914        let mut expressions = vec![];
915        for datum in datums {
916            let location = datum.location;
917            let statement = Self::transform_to_statement(datum, syntax_env)?;
918            match statement {
919                Statement::Definition(def) => {
920                    if expressions.is_empty() {
921                        definitions.push(def)
922                    } else {
923                        return located_error!(
924                            SyntaxError::InvalidDefinitionContext(def.data),
925                            def.location
926                        );
927                    }
928                }
929                Statement::Expression(expr) => expressions.push(expr),
930                _ => {
931                    return located_error!(
932                        SyntaxError::ExpectSomething(
933                            "expression or definition".to_string(),
934                            "other statement".to_string(),
935                        ),
936                        location
937                    )
938                }
939            }
940        }
941        if expressions.is_empty() {
942            return error!(SyntaxError::LambdaBodyNoExpression);
943        }
944        Ok((definitions, expressions))
945    }
946
947    fn transform_import_decl(datums: impl Iterator<Item = Datum>) -> Result<ImportDeclaration> {
948        Ok(ImportDeclaration(
949            datums
950                .map(|import_set| Self::transform_import_set(import_set))
951                .collect::<Result<_>>()?,
952        ))
953    }
954
955    fn transform_condition(
956        mut asts: impl Iterator<Item = Datum>,
957        syntax_env: &Rc<LexicalScope<Transformer>>,
958    ) -> Result<ExpressionBody> {
959        let test = Self::transform_to_expression(Self::unwrap_non_end(asts.next())?, syntax_env)?;
960        let consequent =
961            Self::transform_to_expression(Self::unwrap_non_end(asts.next())?, syntax_env)?;
962        let alternative = asts
963            .next()
964            .map(|datum| Self::transform_to_expression(datum, syntax_env))
965            .transpose()?;
966        Ok(ExpressionBody::Conditional(Box::new((
967            test,
968            consequent,
969            alternative,
970        ))))
971    }
972
973    fn transform_library_name_part(datum: Datum) -> Result<LibraryNameElement> {
974        let location = datum.location;
975        match datum.data {
976            DatumBody::Symbol(identifier) => Ok(LibraryNameElement::Identifier(identifier)),
977            DatumBody::Primitive(Primitive::Integer(i)) if i >= 0 => {
978                Ok(LibraryNameElement::Integer(i as u32))
979            }
980            o => located_error!(SyntaxError::UnexpectedDatum(o.locate(location)), location),
981        }
982    }
983
984    fn transform_library_name(datums: impl Iterator<Item = Datum>) -> Result<LibraryName> {
985        Ok(LibraryName(
986            datums
987                .map(Self::transform_library_name_part)
988                .collect::<Result<_>>()?,
989        ))
990    }
991
992    fn transform_import_set(datum: Datum) -> Result<ImportSet> {
993        let mut iter = datum.expect_list()?.into_iter().peekable();
994        let first = Self::unwrap_non_end(iter.peek())?;
995        let location = first.location;
996        Ok(match Self::transform_identifier(first.clone())? {
997            spec if spec == "only" => {
998                iter.next();
999                let sub_import = Self::transform_import_set(Self::unwrap_non_end(iter.next())?)?;
1000                let idents = iter
1001                    .map(Self::transform_identifier)
1002                    .collect::<Result<_>>()?;
1003                ImportSetBody::Only(Box::new(sub_import), idents)
1004            }
1005            spec if spec == "except" => {
1006                iter.next();
1007                let sub_import = Self::transform_import_set(Self::unwrap_non_end(iter.next())?)?;
1008                let idents = iter
1009                    .map(Self::transform_identifier)
1010                    .collect::<Result<_>>()?;
1011                ImportSetBody::Except(Box::new(sub_import), idents)
1012            }
1013            spec if spec == "prefix" => {
1014                iter.next();
1015                let sub_import = Self::transform_import_set(Self::unwrap_non_end(iter.next())?)?;
1016                let ident = Self::transform_identifier(Self::unwrap_non_end(iter.next())?)?;
1017                ImportSetBody::Prefix(Box::new(sub_import), ident)
1018            }
1019            spec if spec == "rename" => {
1020                iter.next();
1021                let sub_import = Self::transform_import_set(Self::unwrap_non_end(iter.next())?)?;
1022                let renaming = iter
1023                    .map(Self::transform_identifier_pair)
1024                    .collect::<Result<_>>()?;
1025                ImportSetBody::Rename(Box::new(sub_import), renaming)
1026            }
1027            _ => ImportSetBody::Direct(Self::transform_library_name(iter)?.locate(location)),
1028        }
1029        .locate(location))
1030    }
1031
1032    fn transform_definition(
1033        mut datums: impl Iterator<Item = Datum>,
1034        syntax_env: &Rc<LexicalScope<Transformer>>,
1035    ) -> Result<DefinitionBody> {
1036        let first = Self::unwrap_non_end(datums.next())?;
1037        let location = first.location;
1038        match first.data {
1039            DatumBody::Symbol(symbol) => {
1040                let body = Self::transform_to_expression(
1041                    Self::unwrap_non_end(datums.next())?,
1042                    syntax_env,
1043                )?;
1044                Ok(DefinitionBody(symbol, body))
1045            }
1046            DatumBody::Pair(pair) => match *pair {
1047                GenericPair::Some(name, formals) => {
1048                    let location = name.location;
1049                    let name = Self::transform_identifier(name)?;
1050                    let formals = Self::transform_formals(formals)?;
1051                    let (defs, exprs) = Self::transform_procedure_body(datums, syntax_env)?;
1052                    let procedure =
1053                        ExpressionBody::Procedure(SchemeProcedure(formals, defs, exprs))
1054                            .locate(location);
1055                    Ok(DefinitionBody(name, procedure))
1056                }
1057                other => {
1058                    return located_error!(
1059                        SyntaxError::InvalidDefinition(Datum::from(other)),
1060                        location
1061                    )
1062                }
1063            },
1064            other => {
1065                return located_error!(SyntaxError::DefineNonSymbol(other.no_locate()), location)
1066            }
1067        }
1068    }
1069
1070    fn transform_transformer(keyword: &String, datum: Datum) -> Result<UserDefinedTransformer> {
1071        // Skipping symbol 'syntax-rules'
1072        let mut iter = datum.expect_list()?.into_iter().skip(1);
1073
1074        let first = Self::unwrap_non_end(iter.next())?;
1075        let location = first.location;
1076
1077        let (ellipsis, pattern_literals) = match first.data {
1078            DatumBody::Symbol(ellipsis) => (
1079                Some(ellipsis),
1080                Self::unwrap_non_end(iter.next())?
1081                    .expect_list()?
1082                    .into_iter()
1083                    .map(Self::transform_identifier)
1084                    .collect::<Result<HashSet<_>>>()?,
1085            ),
1086            DatumBody::Pair(list) => (
1087                None,
1088                list.into_iter()
1089                    .map(Self::transform_identifier)
1090                    .collect::<Result<HashSet<_>>>()?,
1091            ),
1092            _ => return located_error!(SyntaxError::UnexpectedDatum(first), location),
1093        };
1094
1095        let rules = iter
1096            .map(|datum| Self::transform_syntax_rule(keyword, datum))
1097            .collect::<Result<_>>()?;
1098
1099        Ok(UserDefinedTransformer {
1100            ellipsis,
1101            literals: pattern_literals,
1102            rules,
1103        })
1104    }
1105
1106    fn transform_syntax_definition(
1107        mut datums: impl Iterator<Item = Datum>,
1108        syntax_env: &Rc<LexicalScope<Transformer>>,
1109    ) -> Result<SyntaxDefBody> {
1110        let keyword = Self::transform_identifier(Self::unwrap_non_end(datums.next())?)?;
1111        let syntax_body =
1112            Self::transform_transformer(&keyword, Self::unwrap_non_end(datums.next())?)?;
1113        syntax_env.define(keyword.clone(), Transformer::Scheme(syntax_body.clone()));
1114        Ok(SyntaxDefBody(keyword, syntax_body))
1115    }
1116
1117    fn transform_syntax_rule(
1118        keyword: &String,
1119        datum: Datum,
1120    ) -> Result<(SyntaxPattern, SyntaxTemplate)> {
1121        let mut iter = datum.expect_list()?.into_iter();
1122        let pattern = Self::transform_pattern_root(
1123            keyword,
1124            Self::unwrap_non_end(iter.next())?.expect_list()?,
1125        )?;
1126        let template = Self::transform_template(Self::unwrap_non_end(iter.next())?)?;
1127        Ok((pattern, template))
1128    }
1129
1130    fn transform_pattern_root(
1131        keyword: &String,
1132        mut datum_list: DatumList,
1133    ) -> Result<SyntaxPattern> {
1134        let first = Self::unwrap_non_end(datum_list.pop_proper()?)?;
1135        let location = first.location;
1136        let providing_keyword = first.expect_symbol()?;
1137        if keyword != &providing_keyword {
1138            return located_error!(
1139                SyntaxError::MacroKeywordMissMatch(keyword.clone(), providing_keyword),
1140                location
1141            );
1142        }
1143        Ok(
1144            SyntaxPatternBody::Pair(Box::new(datum_list.map_ok(&mut Self::transform_pattern)?))
1145                .locate(location),
1146        )
1147    }
1148
1149    fn transform_pattern(datum: Datum) -> Result<SyntaxPattern> {
1150        let location = datum.location;
1151        let data = match datum.data {
1152            DatumBody::Symbol(ident) if ident == "_" => SyntaxPatternBody::Underscore,
1153            DatumBody::Symbol(ident) if ident == "..." => SyntaxPatternBody::Ellipsis,
1154            DatumBody::Symbol(ident) => SyntaxPatternBody::Identifier(ident),
1155            DatumBody::Primitive(p) => SyntaxPatternBody::Primitive(p),
1156            DatumBody::Pair(list) => {
1157                SyntaxPatternBody::Pair(Box::new(list.map_ok(&mut Self::transform_pattern)?))
1158            }
1159            DatumBody::Vector(v) => SyntaxPatternBody::Vector(
1160                v.into_iter()
1161                    .map(Self::transform_pattern)
1162                    .collect::<Result<Vec<_>>>()?,
1163            ),
1164        };
1165        Ok(SyntaxPattern {
1166            data,
1167            location: location,
1168        })
1169    }
1170
1171    fn collect_template_elements(
1172        mut datums: impl Iterator<Item = Datum>,
1173    ) -> Result<impl IntoIterator<Item = SyntaxTemplateElement>> {
1174        let mut last_template = None;
1175        let mut elements = vec![];
1176        while let Some(datum) = datums.next() {
1177            let location = datum.location;
1178            match datum.data {
1179                DatumBody::Symbol(symbol) if symbol == "..." => match last_template {
1180                    Some(SyntaxTemplateElement(template, false)) => {
1181                        elements.push(SyntaxTemplateElement(template, true));
1182                        last_template = None;
1183                    }
1184                    _ => {
1185                        return located_error!(
1186                            SyntaxError::UnexpectedDatum(
1187                                DatumBody::Symbol(symbol).locate(location)
1188                            ),
1189                            location
1190                        );
1191                    }
1192                },
1193                other => {
1194                    if let Some(last_template) = last_template {
1195                        elements.push(last_template)
1196                    };
1197                    last_template = Some(SyntaxTemplateElement(
1198                        Self::transform_template(Datum {
1199                            data: other,
1200                            location,
1201                        })?,
1202                        false,
1203                    ))
1204                }
1205            }
1206        }
1207        if let Some(last_template) = last_template {
1208            elements.push(last_template)
1209        };
1210        Ok(elements)
1211    }
1212
1213    fn transform_template(datum: Datum) -> Result<SyntaxTemplate> {
1214        // TODO: replace with ellipsis tests
1215        // let element_transformer = |datum| {
1216        //     Ok(SyntaxTemplateElement(
1217        //         Self::transform_template(datum)?,
1218        //         false,
1219        //     ))
1220        // };
1221        let data = match datum.data {
1222            DatumBody::Symbol(ident) => SyntaxTemplateBody::Identifier(ident),
1223            DatumBody::Primitive(p) => SyntaxTemplateBody::Primitive(p),
1224            DatumBody::Pair(list) => {
1225                let elements = Self::collect_template_elements(list.into_iter())?
1226                    .into_iter()
1227                    .collect::<GenericPair<_>>();
1228                SyntaxTemplateBody::Pair(Box::new(elements))
1229            }
1230            DatumBody::Vector(vec) => SyntaxTemplateBody::Vector(
1231                Self::collect_template_elements(vec.into_iter())?
1232                    .into_iter()
1233                    .collect::<Vec<_>>(),
1234            ),
1235        };
1236        Ok(SyntaxTemplate {
1237            data,
1238            location: datum.location,
1239        })
1240    }
1241
1242    fn transform_assignment(
1243        mut datums: impl Iterator<Item = Datum>,
1244        syntax_env: &Rc<LexicalScope<Transformer>>,
1245    ) -> Result<ExpressionBody> {
1246        let symbol = match Self::unwrap_non_end(datums.next())? {
1247            Datum {
1248                data: DatumBody::Symbol(symbol),
1249                ..
1250            } => symbol,
1251            other => return error!(SyntaxError::DefineNonSymbol(other)),
1252        };
1253        let body = Self::transform_to_expression(Self::unwrap_non_end(datums.next())?, syntax_env)?;
1254        Ok(ExpressionBody::Assignment(symbol, Box::new(body)))
1255    }
1256
1257    fn transform_procedure_call(
1258        first: Datum,
1259        datum: impl Iterator<Item = Datum>,
1260        syntax_env: &Rc<LexicalScope<Transformer>>,
1261    ) -> Result<ExpressionBody> {
1262        Ok(ExpressionBody::ProcedureCall(
1263            Box::new(Self::transform_to_expression(first, syntax_env)?),
1264            datum
1265                .map(|datum| Self::transform_to_expression(datum, syntax_env))
1266                .collect::<Result<Vec<_>>>()?,
1267        ))
1268    }
1269
1270    fn advance(&mut self, count: usize) -> Result<&mut Option<Token>> {
1271        for _ in 1..count {
1272            self.lexer.next();
1273        }
1274        if count > 0 {
1275            self.current = self.lexer.next().transpose()?;
1276            self.location = self.current.as_ref().and_then(|t| t.location);
1277        }
1278        Ok(&mut self.current)
1279    }
1280
1281    fn advance_unwrap<'a>(&'a mut self, count: usize) -> Result<&'a mut Token> {
1282        let location = self.location;
1283        let token = self.advance(count)?;
1284        match token {
1285            Some(tok) => Ok(tok),
1286            None => located_error!(SyntaxError::UnexpectedEnd, location),
1287        }
1288    }
1289
1290    fn advance_unwrap_take(&mut self, count: usize) -> Result<Token> {
1291        let token = self.advance(count)?.take();
1292        match token {
1293            Some(tok) => Ok(tok),
1294            None => located_error!(SyntaxError::UnexpectedEnd, self.location),
1295        }
1296    }
1297
1298    fn peek_next_token(&mut self) -> Result<Option<&Token>> {
1299        match self.lexer.peek() {
1300            Some(ret) => match ret {
1301                Ok(t) => Ok(Some(t)),
1302                Err(e) => Err((*e).clone()),
1303            },
1304            None => Ok(None),
1305        }
1306    }
1307
1308    fn locate<T: PartialEq>(&self, data: T) -> Located<T> {
1309        Located {
1310            data,
1311            location: self.location,
1312        }
1313    }
1314}
1315
1316// macro_rules! match_expect_syntax {
1317//     ($value:expr, $type:pat => $inner: expr, $type_name:expr) => {
1318//         match $value {
1319//             $type => Ok($inner),
1320//             v => Err(SchemeError {
1321//                 location: None,
1322//                 category: ErrorType::Syntax,
1323//                 message: format!("expect a {}, got {}", $type_name, v),
1324//             }),
1325//         }
1326//     };
1327// }
1328
1329#[cfg(test)]
1330pub fn simple_procedure(formals: ParameterFormals, expression: Expression) -> Expression {
1331    ExpressionBody::Procedure(SchemeProcedure(formals, vec![], vec![expression])).into()
1332}
1333#[test]
1334fn empty() -> Result<()> {
1335    let tokens = Vec::new();
1336    let mut parser = token_stream_to_parser(tokens.into_iter());
1337    assert_eq!(parser.parse_root(), Ok(None));
1338    Ok(())
1339}
1340
1341fn expr_body_to_statement(t: ExpressionBody) -> Option<Statement> {
1342    Some(Located::from(t).into())
1343}
1344
1345fn def_body_to_statement(t: DefinitionBody) -> Option<Statement> {
1346    Some(Located::from(t).into())
1347}
1348
1349#[cfg(test)]
1350pub fn token_stream_to_parser(
1351    token_stream: impl Iterator<Item = Token>,
1352) -> Parser<impl Iterator<Item = Result<Token>>> {
1353    let mapped = token_stream.map(|t| -> Result<Token> { Ok(t) });
1354    Parser {
1355        current: None,
1356        lexer: mapped.peekable(),
1357        syntax_env: Rc::new(LexicalScope::new()),
1358        location: None,
1359    }
1360}
1361
1362#[test]
1363fn integer() -> Result<()> {
1364    let tokens = convert_located(vec![TokenData::Primitive(Primitive::Integer(1))]);
1365    let mut parser = token_stream_to_parser(tokens.into_iter());
1366    let ast = parser.parse_root()?;
1367    assert_eq!(ast, expr_body_to_statement(Primitive::Integer(1).into()));
1368    Ok(())
1369}
1370
1371#[test]
1372fn real_number() -> Result<()> {
1373    let tokens = convert_located(vec![TokenData::Primitive(Primitive::Real(
1374        "1.2".to_string(),
1375    ))]);
1376    let mut parser = token_stream_to_parser(tokens.into_iter());
1377    let ast = parser.parse_root()?;
1378    assert_eq!(
1379        ast,
1380        expr_body_to_statement(Primitive::Real("1.2".to_string()).into())
1381    );
1382    Ok(())
1383}
1384
1385#[test]
1386fn rational() -> Result<()> {
1387    let tokens = convert_located(vec![TokenData::Primitive(Primitive::Rational(1, 2))]);
1388    let mut parser = token_stream_to_parser(tokens.into_iter());
1389    let ast = parser.parse_root()?;
1390    assert_eq!(
1391        ast,
1392        expr_body_to_statement(Primitive::Rational(1, 2).into())
1393    );
1394    Ok(())
1395}
1396
1397#[test]
1398fn identifier() -> Result<()> {
1399    let tokens = convert_located(vec![TokenData::Identifier("test".to_string())]);
1400    let mut parser = token_stream_to_parser(tokens.into_iter());
1401    let ast = parser.parse_root()?;
1402    assert_eq!(
1403        ast,
1404        expr_body_to_statement(ExpressionBody::Symbol("test".to_string()))
1405    );
1406    Ok(())
1407}
1408
1409#[test]
1410fn vector() -> Result<()> {
1411    let tokens = convert_located(vec![
1412        TokenData::VecConsIntro,
1413        TokenData::Primitive(Primitive::Integer(1)),
1414        TokenData::Primitive(Primitive::Boolean(false)),
1415        TokenData::RightParen,
1416    ]);
1417    let mut parser = token_stream_to_parser(tokens.into_iter());
1418    let ast = parser.parse_root()?;
1419    assert_eq!(
1420        ast,
1421        expr_body_to_statement(ExpressionBody::Datum(
1422            DatumBody::Vector(convert_located(vec![
1423                DatumBody::Primitive(Primitive::Integer(1)),
1424                DatumBody::Primitive(Primitive::Boolean(false))
1425            ]))
1426            .into()
1427        ))
1428    );
1429    Ok(())
1430}
1431
1432#[test]
1433fn string() -> Result<()> {
1434    let tokens = convert_located(vec![TokenData::Primitive(Primitive::String(
1435        "hello world".to_string(),
1436    ))]);
1437    let mut parser = token_stream_to_parser(tokens.into_iter());
1438    let ast = parser.parse_root()?;
1439    assert_eq!(
1440        ast,
1441        expr_body_to_statement(Primitive::String("hello world".to_string()).into())
1442    );
1443    Ok(())
1444}
1445
1446#[test]
1447fn procedure_call() -> Result<()> {
1448    let tokens = convert_located(vec![
1449        TokenData::LeftParen,
1450        TokenData::Identifier("+".to_string()),
1451        TokenData::Primitive(Primitive::Integer(1)),
1452        TokenData::Primitive(Primitive::Integer(2)),
1453        TokenData::Primitive(Primitive::Integer(3)),
1454        TokenData::RightParen,
1455    ]);
1456    let mut parser = token_stream_to_parser(tokens.into_iter());
1457    let ast = parser.parse_root()?;
1458    assert_eq!(
1459        ast,
1460        expr_body_to_statement(ExpressionBody::ProcedureCall(
1461            Box::new(ExpressionBody::Symbol("+".to_string()).into()),
1462            vec![
1463                Primitive::Integer(1).into(),
1464                Primitive::Integer(2).into(),
1465                Primitive::Integer(3).into(),
1466            ]
1467        ))
1468    );
1469    Ok(())
1470}
1471
1472#[test]
1473fn unmatched_parantheses() {
1474    let tokens = convert_located(vec![
1475        TokenData::LeftParen,
1476        TokenData::Identifier("+".to_string()),
1477        TokenData::Primitive(Primitive::Integer(1)),
1478        TokenData::Primitive(Primitive::Integer(2)),
1479        TokenData::Primitive(Primitive::Integer(3)),
1480    ]);
1481    let mut parser = token_stream_to_parser(tokens.into_iter());
1482    assert_eq!(
1483        parser.parse_root(),
1484        located_error!(SyntaxError::UnexpectedEnd, None)
1485    );
1486}
1487
1488#[test]
1489fn definition() -> Result<()> {
1490    {
1491        {
1492            let tokens = convert_located(vec![
1493                TokenData::LeftParen,
1494                TokenData::Identifier("define".to_string()),
1495                TokenData::Identifier("a".to_string()),
1496                TokenData::Primitive(Primitive::Integer(1)),
1497                TokenData::RightParen,
1498            ]);
1499            let mut parser = token_stream_to_parser(tokens.into_iter());
1500            let ast = parser.parse_root()?;
1501            assert_eq!(
1502                ast,
1503                def_body_to_statement(DefinitionBody(
1504                    "a".to_string(),
1505                    Primitive::Integer(1).into()
1506                ))
1507            );
1508        }
1509        {
1510            let tokens = convert_located(vec![
1511                TokenData::LeftParen,
1512                TokenData::Identifier("define".to_string()),
1513                TokenData::LeftParen,
1514                TokenData::Identifier("add".to_string()),
1515                TokenData::Identifier("x".to_string()),
1516                TokenData::Identifier("y".to_string()),
1517                TokenData::RightParen,
1518                TokenData::LeftParen,
1519                TokenData::Identifier("+".to_string()),
1520                TokenData::Identifier("x".to_string()),
1521                TokenData::Identifier("y".to_string()),
1522                TokenData::RightParen,
1523                TokenData::RightParen,
1524            ]);
1525            let mut parser = token_stream_to_parser(tokens.into_iter());
1526            let ast = parser.parse_root()?;
1527            assert_eq!(
1528                ast,
1529                def_body_to_statement(DefinitionBody(
1530                    "add".to_string(),
1531                    simple_procedure(
1532                        param_fixed!["x", "y"],
1533                        ExpressionBody::ProcedureCall(
1534                            Box::new(ExpressionBody::Symbol("+".to_string()).into()),
1535                            vec![
1536                                ExpressionBody::Symbol("x".to_string()).into(),
1537                                ExpressionBody::Symbol("y".to_string()).into(),
1538                            ]
1539                        )
1540                        .into()
1541                    )
1542                ))
1543            )
1544        }
1545        {
1546            let tokens = convert_located(vec![
1547                TokenData::LeftParen,
1548                TokenData::Identifier("define".to_string()),
1549                TokenData::LeftParen,
1550                TokenData::Identifier("add".to_string()),
1551                TokenData::Period,
1552                TokenData::Identifier("x".to_string()),
1553                TokenData::RightParen,
1554                TokenData::Identifier("x".to_string()),
1555                TokenData::RightParen,
1556            ]);
1557            let mut parser = token_stream_to_parser(tokens.into_iter());
1558            let ast = parser.parse_root()?;
1559            assert_eq!(
1560                ast,
1561                def_body_to_statement(DefinitionBody(
1562                    "add".to_string(),
1563                    simple_procedure(
1564                        append_variadic_param!(param_fixed![], "x"),
1565                        ExpressionBody::Symbol("x".to_string()).into()
1566                    )
1567                ))
1568            )
1569        }
1570        Ok(())
1571    }
1572}
1573
1574#[test]
1575fn nested_procedure_call() -> Result<()> {
1576    let tokens = convert_located(vec![
1577        TokenData::LeftParen,
1578        TokenData::Identifier("+".to_string()),
1579        TokenData::Primitive(Primitive::Integer(1)),
1580        TokenData::LeftParen,
1581        TokenData::Identifier("-".to_string()),
1582        TokenData::Primitive(Primitive::Integer(2)),
1583        TokenData::Primitive(Primitive::Integer(3)),
1584        TokenData::RightParen,
1585        TokenData::RightParen,
1586    ]);
1587    let mut parser = token_stream_to_parser(tokens.into_iter());
1588    let ast = parser.parse_root()?;
1589    assert_eq!(
1590        ast,
1591        expr_body_to_statement(ExpressionBody::ProcedureCall(
1592            Box::new(ExpressionBody::Symbol("+".to_string()).into()),
1593            vec![
1594                Primitive::Integer(1).into(),
1595                ExpressionBody::ProcedureCall(
1596                    Box::new(ExpressionBody::Symbol("-".to_string()).into()),
1597                    vec![Primitive::Integer(2).into(), Primitive::Integer(3).into()]
1598                )
1599                .into(),
1600            ]
1601        ))
1602    );
1603    Ok(())
1604}
1605
1606#[test]
1607fn lambda() -> Result<()> {
1608    {
1609        let tokens = convert_located(vec![
1610            TokenData::LeftParen,
1611            TokenData::Identifier("lambda".to_string()),
1612            TokenData::LeftParen,
1613            TokenData::Identifier("x".to_string()),
1614            TokenData::Identifier("y".to_string()),
1615            TokenData::RightParen,
1616            TokenData::LeftParen,
1617            TokenData::Identifier("+".to_string()),
1618            TokenData::Identifier("x".to_string()),
1619            TokenData::Identifier("y".to_string()),
1620            TokenData::RightParen,
1621            TokenData::RightParen,
1622        ]);
1623        let mut parser = token_stream_to_parser(tokens.into_iter());
1624        let ast = parser.parse_root()?;
1625        assert_eq!(
1626            ast,
1627            Some(Statement::Expression(simple_procedure(
1628                param_fixed!["x", "y"],
1629                ExpressionBody::ProcedureCall(
1630                    Box::new(ExpressionBody::Symbol("+".to_string()).into()),
1631                    vec![
1632                        ExpressionBody::Symbol("x".to_string()).into(),
1633                        ExpressionBody::Symbol("y".to_string()).into()
1634                    ]
1635                )
1636                .into()
1637            )))
1638        );
1639    }
1640
1641    {
1642        let tokens = convert_located(vec![
1643            TokenData::LeftParen,
1644            TokenData::Identifier("lambda".to_string()),
1645            TokenData::LeftParen,
1646            TokenData::Identifier("x".to_string()),
1647            TokenData::RightParen,
1648            TokenData::LeftParen,
1649            TokenData::Identifier("define".to_string()),
1650            TokenData::Identifier("y".to_string()),
1651            TokenData::Primitive(Primitive::Integer(1)),
1652            TokenData::RightParen,
1653            TokenData::LeftParen,
1654            TokenData::Identifier("+".to_string()),
1655            TokenData::Identifier("x".to_string()),
1656            TokenData::Identifier("y".to_string()),
1657            TokenData::RightParen,
1658            TokenData::RightParen,
1659        ]);
1660        let mut parser = token_stream_to_parser(tokens.into_iter());
1661        let ast = parser.parse_root()?;
1662        assert_eq!(
1663            ast,
1664            Some(Statement::Expression(
1665                ExpressionBody::Procedure(SchemeProcedure(
1666                    param_fixed!["x".to_string()],
1667                    vec![Definition::from(DefinitionBody(
1668                        "y".to_string(),
1669                        Primitive::Integer(1).into()
1670                    ))],
1671                    vec![ExpressionBody::ProcedureCall(
1672                        Box::new(ExpressionBody::Symbol("+".to_string()).into()),
1673                        vec![
1674                            ExpressionBody::Symbol("x".to_string()).into(),
1675                            ExpressionBody::Symbol("y".to_string()).into()
1676                        ]
1677                    )
1678                    .into()]
1679                ))
1680                .into()
1681            ))
1682        );
1683    }
1684
1685    {
1686        let tokens = convert_located(vec![
1687            TokenData::LeftParen,
1688            TokenData::Identifier("lambda".to_string()),
1689            TokenData::LeftParen,
1690            TokenData::Identifier("x".to_string()),
1691            TokenData::RightParen,
1692            TokenData::LeftParen,
1693            TokenData::Identifier("define".to_string()),
1694            TokenData::Identifier("y".to_string()),
1695            TokenData::Primitive(Primitive::Integer(1)),
1696            TokenData::RightParen,
1697            TokenData::RightParen,
1698        ]);
1699        let mut parser = token_stream_to_parser(tokens.into_iter());
1700        let err = parser.parse_root();
1701        assert_eq!(
1702            err,
1703            located_error!(SyntaxError::LambdaBodyNoExpression, None)
1704        );
1705    }
1706
1707    {
1708        let tokens = convert_located(vec![
1709            TokenData::LeftParen,
1710            TokenData::Identifier("lambda".to_string()),
1711            TokenData::LeftParen,
1712            TokenData::Identifier("x".to_string()),
1713            TokenData::Period,
1714            TokenData::Identifier("y".to_string()),
1715            TokenData::RightParen,
1716            TokenData::LeftParen,
1717            TokenData::Identifier("+".to_string()),
1718            TokenData::Identifier("x".to_string()),
1719            TokenData::Identifier("y".to_string()),
1720            TokenData::RightParen,
1721            TokenData::RightParen,
1722        ]);
1723        let mut parser = token_stream_to_parser(tokens.into_iter());
1724        let ast = parser.parse_root()?;
1725        assert_eq!(
1726            ast,
1727            Some(Statement::Expression(
1728                ExpressionBody::Procedure(SchemeProcedure(
1729                    append_variadic_param!(param_fixed!["x"], "y"),
1730                    vec![],
1731                    vec![ExpressionBody::ProcedureCall(
1732                        Box::new(ExpressionBody::Symbol("+".to_string()).into()),
1733                        vec![
1734                            ExpressionBody::Symbol("x".to_string()).into(),
1735                            ExpressionBody::Symbol("y".to_string()).into()
1736                        ]
1737                    )
1738                    .into()]
1739                ))
1740                .into()
1741            ))
1742        );
1743    }
1744
1745    Ok(())
1746}
1747
1748#[test]
1749fn conditional() -> Result<()> {
1750    let tokens = convert_located(vec![
1751        TokenData::LeftParen,
1752        TokenData::Identifier("if".to_string()),
1753        TokenData::Primitive(Primitive::Boolean(true)),
1754        TokenData::Primitive(Primitive::Integer(1)),
1755        TokenData::Primitive(Primitive::Integer(2)),
1756        TokenData::RightParen,
1757    ]);
1758    let mut parser = token_stream_to_parser(tokens.into_iter());
1759    assert_eq!(
1760        parser.parse_root()?,
1761        Some(Statement::Expression(
1762            ExpressionBody::Conditional(Box::new((
1763                Primitive::Boolean(true).into(),
1764                Primitive::Integer(1).into(),
1765                Some(Primitive::Integer(2).into())
1766            )))
1767            .into()
1768        ))
1769    );
1770    assert_eq!(parser.parse_root()?, None);
1771    Ok(())
1772}
1773
1774#[test]
1775fn import_set() -> Result<()> {
1776    {
1777        let tokens = convert_located(vec![
1778            TokenData::LeftParen,
1779            TokenData::Identifier("import".to_string()),
1780            TokenData::LeftParen,
1781            TokenData::Identifier("foo".to_string()),
1782            TokenData::Primitive(Primitive::Integer(5)),
1783            TokenData::RightParen,
1784            TokenData::RightParen,
1785        ]);
1786        let mut parser = token_stream_to_parser(tokens.into_iter());
1787        let import_set = parser.parse_root()?;
1788        assert_eq!(
1789            import_set,
1790            Some(Statement::ImportDeclaration(
1791                ImportDeclaration(vec![
1792                    ImportSetBody::Direct(library_name!("foo", 5).into()).into()
1793                ])
1794                .into()
1795            ))
1796        );
1797    }
1798    {
1799        let tokens = convert_located(vec![
1800            TokenData::LeftParen,
1801            TokenData::Identifier("import".to_string()),
1802            TokenData::LeftParen,
1803            TokenData::Identifier("only".to_string()),
1804            TokenData::LeftParen,
1805            TokenData::Identifier("foo".to_string()),
1806            TokenData::Primitive(Primitive::Integer(5)),
1807            TokenData::RightParen,
1808            TokenData::Identifier("a".to_string()),
1809            TokenData::RightParen,
1810            TokenData::RightParen,
1811        ]);
1812        let mut parser = token_stream_to_parser(tokens.into_iter());
1813        let import_set = parser.parse_root()?;
1814        assert_eq!(
1815            import_set,
1816            Some(Statement::ImportDeclaration(
1817                ImportDeclaration(vec![ImportSetBody::Only(
1818                    Box::new(
1819                        ImportSetBody::Direct(library_name!("foo", 5).no_locate()).no_locate()
1820                    ),
1821                    vec!["a".to_string()]
1822                )
1823                .into()])
1824                .into()
1825            ))
1826        );
1827    }
1828    {
1829        let tokens = convert_located(vec![
1830            TokenData::LeftParen,
1831            TokenData::Identifier("import".to_string()),
1832            TokenData::LeftParen,
1833            TokenData::Identifier("except".to_string()),
1834            TokenData::LeftParen,
1835            TokenData::Identifier("foo".to_string()),
1836            TokenData::Primitive(Primitive::Integer(5)),
1837            TokenData::RightParen,
1838            TokenData::Identifier("a".to_string()),
1839            TokenData::Identifier("b".to_string()),
1840            TokenData::RightParen,
1841            TokenData::RightParen,
1842        ]);
1843        let mut parser = token_stream_to_parser(tokens.into_iter());
1844        let import_set = parser.parse_root()?;
1845        assert_eq!(
1846            import_set,
1847            Some(Statement::ImportDeclaration(
1848                ImportDeclaration(vec![ImportSetBody::Except(
1849                    Box::new(
1850                        ImportSetBody::Direct(library_name!("foo", 5).no_locate()).no_locate()
1851                    ),
1852                    vec!["a".to_string(), "b".to_string()]
1853                )
1854                .into()])
1855                .into()
1856            ))
1857        );
1858    }
1859    {
1860        let tokens = convert_located(vec![
1861            TokenData::LeftParen,
1862            TokenData::Identifier("import".to_string()),
1863            TokenData::LeftParen,
1864            TokenData::Identifier("prefix".to_string()),
1865            TokenData::LeftParen,
1866            TokenData::Identifier("foo".to_string()),
1867            TokenData::Primitive(Primitive::Integer(5)),
1868            TokenData::RightParen,
1869            TokenData::Identifier("a-".to_string()),
1870            TokenData::RightParen,
1871            TokenData::RightParen,
1872        ]);
1873        let mut parser = token_stream_to_parser(tokens.into_iter());
1874        let import_set = parser.parse_root()?;
1875        assert_eq!(
1876            import_set,
1877            Some(Statement::ImportDeclaration(
1878                ImportDeclaration(vec![ImportSetBody::Prefix(
1879                    Box::new(
1880                        ImportSetBody::Direct(library_name!("foo", 5).no_locate()).no_locate()
1881                    ),
1882                    "a-".to_string()
1883                )
1884                .into()])
1885                .into()
1886            ))
1887        );
1888    }
1889    {
1890        let tokens = convert_located(vec![
1891            TokenData::LeftParen,
1892            TokenData::Identifier("import".to_string()),
1893            TokenData::LeftParen,
1894            TokenData::Identifier("rename".to_string()),
1895            TokenData::LeftParen,
1896            TokenData::Identifier("foo".to_string()),
1897            TokenData::Primitive(Primitive::Integer(5)),
1898            TokenData::RightParen,
1899            TokenData::LeftParen,
1900            TokenData::Identifier("a".to_string()),
1901            TokenData::Identifier("b".to_string()),
1902            TokenData::RightParen,
1903            TokenData::LeftParen,
1904            TokenData::Identifier("c".to_string()),
1905            TokenData::Identifier("d".to_string()),
1906            TokenData::RightParen,
1907            TokenData::RightParen,
1908            TokenData::RightParen,
1909        ]);
1910        let mut parser = token_stream_to_parser(tokens.into_iter());
1911        let import_set = parser.parse_root()?;
1912        assert_eq!(
1913            import_set,
1914            Some(Statement::ImportDeclaration(
1915                ImportDeclaration(vec![ImportSetBody::Rename(
1916                    Box::new(
1917                        ImportSetBody::Direct(library_name!("foo", 5).no_locate()).no_locate()
1918                    ),
1919                    vec![
1920                        ("a".to_string(), "b".to_string()),
1921                        ("c".to_string(), "d".to_string()),
1922                    ]
1923                )
1924                .into()])
1925                .into()
1926            ))
1927        );
1928    }
1929    Ok(())
1930}
1931/* (import
1932(only (example-lib) a b)
1933(rename (example-lib) (old new))
1934) */
1935
1936#[test]
1937fn import_declaration() -> Result<()> {
1938    {
1939        let tokens = convert_located(vec![
1940            TokenData::LeftParen,
1941            TokenData::Identifier("import".to_string()),
1942            TokenData::LeftParen,
1943            TokenData::Identifier("only".to_string()),
1944            TokenData::LeftParen,
1945            TokenData::Identifier("example-lib".to_string()),
1946            TokenData::RightParen,
1947            TokenData::Identifier("a".to_string()),
1948            TokenData::Identifier("b".to_string()),
1949            TokenData::RightParen,
1950            TokenData::LeftParen,
1951            TokenData::Identifier("rename".to_string()),
1952            TokenData::LeftParen,
1953            TokenData::Identifier("example-lib".to_string()),
1954            TokenData::RightParen,
1955            TokenData::LeftParen,
1956            TokenData::Identifier("old".to_string()),
1957            TokenData::Identifier("new".to_string()),
1958            TokenData::RightParen,
1959            TokenData::RightParen,
1960            TokenData::RightParen,
1961        ]);
1962
1963        let mut parser = token_stream_to_parser(tokens.into_iter());
1964        let ast = parser.parse_root()?;
1965        assert_eq!(
1966            ast,
1967            Some(
1968                ImportDeclaration(convert_located(vec![
1969                    ImportSetBody::Only(
1970                        Box::new(
1971                            ImportSetBody::Direct(
1972                                LibraryName(vec![LibraryNameElement::Identifier(
1973                                    "example-lib".to_string()
1974                                )])
1975                                .into()
1976                            )
1977                            .into()
1978                        ),
1979                        vec!["a".to_string(), "b".to_string()]
1980                    ),
1981                    ImportSetBody::Rename(
1982                        Box::new(
1983                            ImportSetBody::Direct(
1984                                LibraryName(vec![LibraryNameElement::Identifier(
1985                                    "example-lib".to_string()
1986                                )])
1987                                .into()
1988                            )
1989                            .into()
1990                        ),
1991                        vec![("old".to_string(), "new".to_string())]
1992                    )
1993                ]))
1994                .no_locate()
1995                .into()
1996            )
1997        );
1998    }
1999    Ok(())
2000}
2001
2002#[test]
2003fn literals() -> Result<()> {
2004    // symbol + list
2005    {
2006        let tokens = convert_located(vec![
2007            TokenData::Quote,
2008            TokenData::Primitive(Primitive::Integer(1)),
2009            TokenData::Quote,
2010            TokenData::Identifier("a".to_string()),
2011            TokenData::Quote,
2012            TokenData::LeftParen,
2013            TokenData::Primitive(Primitive::Integer(1)),
2014            TokenData::RightParen,
2015            TokenData::VecConsIntro,
2016            TokenData::Primitive(Primitive::Integer(1)),
2017            TokenData::RightParen,
2018            TokenData::Quote,
2019            TokenData::VecConsIntro,
2020            TokenData::Primitive(Primitive::Integer(1)),
2021            TokenData::RightParen,
2022        ]);
2023        let parser = token_stream_to_parser(tokens.into_iter());
2024        let asts = parser.collect::<Result<Vec<_>>>()?;
2025        assert_eq!(
2026            asts,
2027            vec![
2028                Statement::Expression(
2029                    ExpressionBody::Quote(Box::new(
2030                        DatumBody::Primitive(Primitive::Integer(1)).into()
2031                    ))
2032                    .into()
2033                ),
2034                Statement::Expression(
2035                    ExpressionBody::Quote(Box::new(DatumBody::Symbol("a".to_string()).into(),))
2036                        .into()
2037                ),
2038                Statement::Expression(
2039                    ExpressionBody::Quote(Box::new(
2040                        DatumBody::Pair(Box::new(list!(DatumBody::Primitive(Primitive::Integer(
2041                            1
2042                        ))
2043                        .no_locate())))
2044                        .into()
2045                    ))
2046                    .into()
2047                ),
2048                Statement::Expression(
2049                    ExpressionBody::Datum(
2050                        DatumBody::Vector(vec![
2051                            DatumBody::Primitive(Primitive::Integer(1)).no_locate()
2052                        ])
2053                        .into()
2054                    )
2055                    .into()
2056                ),
2057                Statement::Expression(
2058                    ExpressionBody::Quote(Box::new(
2059                        DatumBody::Vector(vec![
2060                            DatumBody::Primitive(Primitive::Integer(1)).no_locate()
2061                        ])
2062                        .into()
2063                    ))
2064                    .into()
2065                ),
2066            ]
2067        );
2068    }
2069    Ok(())
2070}
2071
2072#[test]
2073fn macros() -> Result<()> {
2074    let tokens = convert_located(vec![
2075        TokenData::LeftParen,
2076        TokenData::Identifier("define-syntax".to_string()),
2077        TokenData::Identifier("begin".to_string()),
2078        TokenData::LeftParen,
2079        TokenData::Identifier("syntax-rules".to_string()),
2080        TokenData::LeftParen,
2081        TokenData::RightParen,
2082        TokenData::LeftParen,
2083        TokenData::LeftParen,
2084        TokenData::Identifier("begin".to_string()),
2085        TokenData::Identifier("exp".to_string()),
2086        TokenData::Identifier("...".to_string()),
2087        TokenData::RightParen,
2088        TokenData::LeftParen,
2089        TokenData::LeftParen,
2090        TokenData::Identifier("lambda".to_string()),
2091        TokenData::LeftParen,
2092        TokenData::RightParen,
2093        TokenData::Identifier("exp".to_string()),
2094        TokenData::Identifier("...".to_string()),
2095        TokenData::RightParen,
2096        TokenData::RightParen,
2097        TokenData::RightParen,
2098        TokenData::RightParen,
2099        TokenData::RightParen,
2100    ]);
2101
2102    let parser = token_stream_to_parser(tokens.into_iter());
2103    let asts = parser.collect::<Result<Vec<_>>>()?;
2104    assert_eq!(
2105        asts,
2106        vec![Statement::SyntaxDefinition(
2107            SyntaxDefBody(
2108                "begin".to_owned(),
2109                UserDefinedTransformer {
2110                    ellipsis: None,
2111                    literals: HashSet::new(),
2112                    rules: vec![(
2113                        SyntaxPatternBody::Pair(Box::new(list![
2114                            SyntaxPatternBody::Identifier("exp".to_string()).into(),
2115                            SyntaxPatternBody::Ellipsis.into()
2116                        ]))
2117                        .into(),
2118                        SyntaxTemplateBody::Pair(Box::new(list![SyntaxTemplateElement(
2119                            SyntaxTemplateBody::Pair(Box::new(list![
2120                                SyntaxTemplateElement(
2121                                    SyntaxTemplateBody::Identifier("lambda".to_string()).into(),
2122                                    false
2123                                ),
2124                                SyntaxTemplateElement(
2125                                    SyntaxTemplateBody::Pair(Box::new(list![])).into(),
2126                                    false
2127                                ),
2128                                SyntaxTemplateElement(
2129                                    SyntaxTemplateBody::Identifier("exp".to_string()).into(),
2130                                    true
2131                                )
2132                            ]))
2133                            .into(),
2134                            false
2135                        )]))
2136                        .into()
2137                    )],
2138                }
2139            )
2140            .into()
2141        )]
2142    );
2143
2144    Ok(())
2145}
2146
2147#[test]
2148fn library_name() -> Result<()> {
2149    {
2150        let tokens = convert_located(vec![
2151            TokenData::LeftParen,
2152            TokenData::Identifier("import".to_string()),
2153            TokenData::LeftParen,
2154            TokenData::Identifier("f".to_string()),
2155            TokenData::Primitive(Primitive::Integer(5)),
2156            TokenData::RightParen,
2157            TokenData::RightParen,
2158        ]);
2159        let mut parser = token_stream_to_parser(tokens.into_iter());
2160        let library_name = parser.parse_root()?;
2161        assert_eq!(
2162            library_name,
2163            Some(Statement::ImportDeclaration(
2164                ImportDeclaration(vec![
2165                    ImportSetBody::Direct(library_name!("f", 5).into()).into()
2166                ])
2167                .into()
2168            ))
2169        );
2170    }
2171    {
2172        let tokens = convert_located(vec![
2173            TokenData::LeftParen,
2174            TokenData::Identifier("import".to_string()),
2175            TokenData::LeftParen,
2176            TokenData::Identifier("f".to_string()),
2177            TokenData::Primitive(Primitive::Integer(-5)),
2178            TokenData::RightParen,
2179            TokenData::RightParen,
2180        ]);
2181        let mut parser = token_stream_to_parser(tokens.into_iter());
2182        let library_name = parser.parse_root();
2183        assert!(library_name.is_err());
2184    }
2185    {
2186        let tokens = convert_located(vec![
2187            TokenData::LeftParen,
2188            TokenData::Identifier("import".to_string()),
2189            TokenData::LeftParen,
2190            TokenData::Identifier("f".to_string()),
2191            TokenData::Primitive(Primitive::String("haha".to_string())),
2192            TokenData::RightParen,
2193            TokenData::RightParen,
2194        ]);
2195        let mut parser = token_stream_to_parser(tokens.into_iter());
2196        let library_name = parser.parse_root();
2197        assert!(library_name.is_err());
2198    }
2199    Ok(())
2200}
2201#[test]
2202fn export_spec() -> Result<()> {
2203    {
2204        let tokens = convert_located(vec![
2205            TokenData::LeftParen,
2206            TokenData::Identifier("define-library".to_string()),
2207            TokenData::LeftParen,
2208            TokenData::Identifier("foo".to_string()),
2209            TokenData::RightParen,
2210            TokenData::LeftParen,
2211            TokenData::Identifier("export".to_string()),
2212            TokenData::Identifier("a".to_string()),
2213            TokenData::RightParen,
2214            TokenData::RightParen,
2215        ]);
2216        let mut parser = token_stream_to_parser(tokens.into_iter());
2217        let export_spec = parser.parse_root()?;
2218
2219        assert_eq!(
2220            export_spec,
2221            Some(Statement::LibraryDefinition(
2222                LibraryDefinition(
2223                    library_name!("foo").into(),
2224                    vec![LibraryDeclaration::Export(vec![
2225                        ExportSpec::Direct("a".to_string()).into()
2226                    ])
2227                    .into()]
2228                )
2229                .into()
2230            ))
2231        );
2232    }
2233    {
2234        let tokens = convert_located(vec![
2235            TokenData::LeftParen,
2236            TokenData::Identifier("define-library".to_string()),
2237            TokenData::LeftParen,
2238            TokenData::Identifier("foo".to_string()),
2239            TokenData::RightParen,
2240            TokenData::LeftParen,
2241            TokenData::Identifier("export".to_string()),
2242            TokenData::LeftParen,
2243            TokenData::Identifier("rename".to_string()),
2244            TokenData::Identifier("a".to_string()),
2245            TokenData::Identifier("b".to_string()),
2246            TokenData::RightParen,
2247            TokenData::RightParen,
2248            TokenData::RightParen,
2249        ]);
2250        let mut parser = token_stream_to_parser(tokens.into_iter());
2251        let export_spec = parser.parse_root()?;
2252        assert_eq!(
2253            export_spec,
2254            Some(Statement::LibraryDefinition(
2255                LibraryDefinition(
2256                    library_name!("foo").into(),
2257                    vec![LibraryDeclaration::Export(vec![ExportSpec::Rename(
2258                        "a".to_string(),
2259                        "b".to_string()
2260                    )
2261                    .into()])
2262                    .into()]
2263                )
2264                .into()
2265            ))
2266        );
2267    }
2268    {
2269        let tokens = convert_located(vec![
2270            TokenData::LeftParen,
2271            TokenData::Identifier("define-library".to_string()),
2272            TokenData::LeftParen,
2273            TokenData::Identifier("foo".to_string()),
2274            TokenData::RightParen,
2275            TokenData::LeftParen,
2276            TokenData::Identifier("export".to_string()),
2277            TokenData::LeftParen,
2278            TokenData::Identifier("c".to_string()),
2279            TokenData::Identifier("a".to_string()),
2280            TokenData::Identifier("b".to_string()),
2281            TokenData::RightParen,
2282            TokenData::RightParen,
2283            TokenData::RightParen,
2284        ]);
2285        let mut parser = token_stream_to_parser(tokens.into_iter());
2286        assert!(parser.parse_root().is_err());
2287    }
2288    Ok(())
2289}
2290#[test]
2291fn library_declaration() -> Result<()> {
2292    {
2293        let tokens = convert_located(vec![
2294            TokenData::LeftParen,
2295            TokenData::Identifier("define-library".to_string()),
2296            TokenData::LeftParen,
2297            TokenData::Identifier("foo".to_string()),
2298            TokenData::RightParen,
2299            TokenData::LeftParen,
2300            TokenData::Identifier("import".to_string()),
2301            TokenData::LeftParen,
2302            TokenData::Identifier("a".to_string()),
2303            TokenData::Identifier("b".to_string()),
2304            TokenData::RightParen,
2305            TokenData::RightParen,
2306            TokenData::RightParen,
2307        ]);
2308        let mut parser = token_stream_to_parser(tokens.into_iter());
2309
2310        let library_declaration = parser.parse_root()?;
2311        assert_eq!(
2312            library_declaration,
2313            Some(Statement::LibraryDefinition(
2314                LibraryDefinition(
2315                    library_name!("foo").into(),
2316                    vec![LibraryDeclaration::ImportDeclaration(
2317                        ImportDeclaration(vec![ImportSetBody::Direct(
2318                            library_name!("a", "b").no_locate()
2319                        )
2320                        .no_locate()])
2321                        .no_locate()
2322                    )
2323                    .into()]
2324                )
2325                .into()
2326            ))
2327        );
2328    }
2329    {
2330        let tokens = convert_located(vec![
2331            TokenData::LeftParen,
2332            TokenData::Identifier("define-library".to_string()),
2333            TokenData::LeftParen,
2334            TokenData::Identifier("foo".to_string()),
2335            TokenData::RightParen,
2336            TokenData::LeftParen,
2337            TokenData::Identifier("export".to_string()),
2338            TokenData::Identifier("a".to_string()),
2339            TokenData::Identifier("b".to_string()),
2340            TokenData::RightParen,
2341            TokenData::RightParen,
2342        ]);
2343        let mut parser = token_stream_to_parser(tokens.into_iter());
2344        let library_declaration = parser.parse_root()?;
2345        assert_eq!(
2346            library_declaration,
2347            Some(Statement::LibraryDefinition(
2348                LibraryDefinition(
2349                    library_name!("foo").into(),
2350                    vec![LibraryDeclaration::Export(vec![
2351                        ExportSpec::Direct("a".to_string()).no_locate(),
2352                        ExportSpec::Direct("b".to_string()).no_locate()
2353                    ])
2354                    .into()]
2355                )
2356                .into()
2357            ))
2358        );
2359    }
2360    {
2361        let tokens = convert_located(vec![
2362            TokenData::LeftParen,
2363            TokenData::Identifier("define-library".to_string()),
2364            TokenData::LeftParen,
2365            TokenData::Identifier("foo".to_string()),
2366            TokenData::RightParen,
2367            TokenData::LeftParen,
2368            TokenData::Identifier("begin".to_string()),
2369            TokenData::LeftParen,
2370            TokenData::Identifier("define".to_string()),
2371            TokenData::Identifier("s".to_string()),
2372            TokenData::Primitive(Primitive::String("a".to_string())),
2373            TokenData::RightParen,
2374            TokenData::RightParen,
2375            TokenData::RightParen,
2376        ]);
2377        let mut parser = token_stream_to_parser(tokens.into_iter());
2378        let library_declaration = parser.parse_root()?;
2379        assert_eq!(
2380            library_declaration,
2381            Some(Statement::LibraryDefinition(
2382                LibraryDefinition(
2383                    library_name!("foo").into(),
2384                    vec![LibraryDeclaration::Begin(vec![Statement::Definition(
2385                        DefinitionBody(
2386                            "s".to_string(),
2387                            ExpressionBody::Primitive(Primitive::String("a".to_string()))
2388                                .no_locate()
2389                        )
2390                        .no_locate()
2391                    )])
2392                    .into()]
2393                )
2394                .into()
2395            ))
2396        );
2397    }
2398    Ok(())
2399}
2400/*
2401(define-library (lib-a 0 base)
2402    (import (lib-b))
2403    (begin
2404        (define c 0)
2405        (define d 1)
2406    )
2407    (export c (rename d e) f)
2408    (begin
2409        (define f 2)
2410    )
2411)
2412*/
2413#[test]
2414fn library() {
2415    {
2416        let tokens = convert_located(vec![
2417            TokenData::LeftParen,
2418            TokenData::Identifier("define-library".to_string()),
2419            TokenData::LeftParen,
2420            TokenData::Identifier("lib-a".to_string()),
2421            TokenData::Primitive(Primitive::Integer(0)),
2422            TokenData::Identifier("base".to_string()),
2423            TokenData::RightParen,
2424            TokenData::LeftParen,
2425            TokenData::Identifier("import".to_string()),
2426            TokenData::LeftParen,
2427            TokenData::Identifier("lib-b".to_string()),
2428            TokenData::RightParen,
2429            TokenData::RightParen,
2430            TokenData::LeftParen,
2431            TokenData::Identifier("begin".to_string()),
2432            TokenData::LeftParen,
2433            TokenData::Identifier("define".to_string()),
2434            TokenData::Identifier("c".to_string()),
2435            TokenData::Primitive(Primitive::Integer(0)),
2436            TokenData::RightParen,
2437            TokenData::LeftParen,
2438            TokenData::Identifier("define".to_string()),
2439            TokenData::Identifier("d".to_string()),
2440            TokenData::Primitive(Primitive::Integer(1)),
2441            TokenData::RightParen,
2442            TokenData::RightParen,
2443            TokenData::LeftParen,
2444            TokenData::Identifier("export".to_string()),
2445            TokenData::Identifier("c".to_string()),
2446            TokenData::LeftParen,
2447            TokenData::Identifier("rename".to_string()),
2448            TokenData::Identifier("d".to_string()),
2449            TokenData::Identifier("e".to_string()),
2450            TokenData::RightParen,
2451            TokenData::Identifier("f".to_string()),
2452            TokenData::RightParen,
2453            TokenData::LeftParen,
2454            TokenData::Identifier("begin".to_string()),
2455            TokenData::LeftParen,
2456            TokenData::Identifier("define".to_string()),
2457            TokenData::Identifier("f".to_string()),
2458            TokenData::Primitive(Primitive::Integer(2)),
2459            TokenData::RightParen,
2460            TokenData::RightParen,
2461            TokenData::RightParen,
2462        ]);
2463        let mut parser = token_stream_to_parser(tokens.into_iter());
2464        let ast = parser.parse_root();
2465
2466        assert_eq!(
2467            ast,
2468            Ok(Some(Statement::LibraryDefinition(
2469                LibraryDefinition(
2470                    library_name!("lib-a", 0, "base").into(),
2471                    vec![
2472                        LibraryDeclaration::ImportDeclaration(
2473                            ImportDeclaration(vec![ImportSetBody::Direct(
2474                                LibraryName(vec![LibraryNameElement::Identifier(
2475                                    "lib-b".to_string()
2476                                )])
2477                                .into()
2478                            )
2479                            .into()])
2480                            .no_locate()
2481                        )
2482                        .into(),
2483                        LibraryDeclaration::Begin(vec![
2484                            Statement::Definition(
2485                                DefinitionBody(
2486                                    "c".to_string(),
2487                                    ExpressionBody::Primitive(Primitive::Integer(0)).into()
2488                                )
2489                                .into()
2490                            ),
2491                            Statement::Definition(
2492                                DefinitionBody(
2493                                    "d".to_string(),
2494                                    ExpressionBody::Primitive(Primitive::Integer(1)).into()
2495                                )
2496                                .into()
2497                            )
2498                        ])
2499                        .into(),
2500                        LibraryDeclaration::Export(vec![
2501                            ExportSpec::Direct("c".to_string()).into(),
2502                            ExportSpec::Rename("d".to_string(), "e".to_string()).into(),
2503                            ExportSpec::Direct("f".to_string()).into(),
2504                        ])
2505                        .into(),
2506                        LibraryDeclaration::Begin(vec![Statement::Definition(
2507                            DefinitionBody(
2508                                "f".to_string(),
2509                                ExpressionBody::Primitive(Primitive::Integer(2)).into()
2510                            )
2511                            .into()
2512                        ),])
2513                        .into()
2514                    ]
2515                )
2516                .no_locate()
2517            )))
2518        )
2519    }
2520}