1use super::super::tokens;
39use super::super::ast::{
40 Name,
41 Variable
42};
43
44named!(
45 pub variable<Variable>,
46 map_res!(
47 preceded!(
48 tag!(tokens::VARIABLE),
49 name
50 ),
51 variable_mapper
52 )
53);
54
55#[inline(always)]
56fn variable_mapper(string: &[u8]) -> Result<Variable, ()> {
57 Ok(Variable(string))
58}
59
60named!(
61 pub qualified_name<Name>,
62 chain!(
63 head: alt!(
64 tag!(tokens::NAMESPACE_SEPARATOR)
65 | terminated!(
66 keyword!(tokens::NAMESPACE),
67 first!(tag!(tokens::NAMESPACE_SEPARATOR))
68 )
69 )? ~
70 mut accumulator: map_res!(
71 exclude!(first!(name), tokens::keywords),
72 wrap_into_vector_mapper
73 ) ~
74 many0!(
75 tap!(
76 tail: preceded!(
77 first!(tag!(tokens::NAMESPACE_SEPARATOR)),
78 exclude!(first!(name), tokens::keywords)
79 ) =>
80 accumulator.push(tail)
81 )
82 ),
83 || {
84 match head {
85 Some(handle) =>
86 if handle == tokens::NAMESPACE_SEPARATOR {
87 Name::FullyQualified(accumulator)
88 } else {
89 Name::RelativeQualified(accumulator)
90 },
91
92 None =>
93 if accumulator.len() > 1 {
94 Name::Qualified(accumulator)
95 } else {
96 Name::Unqualified(accumulator[0])
97 }
98 }
99 }
100 )
101);
102
103#[inline(always)]
104fn wrap_into_vector_mapper(string: &[u8]) -> Result<Vec<&[u8]>, ()> {
105 Ok(vec![string])
106}
107
108named!(
109 pub name,
110 re_bytes_find_static!(r"^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*")
111);
112
113
114#[cfg(test)]
115mod tests {
116 use super::{
117 name,
118 qualified_name,
119 variable
120 };
121 use super::super::super::ast::{
122 Name,
123 Variable
124 };
125 use super::super::super::internal::{
126 Error,
127 ErrorKind,
128 Result
129 };
130 use super::super::super::macros::ErrorKindCustom;
131
132 #[test]
133 fn case_variable() {
134 assert_eq!(variable(b"$foo"), Result::Done(&b""[..], Variable(&b"foo"[..])));
135 }
136
137 #[test]
138 fn case_variable_shortest() {
139 assert_eq!(variable(b"$x"), Result::Done(&b""[..], Variable(&b"x"[..])));
140 }
141
142 #[test]
143 fn case_invalid_variable_prefix() {
144 assert_eq!(variable(b"x"), Result::Error(Error::Position(ErrorKind::Tag, &b"x"[..])));
145 }
146
147 #[test]
148 fn case_invalid_variable_name() {
149 assert_eq!(variable(b"$0"), Result::Error(Error::Code(ErrorKind::RegexpFind)));
150 }
151
152 #[test]
153 fn case_unqualified_name() {
154 assert_eq!(qualified_name(b"Foo"), Result::Done(&b""[..], Name::Unqualified(&b"Foo"[..])));
155 }
156
157 #[test]
158 fn case_invalid_unqualified_name() {
159 assert_eq!(qualified_name(b"class"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"class"[..])));
160 assert_eq!(qualified_name(b"ClAsS"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"ClAsS"[..])));
161 }
162
163 #[test]
164 fn case_qualified_name() {
165 assert_eq!(qualified_name(b"Foo\\Bar\\Baz"), Result::Done(&b""[..], Name::Qualified(vec![&b"Foo"[..], &b"Bar"[..], &b"Baz"[..]])));
166 }
167
168 #[test]
169 fn case_qualified_name_with_skip_tokens() {
170 assert_eq!(qualified_name(b"Foo\n/* baz */ \\ Bar /* qux */\\"), Result::Done(&b" /* qux */\\"[..], Name::Qualified(vec![&b"Foo"[..], &b"Bar"[..]])));
171 }
172
173 #[test]
174 fn case_invalid_qualified_name() {
175 assert_eq!(qualified_name(b"Foo\\class\\Baz"), Result::Done(&b"\\class\\Baz"[..], Name::Unqualified(&b"Foo"[..])));
176 assert_eq!(qualified_name(b"Foo\\ClAsS\\Baz"), Result::Done(&b"\\ClAsS\\Baz"[..], Name::Unqualified(&b"Foo"[..])));
177 }
178
179 #[test]
180 fn case_relative_qualified_name() {
181 assert_eq!(qualified_name(b"namespace\\Foo\\Bar\\Baz"), Result::Done(&b""[..], Name::RelativeQualified(vec![&b"Foo"[..], &b"Bar"[..], &b"Baz"[..]])));
182 }
183
184 #[test]
185 fn case_relative_qualified_name_case_insensitive() {
186 assert_eq!(qualified_name(b"NaMeSpAcE\\Foo\\Bar\\Baz"), Result::Done(&b""[..], Name::RelativeQualified(vec![&b"Foo"[..], &b"Bar"[..], &b"Baz"[..]])));
187 }
188
189 #[test]
190 fn case_relative_qualified_name_with_skip_tokens() {
191 assert_eq!(qualified_name(b"namespace/* baz */ \\ Foo\n/* qux */ \\ Bar /* hello */\\"), Result::Done(&b" /* hello */\\"[..], Name::RelativeQualified(vec![&b"Foo"[..], &b"Bar"[..]])));
192 }
193
194 #[test]
195 fn case_invalid_relative_qualified_name_with_namespace() {
196 assert_eq!(qualified_name(b"namespace\\Foo\\namespace\\Baz"), Result::Done(&b"\\namespace\\Baz"[..], Name::RelativeQualified(vec![&b"Foo"[..]])));
197 assert_eq!(qualified_name(b"namespace\\Foo\\NaMeSpAcE\\Baz"), Result::Done(&b"\\NaMeSpAcE\\Baz"[..], Name::RelativeQualified(vec![&b"Foo"[..]])));
198 }
199
200 #[test]
201 fn case_invalid_relative_qualified_name_with_any_keyword() {
202 assert_eq!(qualified_name(b"namespace\\class"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"class"[..])));
203 assert_eq!(qualified_name(b"namespace\\ClAsS"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"ClAsS"[..])));
204 }
205
206 #[test]
207 fn case_fully_qualified_name() {
208 assert_eq!(qualified_name(b"\\Foo\\Bar\\Baz"), Result::Done(&b""[..], Name::FullyQualified(vec![&b"Foo"[..], &b"Bar"[..], &b"Baz"[..]])));
209 }
210
211 #[test]
212 fn case_fully_qualified_shortest_name() {
213 assert_eq!(qualified_name(b"\\Foo"), Result::Done(&b""[..], Name::FullyQualified(vec![&b"Foo"[..]])));
214 }
215
216 #[test]
217 fn case_invalid_fully_and_relative_qualified_name_with_namespace() {
218 assert_eq!(qualified_name(b"\\namespace\\Foo\\Bar"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"namespace\\Foo\\Bar"[..])));
219 }
220
221 #[test]
222 fn case_invalid_fully_and_relative_qualified_name_with_any_keyword() {
223 assert_eq!(qualified_name(b"\\class\\Foo\\Bar"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"class\\Foo\\Bar"[..])));
224 assert_eq!(qualified_name(b"\\ClAsS\\Foo\\Bar"), Result::Error(Error::Position(ErrorKind::Custom(ErrorKindCustom::Exclude as u32), &b"ClAsS\\Foo\\Bar"[..])));
225 }
226
227 #[test]
228 fn case_invalid_qualified_name_ending_with_a_separator() {
229 assert_eq!(qualified_name(b"Foo\\Bar\\"), Result::Done(&b"\\"[..], Name::Qualified(vec![&b"Foo"[..], &b"Bar"[..]])));
230 }
231
232 #[test]
233 fn case_name() {
234 assert_eq!(name(b"_fooBar42"), Result::Done(&b""[..], &b"_fooBar42"[..]));
235 }
236
237 #[test]
238 fn case_name_shortest() {
239 assert_eq!(name(b"x"), Result::Done(&b""[..], &b"x"[..]));
240 }
241
242 #[test]
243 fn case_name_only_head() {
244 assert_eq!(name(b"aB_\x80"), Result::Done(&b""[..], &b"aB_\x80"[..]));
245 }
246
247 #[test]
248 fn case_name_head_and_tail() {
249 assert_eq!(name(b"aB_\x80aB7\xff"), Result::Done(&b""[..], &b"aB_\x80aB7\xff"[..]));
250 }
251
252 #[test]
253 fn case_name_copyright() {
254 assert_eq!(name(b"\xa9"), Result::Done(&b""[..], &b"\xa9"[..]));
256 }
257
258 #[test]
259 fn case_name_non_breaking_space() {
260 assert_eq!(name(b"\xa0"), Result::Done(&b""[..], &b"\xa0"[..]));
262 }
263
264 #[test]
265 fn case_invalid_name() {
266 assert_eq!(name(b"0x"), Result::Error(Error::Code(ErrorKind::RegexpFind)));
267 }
268}