Skip to main content

weedle/
common.rs

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
13/// Parses `item1 item2 item3...`
14impl<'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    /// Parses `( body )`
30    #[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    /// Parses `[ body ]`
38    #[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    /// Parses `{ body }`
46    #[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    /// Parses `< body >`
54    #[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    /// Parses `(item1, item2, item3,...)?`
62    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    /// Parses `item1, item2, item3, ...`
68    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    /// Represents an identifier
77    ///
78    /// Follows `/_?[A-Za-z][0-9A-Z_a-z-]*/`
79    #[derive(Copy)]
80    struct Identifier<'a>(
81        // See https://heycam.github.io/webidl/#idl-names for why the leading
82        // underscore is trimmed
83        &'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    /// Parses rhs of an assignment expression. Ex: `= 45`
95    #[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}