1pub use directive::Directive;
2pub use owner::Owner;
3pub use per_file::PerFile;
4pub use statement::Statement;
5
6use error::ParseError;
7
8pub mod error;
9
10mod directive;
11mod owner;
12mod per_file;
13mod statement;
14
15pub fn parse<T: AsRef<str>>(input: T) -> Result<Vec<Statement>, ParseError> {
16 let filtered = input
17 .as_ref()
18 .split("\n")
19 .enumerate()
21 .map(|(line_num, content)| (line_num + 1, remove_inline_comments(content)))
23 .filter(|(_, content)| !content.is_empty() && !content.starts_with("#"));
25
26 let mut parsed = vec![];
27 for (line_num, content) in filtered {
28 statement::statement(content)
29 .map(|(_, output)| parsed.push(output))
30 .map_err(|e| ParseError::from_nom(line_num, e))?;
31 }
32 Ok(parsed)
33}
34
35fn is_whitespace(c: char) -> bool {
36 c == ' ' || c == '\t' || c == '\n'
37}
38
39fn remove_inline_comments(line: &str) -> &str {
43 line.trim().split("#").nth(0).unwrap()
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn empty() {
52 assert!(parse("").unwrap().is_empty());
53 }
54
55 #[test]
56 fn empty_ws() {
57 assert!(parse(" ").unwrap().is_empty());
58 }
59
60 #[test]
61 fn comment() {
62 assert!(parse("# comment").unwrap().is_empty());
63 }
64
65 #[test]
66 fn comment_ws() {
67 assert!(parse("#comment").unwrap().is_empty());
68 }
69
70 #[test]
71 fn inline_comment() {
72 assert_eq!(
73 parse("set noparent # comment").unwrap(),
74 vec![Statement::Directive(Directive::NoParent)]
75 );
76 }
77
78 #[test]
79 fn inline_comment_ws() {
80 assert_eq!(
81 parse("set noparent# comment").unwrap(),
82 vec![Statement::Directive(Directive::NoParent)]
83 );
84 }
85
86 #[test]
87 fn multiline() {
88 assert_eq!(
89 parse("set noparent\n*").unwrap(),
90 vec![
91 Statement::Directive(Directive::NoParent),
92 Statement::Directive(Directive::StarGlob)
93 ]
94 );
95 }
96
97 #[test]
98 fn multiline_trailing_newline() {
99 assert_eq!(
100 parse("set noparent\n*\n").unwrap(),
101 vec![
102 Statement::Directive(Directive::NoParent),
103 Statement::Directive(Directive::StarGlob)
104 ]
105 );
106 }
107
108 #[test]
109 fn multiline_leading_newline() {
110 assert_eq!(
111 parse("\nset noparent\n*").unwrap(),
112 vec![
113 Statement::Directive(Directive::NoParent),
114 Statement::Directive(Directive::StarGlob)
115 ]
116 );
117 }
118
119 #[test]
120 fn multiline_comments() {
121 assert_eq!(
122 parse("set noparent # comment\n* # comment").unwrap(),
123 vec![
124 Statement::Directive(Directive::NoParent),
125 Statement::Directive(Directive::StarGlob)
126 ]
127 );
128 }
129}