1use crate::literal::DefaultValue;
2use crate::term;
3use crate::Parse;
4
5impl<'a, T: Parse<'a>> Parse<'a> for Option<T> {
6 parser!(opt!(weedle!(T)));
7}
8
9impl<'a, T: Parse<'a>> Parse<'a> for Box<T> {
10 parser!(do_parse!(inner: weedle!(T) >> (Box::new(inner))));
11}
12
13impl<'a, T: Parse<'a>> Parse<'a> for Vec<T> {
15 parser!(many0!(weedle!(T)));
16}
17
18impl<'a, T: Parse<'a>, U: Parse<'a>> Parse<'a> for (T, U) {
19 parser!(do_parse!(t: weedle!(T) >> u: weedle!(U) >> ((t, u))));
20}
21
22impl<'a, T: Parse<'a>, U: Parse<'a>, V: Parse<'a>> Parse<'a> for (T, U, V) {
23 parser!(do_parse!(
24 t: weedle!(T) >> u: weedle!(U) >> v: weedle!(V) >> ((t, u, v))
25 ));
26}
27
28ast_types! {
29 #[derive(Copy, Default)]
31 struct Parenthesized<T> where [T: Parse<'a>] {
32 open_paren: term::OpenParen,
33 body: T,
34 close_paren: term::CloseParen,
35 }
36
37 #[derive(Copy, Default)]
39 struct Bracketed<T> where [T: Parse<'a>] {
40 open_bracket: term::OpenBracket,
41 body: T,
42 close_bracket: term::CloseBracket,
43 }
44
45 #[derive(Copy, Default)]
47 struct Braced<T> where [T: Parse<'a>] {
48 open_brace: term::OpenBrace,
49 body: T,
50 close_brace: term::CloseBrace,
51 }
52
53 #[derive(Copy, Default)]
55 struct Generics<T> where [T: Parse<'a>] {
56 open_angle: term::LessThan,
57 body: T,
58 close_angle: term::GreaterThan,
59 }
60
61 struct Punctuated<T, S> where [T: Parse<'a>, S: Parse<'a> + ::std::default::Default] {
63 list: Vec<T> = separated_list!(weedle!(S), weedle!(T)),
64 separator: S = marker,
65 }
66
67 struct PunctuatedNonEmpty<T, S> where [T: Parse<'a>, S: Parse<'a> + ::std::default::Default] {
69 list: Vec<T> = terminated!(
70 separated_nonempty_list!(weedle!(S), weedle!(T)),
71 opt!(weedle!(S))
72 ),
73 separator: S = marker,
74 }
75
76 #[derive(Copy)]
80 struct Identifier<'a>(
81 &'a str = ws!(do_parse!(
84 opt!(char!('_')) >>
85 id: recognize!(do_parse!(
86 take_while1!(|c: char| c.is_ascii_alphabetic()) >>
87 take_while!(|c: char| c.is_ascii_alphanumeric() || c == '_' || c == '-') >>
88 (())
89 )) >>
90 (id)
91 )),
92 )
93
94 #[derive(Copy)]
96 struct Default<'a> {
97 assign: term!(=),
98 value: DefaultValue<'a>,
99 }
100}
101
102#[cfg(test)]
103mod test {
104 use super::*;
105
106 test!(should_parse_optional_present { "one" =>
107 "";
108 Option<Identifier>;
109 is_some();
110 });
111
112 test!(should_parse_optional_not_present { "" =>
113 "";
114 Option<Identifier>;
115 is_none();
116 });
117
118 test!(should_parse_boxed { "one" =>
119 "";
120 Box<Identifier>;
121 });
122
123 test!(should_parse_vec { "one two three" =>
124 "";
125 Vec<Identifier>;
126 len() == 3;
127 });
128
129 test!(should_parse_parenthesized { "( one )" =>
130 "";
131 Parenthesized<Identifier>;
132 body.0 == "one";
133 });
134
135 test!(should_parse_bracketed { "[ one ]" =>
136 "";
137 Bracketed<Identifier>;
138 body.0 == "one";
139 });
140
141 test!(should_parse_braced { "{ one }" =>
142 "";
143 Braced<Identifier>;
144 body.0 == "one";
145 });
146
147 test!(should_parse_generics { "<one>" =>
148 "";
149 Generics<Identifier>;
150 body.0 == "one";
151 });
152
153 test!(should_parse_generics_two { "<one, two>" =>
154 "";
155 Generics<(Identifier, term!(,), Identifier)> =>
156 Generics {
157 open_angle: term!(<),
158 body: (Identifier("one"), term!(,), Identifier("two")),
159 close_angle: term!(>),
160 }
161 });
162
163 test!(should_parse_comma_separated_values { "one, two, three" =>
164 "";
165 Punctuated<Identifier, term!(,)>;
166 list.len() == 3;
167 });
168
169 test!(err should_not_parse_comma_separated_values_empty { "" =>
170 PunctuatedNonEmpty<Identifier, term!(,)>
171 });
172
173 test!(should_parse_identifier { "hello" =>
174 "";
175 Identifier;
176 0 == "hello";
177 });
178
179 test!(should_parse_numbered_identifier { "hello5" =>
180 "";
181 Identifier;
182 0 == "hello5";
183 });
184
185 test!(should_parse_underscored_identifier { "_hello_" =>
186 "";
187 Identifier;
188 0 == "hello_";
189 });
190
191 test!(should_parse_identifier_surrounding_with_spaces { " hello " =>
192 "";
193 Identifier;
194 0 == "hello";
195 });
196
197 test!(should_parse_identifier_preceeding_others { "hello note" =>
198 "note";
199 Identifier;
200 0 == "hello";
201 });
202
203 test!(should_parse_identifier_attached_to_symbol { "hello=" =>
204 "=";
205 Identifier;
206 0 == "hello";
207 });
208}