]> Witch of Git - ess/blob - src/parser.rs
Add quasiquote with `
[ess] / src / parser.rs
1 //! Functions to parse s-expressions and expression atoms.
2 //!
3 //! This module contains the core parsing machinery.
4 //!
5 //! * If you're interested in getting a parsed s-expression that you can use,
6 //! then looking at [`parse`] and [`parse_one`] are your best bet.
7 //! * If you want to write your own parsers that contain s-expressions,
8 //! [`ParseResult`] and [`parse_expression`] will be the most useful to you.
9 //!
10 //! [`parse`]: fn.parse.html
11 //! [`parse_one`]: fn.parse_one.html
12 //! [`ParseResult`]: enum.ParseResult.html
13 //! [`parse_expression`]: fn.parse_expression.html
14
15 use sexp::Sexp;
16 use span::{Span, ByteSpan};
17
18 \f
19 // Parsing Types ///////////////////////////////////////////////////////////////
20
21 /// Represents what to do next in partially completed parsing.
22 ///
23 /// `ParseResult` is returned from all intermediate parsers. If you just want to
24 /// get back parsed s-expressions, you won't need to worry about this type since
25 /// the top level parsers just return a `Result`.
26 ///
27 /// If the parser failed to produce a result, it will return `Error`, and if it
28 /// succeeded we'll get the `Done` variant containing the value produced and the
29 /// rest of the text to work on.
30 #[derive(Debug, PartialEq, Eq, Clone)]
31 pub enum ParseResult<'a, T, E> {
32 /// The parser succeeded, this contains first the un-consumed portion of the
33 /// input then the result produced by parsing.
34 Done(&'a str, T),
35 /// The parser failed, the `E` represents the reason for the failure.
36 Error(E),
37 }
38
39 /// Indicates how parsing failed.
40 ///
41 /// Most `ParseError` variants contain a `Box<ParseError>` that represents the
42 /// cause of that error. Using this, `ParseError` variants can be chained to
43 /// produce a more complete picture of what exactly went wrong during parsing.
44 #[derive(Debug, PartialEq, Eq, Clone)]
45 pub enum ParseError<Loc=ByteSpan> where Loc: Span {
46 /// Parsing reached the end of input where not expecting to, usually this
47 /// will be contained inside another `ParseError` like `String(box
48 /// UnexpectedEof, ...)` which indicates that the closing quote was never
49 /// found.
50 UnexpectedEof,
51 /// Some problem occurred while parsing a list, along with the cause of that
52 /// error.
53 List(Box<ParseError>, Loc),
54 /// Some problem occurred while parsing an s-expression. This will only be
55 /// generated if EOF is reached unexpectedly at the beginning of
56 /// `parse_expression`, so it should probably be removed.
57 Sexp(Box<ParseError>, Loc),
58 /// Some problem occurred while parsing a character literal, along with the
59 /// cause of the error.
60 Char(Box<ParseError>, Loc),
61 /// Some problem occurred while parsing a string literal, along with the
62 /// cause of the error.
63 String(Box<ParseError>, Loc),
64 /// Some problem occurred while parsing a symbol, along with the cause of
65 /// the error.
66 Symbol(Box<ParseError>, Loc),
67 /// Some problem occurred while parsing a number literal, along with the
68 /// cause of the error.
69 Number(Box<ParseError>, Loc),
70 /// An unexpected character was found. This will usually be the root cause
71 /// in some chain of `ParseError`s.
72 Unexpected(char, Loc::Begin),
73 }
74 use self::ParseResult::*;
75
76 \f
77 // Parsing Utilities ///////////////////////////////////////////////////////////
78
79 trait IsDelimeter {
80 fn is_delimiter(&self) -> bool;
81 }
82
83 impl IsDelimeter for char {
84 fn is_delimiter(&self) -> bool {
85 self.is_whitespace() || *self == ';'
86 || *self == '(' || *self == ')'
87 || *self == '[' || *self == ']'
88 || *self == '{' || *self == '}'
89 || *self == '"' || *self == '\''
90 || *self == '`' || *self == ','
91 }
92 }
93
94 macro_rules! consume_whitespace {
95 ($input:expr, $start_loc:expr, $ErrorFn:expr) => {
96 if let Some(pos) = $input.find(|c: char| !c.is_whitespace()) {
97 (&$input[pos..], $start_loc + pos)
98 } else {
99 return Error($ErrorFn(
100 Box::new(ParseError::UnexpectedEof),
101 ($input.len(), $input.len()).offset($start_loc)));
102 }
103 }
104 }
105
106 \f
107 // Top Level Parsers ///////////////////////////////////////////////////////////
108
109 /// Parse a sequence of s-expressions.
110 ///
111 /// This function returns `(Vec<Sexp>, Option<ParseError>)` so that it can
112 /// return partial results, for when some component parses successfully and a
113 /// later part fails.
114 ///
115 /// # Errors
116 ///
117 /// If the text contains an invalid s-expression (imbalanced parenthesis,
118 /// quotes, invalid numbers like 123q, etc.) then the parser will stop and
119 /// return an error. Every s-expression before that point that successfully
120 /// parsed will still be returned.
121 ///
122 /// # Examples
123 ///
124 /// We can get useful partial results
125 ///
126 /// ```rust
127 /// # use ess::parser::parse;
128 /// let (exprs, err) = parse("1 2 3 ( 4");
129 /// assert_eq!(exprs.len(), 3);
130 /// assert!(err.is_some());
131 /// ```
132 pub fn parse(mut input: &str) -> (Vec<Sexp>, Option<ParseError>) {
133 let mut start_loc = 0;
134 let mut results = Vec::new();
135 loop {
136 match parse_expression(input, start_loc) {
137 Done(rest, result) => {
138 input = rest;
139 start_loc = result.get_loc().1;
140 results.push(result);
141 if rest.trim() == "" {
142 return (results, None);
143 }
144 }
145 Error(err) => {
146 return (results, Some(err));
147 }
148 }
149 }
150 }
151
152 /// Parses a single s-expression, ignoring any trailing text.
153 ///
154 /// This function returns a pair of the parsed s-expression and the tail of the text.
155 ///
156 /// # Errors
157 ///
158 /// If the text begins with an invalid s-expression (imbalanced parenthesis,
159 /// quotes, invalid numbers like 123q, etc.) then the parser will return an
160 /// error. Any text after the first s-expression doesn't affect the parsing.
161 ///
162 /// # Examples
163 ///
164 /// ```rust
165 /// # use ess::parser::parse_one;
166 /// let (expr, rest) = parse_one("1 (").unwrap();
167 /// assert_eq!(rest, " (");
168 /// ```
169 pub fn parse_one(input: &str) -> Result<(Sexp, &str), ParseError> {
170 match parse_expression(input, 0) {
171 Done(rest, result) => Ok((result, rest)),
172 Error(err) => Err(err),
173 }
174 }
175
176 \f
177 // Core Parsers ////////////////////////////////////////////////////////////////
178
179 // TODO: All of these parsers deserve docs, but since they're somewhat internal
180 // parsers, it's less critical than the rest of the API.
181
182 #[allow(missing_docs)]
183 pub fn parse_expression(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
184 let (input, start_loc) = consume_whitespace!(input, start_loc, ParseError::Sexp);
185
186 match input.chars().next() {
187 Some('0'...'9') => parse_number(input, start_loc),
188 Some('(') => parse_list(input, start_loc),
189 Some('#') => parse_character(input, start_loc),
190 Some('"') => parse_string(input, start_loc),
191 Some('\'') => {
192 match parse_expression(&input[1..], start_loc + 1) {
193 Done(rest, result) => {
194 let span = *result.get_loc();
195 let quote_span = (0, 1).offset(start_loc);
196 Done(rest,
197 Sexp::List(vec![Sexp::Sym("quote".into(), quote_span), result],
198 quote_span.union(&span)))
199 }
200 err => err,
201 }
202 }
203 Some('`') => {
204 match parse_expression(&input[1..], start_loc + 1) {
205 Done(rest, result) => {
206 let span = *result.get_loc();
207 let quote_span = (0, 1).offset(start_loc);
208 Done(rest,
209 Sexp::List(vec![Sexp::Sym("quasiquote".into(), quote_span),
210 result],
211 quote_span.union(&span)))
212 }
213 err => err,
214 }
215 }
216 Some(_) => parse_symbol(input, start_loc),
217 None => unreachable!(),
218 }
219 }
220
221 #[allow(missing_docs)]
222 pub fn parse_list(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
223 let (input, start_loc) = consume_whitespace!(input, start_loc, ParseError::List);
224
225 match input.chars().nth(0) {
226 Some('(') => (),
227 Some(c) =>
228 return Error(ParseError::List(
229 Box::new(ParseError::Unexpected(c, 0)),
230 (0, 0).offset(start_loc))),
231 None => unreachable!(),
232 }
233
234 let mut input = &input[1..];
235 let mut loc = start_loc + 1;
236 let mut members = Vec::new();
237 loop {
238 {
239 let (new_input, new_loc) = consume_whitespace!(input, loc, ParseError::List);
240 input = new_input;
241 loc = new_loc;
242 }
243
244 match input.chars().nth(0) {
245 Some(')') =>
246 return Done(&input[1..],
247 Sexp::List(members, (start_loc, loc+1))),
248 Some(_) => (),
249 None => unreachable!(),
250 }
251
252 match parse_expression(input, loc) {
253 Done(new_input, member) => {
254 loc = member.get_loc().1;
255 members.push(member);
256 input = new_input;
257 }
258 Error(err) =>
259 return Error(ParseError::List(
260 Box::new(err),
261 (0, 0).offset(loc)))
262 }
263 }
264 }
265
266 #[allow(missing_docs)]
267 pub fn parse_number(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
268 let (input, start_loc) = consume_whitespace!(input, start_loc, ParseError::Number);
269
270 match input.chars().next() {
271 Some(c) if !c.is_digit(10) => {
272 return Error(ParseError::Number(
273 Box::new(ParseError::Unexpected(c, start_loc)),
274 (0, c.len_utf8()).offset(start_loc)));
275 }
276 None => return Error(ParseError::Number(
277 Box::new(ParseError::UnexpectedEof),
278 (0, 0).offset(start_loc))),
279 _ => (),
280 }
281
282 let base = 10;
283
284 let mut end = 0;
285 // Before the decimal point
286 for (i, c) in input.char_indices() {
287 if c == '.' {
288 end = i + 1;
289 break;
290 }
291
292 if c.is_delimiter() {
293 return Done(&input[i..],
294 Sexp::Int(input[..i].parse().expect("Already matched digits"),
295 (0, i).offset(start_loc)));
296 }
297
298 if !c.is_digit(base) {
299 return Error(ParseError::Number(
300 Box::new(ParseError::Unexpected(c, start_loc + i)),
301 (i, i).offset(start_loc)));
302 }
303
304 end = i + c.len_utf8();
305 }
306
307 if input[end..].is_empty() {
308 return Done(&input[end..],
309 Sexp::Int(input.parse().expect("Already matched digits"),
310 (0, end).offset(start_loc)));
311 }
312
313 // After the decimal point
314 for (i, c) in input[end..].char_indices() {
315 if c.is_delimiter() {
316 return Done(&input[i+end..],
317 Sexp::Float(input[..end+i].parse().expect("Already matched digits.digits"),
318 (0, end+i).offset(start_loc)));
319 }
320
321 if !c.is_digit(base) {
322 return Error(ParseError::Number(
323 Box::new(ParseError::Unexpected(c, start_loc + i + end)),
324 (i+end, i+end).offset(start_loc)));
325 }
326 }
327
328 Done(&input[input.len()..],
329 Sexp::Float(input.parse().expect("Already matched digits.digits"),
330 (0, input.len()).offset(start_loc)))
331 }
332
333 #[allow(missing_docs)]
334 pub fn parse_symbol(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
335 let (input, start_loc) = consume_whitespace!(input, start_loc, ParseError::Symbol);
336
337 match input.chars().next() {
338 Some(c@'#') | Some(c@':') | Some(c@'0'...'9') =>
339 return Error(ParseError::Symbol(
340 Box::new(ParseError::Unexpected(c, start_loc)),
341 (0, 0).offset(start_loc))),
342 Some(c) if c.is_delimiter() =>
343 return Error(ParseError::Symbol(
344 Box::new(ParseError::Unexpected(c, start_loc)),
345 (0, 0).offset(start_loc))),
346 Some(_) => (),
347 None => unreachable!(),
348 }
349
350 for (i, c) in input.char_indices() {
351 if c.is_delimiter() {
352 return Done(&input[i..],
353 Sexp::Sym(input[..i].into(), (0, i).offset(start_loc)));
354 }
355 }
356
357 Done(&input[input.len()..],
358 Sexp::Sym(input.into(), (0, input.len()).offset(start_loc)))
359 }
360
361 #[allow(missing_docs)]
362 pub fn parse_string(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
363 let (input, start_loc) = consume_whitespace!(input, start_loc, ParseError::String);
364
365 match input.chars().next() {
366 Some('"') => (),
367 Some(c) =>
368 return Error(ParseError::String(
369 Box::new(ParseError::Unexpected(c, start_loc)),
370 (0, 0).offset(start_loc))),
371 None => unreachable!(),
372 }
373
374 for (i, c) in input[1..].char_indices() {
375 if c == '"' {
376 return Done(&input[2+i..],
377 Sexp::Str(input[1..i+1].into(), (0, i+2).offset(start_loc)));
378 }
379 }
380
381 Error(ParseError::String(
382 Box::new(ParseError::UnexpectedEof),
383 (0, input.len()).offset(start_loc)))
384 }
385
386 #[allow(missing_docs)]
387 pub fn parse_character(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
388 let (input, start_loc) = consume_whitespace!(input, start_loc, ParseError::Char);
389
390 match input.chars().nth(0) {
391 Some('#') => (),
392 Some(c) =>
393 return Error(ParseError::Char(
394 Box::new(ParseError::Unexpected(c, start_loc)),
395 (0, 0).offset(start_loc))),
396 None =>
397 return Error(ParseError::Char(
398 Box::new(ParseError::UnexpectedEof),
399 (0, 0).offset(start_loc))),
400 }
401
402 match input.chars().nth(1) {
403 Some('\\') => (),
404 Some(c) =>
405 return Error(ParseError::Char(
406 Box::new(ParseError::Unexpected(c, start_loc + 1)),
407 (1, 1).offset(start_loc))),
408 None =>
409 return Error(ParseError::Char(
410 Box::new(ParseError::UnexpectedEof),
411 (1, 1).offset(start_loc)))
412 }
413
414 match input.chars().nth(2) {
415 Some(c) =>
416 Done(&input[3..], Sexp::Char(c, (0, 3).offset(start_loc))),
417 None =>
418 Error(ParseError::Char(
419 Box::new(ParseError::UnexpectedEof),
420 (2, 2).offset(start_loc)))
421 }
422 }
423
424 \f
425 // Tests ///////////////////////////////////////////////////////////////////////
426
427 #[cfg(test)]
428 mod test {
429 use sexp::Sexp;
430 use span::Span;
431 use parser::*;
432 use parser::ParseResult::*;
433
434 #[test]
435 fn test_parse() {
436 assert_eq!(parse("1 2 3"), (vec![
437 Sexp::Int(1, (0, 1)), Sexp::Int(2, (2, 3)), Sexp::Int(3, (4, 5))
438 ], None));
439 assert_eq!(parse("1 2 )"), (vec![
440 Sexp::Int(1, (0, 1)), Sexp::Int(2, (2, 3))
441 ], Some(ParseError::Symbol(Box::new(ParseError::Unexpected(')', 4)), (4, 4)))));
442 }
443
444 #[test]
445 fn test_parse_one() {
446 assert_eq!(parse_one("1 2"),
447 Ok((Sexp::Int(1, (0, 1)), " 2")));
448 }
449
450 #[test]
451 fn test_parse_expression() {
452 assert_eq!(parse_expression(" 1", 0),
453 Done("", Sexp::Int(1, (1, 2))));
454 assert_eq!(parse_expression("2.2", 0),
455 Done("", Sexp::Float(2.2, (0, 3))));
456 assert_eq!(parse_expression(" a", 0),
457 Done("", Sexp::Sym("a".into(), (1, 2))));
458 assert_eq!(parse_expression("#\\c", 0),
459 Done("", Sexp::Char('c', (0, 3))));
460 assert_eq!(parse_expression(r#""hi""#, 0),
461 Done("", Sexp::Str("hi".into(), (0, 4))));
462 assert_eq!(parse_expression("()", 0),
463 Done("", Sexp::List(vec![], (0, 2))));
464 assert_eq!(parse_expression("( 1 2 3 )", 0),
465 Done("", Sexp::List(vec![
466 Sexp::Int(1, (2, 3)),
467 Sexp::Int(2, (4, 5)),
468 Sexp::Int(3, (6, 7)),
469 ], (0, 9))));
470
471 assert_eq!(parse_expression("", 0),
472 Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (0, 0))));
473 }
474
475 #[test]
476 fn test_parse_expr_quote() {
477 assert_eq!(parse_expression("'a", 0),
478 Done("", Sexp::List(vec![
479 Sexp::Sym("quote".into(), (0, 1)),
480 Sexp::Sym("a".into(), (1, 2)),
481 ], (0, 2))));
482 assert_eq!(parse_expression("'1", 0),
483 Done("", Sexp::List(vec![
484 Sexp::Sym("quote".into(), (0, 1)),
485 Sexp::Int(1, (1, 2)),
486 ], (0, 2))));
487 assert_eq!(parse_expression("' (1 2 3)", 0),
488 Done("", Sexp::List(vec![
489 Sexp::Sym("quote".into(), (0, 1)),
490 Sexp::List(vec![
491 Sexp::Int(1, (3, 4)),
492 Sexp::Int(2, (5, 6)),
493 Sexp::Int(3, (7, 8)),
494 ], (2, 9)),
495 ], (0, 9))));
496
497 assert_eq!(parse_expression("'", 0),
498 Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (1, 1))));
499 assert_eq!(parse_expression("`'", 0),
500 Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (2, 2))));
501 }
502
503 #[test]
504 fn test_parse_expr_quasiquote() {
505 assert_eq!(parse_expression("`a", 0),
506 Done("", Sexp::List(vec![
507 Sexp::Sym("quasiquote".into(), (0, 1)),
508 Sexp::Sym("a".into(), (1, 2)),
509 ], (0, 2))));
510 assert_eq!(parse_expression("`1", 0),
511 Done("", Sexp::List(vec![
512 Sexp::Sym("quasiquote".into(), (0, 1)),
513 Sexp::Int(1, (1, 2)),
514 ], (0, 2))));
515 assert_eq!(parse_expression("` (1 2 3)", 0),
516 Done("", Sexp::List(vec![
517 Sexp::Sym("quasiquote".into(), (0, 1)),
518 Sexp::List(vec![
519 Sexp::Int(1, (3, 4)),
520 Sexp::Int(2, (5, 6)),
521 Sexp::Int(3, (7, 8)),
522 ], (2, 9)),
523 ], (0, 9))));
524 assert_eq!(parse_expression("`'a", 0),
525 Done("", Sexp::List(vec![
526 Sexp::Sym("quasiquote".into(), (0, 1)),
527 Sexp::List(vec![
528 Sexp::Sym("quote".into(), (1, 2)),
529 Sexp::Sym("a".into(), (2, 3)),
530 ], (1, 3)),
531 ], (0, 3))));
532
533 assert_eq!(parse_expression("`", 0),
534 Error(ParseError::Sexp(Box::new(ParseError::UnexpectedEof), (1, 1))));
535 }
536
537 #[test]
538 fn test_parse_list() {
539 assert_eq!(parse_list("()", 0),
540 Done("", Sexp::List(vec![], (0, 2))));
541 assert_eq!(parse_list("(1)", 0),
542 Done("", Sexp::List(vec![Sexp::Int(1, (1, 2))], (0, 3))));
543 assert_eq!(parse_list(" ( 1 2 3 a )", 0), Done("", Sexp::List(vec![
544 Sexp::Int(1, (4, 5)),
545 Sexp::Int(2, (9, 10)),
546 Sexp::Int(3, (12, 13)),
547 Sexp::Sym("a".into(), (14, 15)),
548 ], (2, 17))));
549 }
550
551 #[test]
552 fn test_parse_number() {
553 assert_eq!(parse_number("1", 0),
554 Done("", Sexp::Int(1, (0, 1))));
555 assert_eq!(parse_number(" 13", 0),
556 Done("", Sexp::Int(13, (1, 3))));
557 assert_eq!(parse_number("1.2", 0),
558 Done("", Sexp::Float(1.2, (0, 3))));
559 assert_eq!(parse_number("\u{3000}4.2", 0),
560 Done("", Sexp::Float(4.2, (0, 3).offset('\u{3000}'.len_utf8()))));
561 assert_eq!(parse_number(" 42 ", 0),
562 Done(" ", Sexp::Int(42, (2, 4))));
563 assert_eq!(parse_number(" 4.2 ", 0),
564 Done(" ", Sexp::Float(4.2, (1, 4))));
565 assert_eq!(parse_number("1()", 0),
566 Done("()", Sexp::Int(1, (0, 1))));
567 assert_eq!(parse_number("3.6()", 0),
568 Done("()", Sexp::Float(3.6, (0, 3))));
569
570 assert_eq!(parse_number("", 0),
571 Error(ParseError::Number(Box::new(ParseError::UnexpectedEof), (0, 0))));
572 assert_eq!(parse_number("123a", 0),
573 Error(ParseError::Number(Box::new(ParseError::Unexpected('a', 3)), (3, 3))));
574 assert_eq!(parse_number("66.6+", 0),
575 Error(ParseError::Number(Box::new(ParseError::Unexpected('+', 4)), (4, 4))));
576 }
577
578 #[test]
579 fn test_parse_ident() {
580 assert_eq!(parse_symbol("+", 0),
581 Done("", Sexp::Sym("+".into(), (0, 1))));
582 assert_eq!(parse_symbol(" nil?", 0),
583 Done("", Sexp::Sym("nil?".into(), (1, 5))));
584 assert_eq!(parse_symbol(" ->socket", 0),
585 Done("", Sexp::Sym("->socket".into(), (1, 9))));
586 assert_eq!(parse_symbol("fib(", 0),
587 Done("(", Sexp::Sym("fib".into(), (0, 3))));
588 assert_eq!(parse_symbol("foo2", 0),
589 Done("", Sexp::Sym("foo2".into(), (0, 4))));
590
591 // We reserve #foo for the implementation to do as it wishes
592 assert_eq!(parse_symbol("#hi", 0),
593 Error(ParseError::Symbol(Box::new(ParseError::Unexpected('#', 0)), (0, 0))));
594 // We reserve :foo for keywords
595 assert_eq!(parse_symbol(":hi", 0),
596 Error(ParseError::Symbol(Box::new(ParseError::Unexpected(':', 0)), (0, 0))));
597
598 assert_eq!(parse_symbol("", 0),
599 Error(ParseError::Symbol(Box::new(ParseError::UnexpectedEof), (0, 0))));
600 assert_eq!(parse_symbol("0", 0),
601 Error(ParseError::Symbol(Box::new(ParseError::Unexpected('0', 0)), (0, 0))));
602 assert_eq!(parse_symbol("()", 0),
603 Error(ParseError::Symbol(Box::new(ParseError::Unexpected('(', 0)), (0, 0))));
604 }
605
606 #[test]
607 fn test_parse_string() {
608 assert_eq!(parse_string(r#""""#, 0),
609 Done("", Sexp::Str("".into(), (0, 2))));
610 assert_eq!(parse_string(r#""hello""#, 0),
611 Done("", Sexp::Str("hello".into(), (0, 7))));
612 assert_eq!(parse_string(r#" "this is a nice string
613 with 0123 things in it""#, 0),
614 Done("", Sexp::Str("this is a nice string\nwith 0123 things in it".into(), (2, 48))));
615
616 assert_eq!(parse_string("", 0),
617 Error(ParseError::String(Box::new(ParseError::UnexpectedEof), (0, 0))));
618 assert_eq!(parse_string(r#""hi"#, 0),
619 Error(ParseError::String(Box::new(ParseError::UnexpectedEof), (0, 3))));
620 }
621
622 #[test]
623 fn test_parse_char() {
624 assert_eq!(parse_character(r#"#\""#, 0), Done("", Sexp::Char('"', (0, 3))));
625 assert_eq!(parse_character(r#"#\ "#, 0), Done("", Sexp::Char(' ', (0, 3))));
626 assert_eq!(parse_character(r#" #\\"#, 0), Done("", Sexp::Char('\\', (2, 5))));
627
628 assert_eq!(parse_character("", 0),
629 Error(ParseError::Char(Box::new(ParseError::UnexpectedEof), (0, 0))));
630 assert_eq!(parse_character("#", 0),
631 Error(ParseError::Char(Box::new(ParseError::UnexpectedEof), (1, 1))));
632 assert_eq!(parse_character("#\\", 0),
633 Error(ParseError::Char(Box::new(ParseError::UnexpectedEof), (2, 2))));
634 assert_eq!(parse_character("a", 0),
635 Error(ParseError::Char(Box::new(ParseError::Unexpected('a', 0)), (0, 0))));
636 }
637 }