parser_test/
lib.rs

1use std::fmt::Debug;
2
3pub mod highlighter;
4
5/// Parser output tokens should implement this trait
6pub trait Token {
7    type Rule;
8
9    fn start(&self) -> usize;
10    fn end(&self) -> usize;
11    fn rule(&self) -> Self::Rule;
12}
13
14pub struct TestToken<R> {
15    pub start: usize,
16    pub end: usize,
17    pub rule: R,
18}
19
20impl<R: Copy> Token for TestToken<R> {
21    type Rule = R;
22
23    fn start(&self) -> usize {
24        self.start
25    }
26    fn end(&self) -> usize {
27        self.end
28    }
29    fn rule(&self) -> Self::Rule {
30        self.rule
31    }
32}
33
34pub fn test<O, E, R>(output: O, expected: E, spans: &str) -> bool
35    where O: IntoIterator,
36          <O as IntoIterator>::Item: Token<Rule = R>,
37          E: IntoIterator<Item = R>,
38          R: Eq + Sized + Debug,
39{
40    let mut expected_spans = highlighter::Highlighter::new(spans);
41    let mut expected = expected.into_iter();
42    for actual_output in output {
43        let expected_span = expected_spans.next().expect("Not enough spans defined");
44        let expected_output = expected.next().expect("More output than expected");
45        if actual_output.rule() != expected_output {
46            panic!("Expected rule: {:?} got: {:?} at pos:{}",
47                   expected_output,
48                   actual_output.rule(),
49                   actual_output.start()
50            );
51        }
52        if actual_output.start() != expected_span.0 || actual_output.end() != expected_span.1 {
53            panic!("Spans do not match on rule: {:?}: [{}, {}] vs [{}, {}]",
54                   actual_output.rule(),
55                   actual_output.start(),
56                   actual_output.end(),
57                   expected_span.0,
58                   expected_span.1
59            );
60        }
61    }
62    assert!(expected.next().is_none(), "Expected more output");
63    assert!(expected_spans.next().is_none(), "Defined more spans than expected rules");
64
65    true
66}