1mod data;
17mod loc;
18mod parser;
19mod printer;
20mod tokenizer;
21mod utf8;
22
23pub use data::{ABytes, ADecimal, ANum, Atom, GroupKind};
24pub use loc::{Position, Span};
25pub use parser::{Element, Parser, ParserError, SpannedElement};
26pub use printer::Printer;
27pub use tokenizer::{SpannedToken, Token, TokenError, Tokenizer, TokenizerConfig};
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 const PROG1: &str = r#"
34(define x 1) ; this is a post comment
35; this is a comment
36(define y 0x01_ab)
37(if (zero? x)
38 (strip " " "abc")
39 [1 2 "def\"x"]
40)
41"#;
42
43 const PROG2: &str = r#"
44 (define hello world 123)
45
46 ; comment space
47 #1234# ( (let x 1) (let y = x + x) 123 x ) "string"
48
49 ( "this is a quote char: \" " )
50
51 (== (/ (+ 1 2) 3) 1)
52 (pöjk unicode) ; unicode support
53"#;
54
55 fn collect_tokens<'a>(
56 mut tokenizer: Tokenizer<'a>,
57 ) -> Result<Vec<SpannedToken<'a>>, TokenError> {
58 let mut toks = Vec::new();
59 loop {
60 match tokenizer.next() {
61 Ok(Some(tok)) => toks.push(tok),
62 Ok(None) => break,
63 Err(e) => return Err(e),
64 }
65 }
66 return Ok(toks);
67 }
68
69 #[test]
70 fn prog1_tokenize() {
71 let toks1 = collect_tokens(Tokenizer::new(PROG1));
72 assert!(toks1.is_ok())
73 }
74
75 #[test]
76 fn prog2_tokenize() {
77 let toks2 = collect_tokens(Tokenizer::new(PROG2));
78 assert!(toks2.is_ok())
79 }
80
81 #[test]
82 fn prog1_parser() {
83 let mut parser = Parser::new_with_config(PROG1, TokenizerConfig::default().comment(false));
84 {
85 let first_element = parser
86 .next()
87 .expect("parser error")
88 .expect("not end of stream");
89 let e0 = first_element.inner.paren().expect("first group is paren");
90 assert_eq!(e0[0].inner.atom().and_then(|a| a.ident()), Some("define"));
91 assert_eq!(e0[1].inner.atom().and_then(|a| a.ident()), Some("x"));
92 assert_eq!(
93 e0[2]
94 .inner
95 .atom()
96 .and_then(|a| a.number())
97 .and_then(|n| n.to_u64().ok()),
98 Some(1)
99 )
100 }
101 {
102 let second_element = parser
103 .next()
104 .expect("parser error")
105 .expect("not end of stream");
106 let e0 = second_element.inner.paren().expect("second group is paren");
107 assert_eq!(e0[0].inner.atom().and_then(|a| a.ident()), Some("define"));
108 assert_eq!(e0[1].inner.atom().and_then(|a| a.ident()), Some("y"));
109 assert_eq!(
110 e0[2]
111 .inner
112 .atom()
113 .and_then(|a| a.number())
114 .and_then(|n| n.to_u64().ok()),
115 Some(0x01_ab)
116 )
117 }
118
119 {
120 let third_element = parser
121 .next()
122 .expect("parser error")
123 .expect("not end of stream");
124 let e0 = third_element.inner.paren().expect("third group is paren");
125 assert_eq!(e0[0].inner.atom().and_then(|a| a.ident()), Some("if"));
126 let conditional = e0[1].inner.paren().expect("conditional");
127 assert_eq!(
128 conditional[0].inner.atom().and_then(|a| a.ident()),
129 Some("zero?")
130 );
131 assert_eq!(
132 conditional[1].inner.atom().and_then(|a| a.ident()),
133 Some("x")
134 );
135 let then_expr = e0[2].inner.paren().expect("then");
136 assert_eq!(
137 then_expr[0].inner.atom().and_then(|a| a.ident()),
138 Some("strip")
139 );
140 assert_eq!(
141 then_expr[1]
142 .inner
143 .atom()
144 .and_then(|a| a.string())
145 .map(|s| s.to_string()),
146 Some(" ".to_string())
147 );
148 assert_eq!(
149 then_expr[2]
150 .inner
151 .atom()
152 .and_then(|a| a.string())
153 .map(|s| s.to_string()),
154 Some("abc".to_string())
155 );
156
157 let _else_expr = e0[3].inner.bracket().expect("else");
158 }
159 }
160}