1use nom::{
2 branch::alt,
3 bytes::complete::{tag, take_while1},
4 character::complete::char,
5 character::complete::{alpha1, alphanumeric1, multispace0, multispace1},
6 combinator::{eof, fail, map, not, opt, recognize, value},
7 error::{ContextError, ParseError},
8 multi::{many0, separated_list0},
9 sequence::{delimited, pair, preceded},
10 IResult,
11};
12
13use crate::query::*;
14
15type Symbol = String;
16
17pub fn parse_query(i: &str) -> IResult<&str, Query> {
18 parse_function_query(i)
19}
20
21fn parse_symbol<'a, E>(i: &'a str) -> IResult<&'a str, Symbol, E>
22where
23 E: ParseError<&'a str> + ContextError<&'a str>,
24{
25 map(
26 recognize(pair(
27 alt((tag("_"), alpha1)),
28 many0(alt((tag("_"), alphanumeric1))),
29 )),
30 |symbol: &str| symbol.to_string(),
31 )(i)
32}
33
34fn parse_function_query<'a, E>(i: &'a str) -> IResult<&'a str, Query, E>
35where
36 E: ParseError<&'a str> + ContextError<&'a str>,
37{
38 let (i, f) = opt(tag("fn"))(i)?;
39 let (i, _) = match f {
40 Some(_) => multispace1(i)?,
41 None => multispace0(i)?,
42 };
43 let (i, name) = opt(parse_symbol)(i)?;
44 let (i, decl) = opt(parse_function)(i)?;
45
46 let query = Query {
47 name,
48 kind: decl.map(QueryKind::FunctionQuery),
49 };
50 Ok((i, query))
51}
52
53fn parse_function<'a, E>(i: &'a str) -> IResult<&'a str, Function, E>
54where
55 E: ParseError<&'a str> + ContextError<&'a str>,
56{
57 let (i, decl) = parse_function_decl(i)?;
58
59 let function = Function { decl };
60 Ok((i, function))
61}
62
63fn parse_function_decl<'a, E>(i: &'a str) -> IResult<&'a str, FnDecl, E>
64where
65 E: ParseError<&'a str> + ContextError<&'a str>,
66{
67 let (i, inputs) = delimited(
68 char('('),
69 alt((
70 value(None, tag("..")),
71 opt(parse_arguments),
72 value(Some(Vec::new()), not(eof)),
73 )),
74 char(')'),
75 )(i)?;
76 let (i, output) = opt(parse_output)(i)?;
77
78 let decl = FnDecl { inputs, output };
79 Ok((i, decl))
80}
81
82fn parse_arguments<'a, E>(i: &'a str) -> IResult<&'a str, Vec<Argument>, E>
83where
84 E: ParseError<&'a str> + ContextError<&'a str>,
85{
86 separated_list0(
87 char(','),
88 preceded(
89 multispace0,
90 alt((
91 parse_argument,
92 value(
93 Argument {
94 ty: None,
95 name: None,
96 },
97 char('_'),
98 ),
99 map(parse_type, |ty| Argument {
100 ty: Some(ty),
101 name: None,
102 }),
103 )),
104 ),
105 )(i)
106}
107
108fn parse_argument<'a, E>(i: &'a str) -> IResult<&'a str, Argument, E>
109where
110 E: ParseError<&'a str> + ContextError<&'a str>,
111{
112 let (i, name) = alt((value(None, char('_')), opt(parse_symbol)))(i)?;
113 let (i, _) = char(':')(i)?;
114 let (i, _) = multispace0(i)?;
115 let (i, ty) = alt((value(None, char('_')), opt(parse_type)))(i)?;
116
117 let arg = Argument { ty, name };
118 Ok((i, arg))
119}
120
121fn parse_output<'a, E>(i: &'a str) -> IResult<&'a str, FnRetTy, E>
122where
123 E: ParseError<&'a str> + ContextError<&'a str>,
124{
125 preceded(
126 multispace0,
127 alt((
128 value(
129 FnRetTy::DefaultReturn,
130 preceded(preceded(tag("->"), multispace0), tag("()")),
131 ),
132 map(preceded(tag("->"), parse_type), FnRetTy::Return),
133 value(FnRetTy::DefaultReturn, eof),
134 )),
135 )(i)
136}
137
138fn parse_type<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
139where
140 E: ParseError<&'a str> + ContextError<&'a str>,
141{
142 preceded(
143 multispace0,
144 alt((
145 map(parse_primitive_type, Type::Primitive),
146 parse_generic_type,
147 parse_unresolved_path,
148 parse_tuple,
149 parse_slice,
150 value(Type::Never, char('!')),
151 parse_raw_pointer,
152 parse_borrowed_ref,
153 )),
154 )(i)
155}
156
157fn parse_tuple<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
158where
159 E: ParseError<&'a str> + ContextError<&'a str>,
160{
161 map(
162 delimited(
163 char('('),
164 separated_list0(
165 char(','),
166 preceded(
167 multispace0,
168 alt((value(None, tag("_")), map(parse_type, Some))),
169 ),
170 ),
171 char(')'),
172 ),
173 Type::Tuple,
174 )(i)
175}
176
177fn parse_slice<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
178where
179 E: ParseError<&'a str> + ContextError<&'a str>,
180{
181 map(
182 delimited(
183 char('['),
184 alt((value(None, tag("_")), map(parse_type, Some))),
185 char(']'),
186 ),
187 |ty| Type::Slice(ty.map(Box::new)),
188 )(i)
189}
190
191fn parse_raw_pointer<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
192where
193 E: ParseError<&'a str> + ContextError<&'a str>,
194{
195 let (i, mutable) = alt((value(true, tag("*mut")), value(false, tag("*const"))))(i)?;
196 let (i, type_) = parse_type(i)?;
197
198 Ok((
199 i,
200 Type::RawPointer {
201 mutable,
202 type_: Box::new(type_),
203 },
204 ))
205}
206
207fn parse_borrowed_ref<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
208where
209 E: ParseError<&'a str> + ContextError<&'a str>,
210{
211 let (i, mutable) = alt((value(true, tag("&mut")), value(false, tag("&"))))(i)?;
212 let (i, type_) = parse_type(i)?;
213
214 Ok((
215 i,
216 Type::BorrowedRef {
217 mutable,
218 type_: Box::new(type_),
219 },
220 ))
221}
222
223fn parse_unresolved_path<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
224where
225 E: ParseError<&'a str> + ContextError<&'a str>,
226{
227 let (i, name) = parse_symbol(i)?;
228 let (i, args) = opt(parse_generic_args)(i)?;
229
230 Ok((
231 i,
232 Type::UnresolvedPath {
233 name,
234 args: args.map(Box::new),
235 },
236 ))
237}
238
239fn parse_generic_args<'a, E>(i: &'a str) -> IResult<&'a str, GenericArgs, E>
240where
241 E: ParseError<&'a str> + ContextError<&'a str>,
242{
243 map(
244 delimited(
245 char('<'),
246 separated_list0(
247 char(','),
248 preceded(
249 multispace0,
250 alt((
251 value(None, tag("_")),
252 opt(map(parse_type, GenericArg::Type)),
253 )),
254 ),
255 ),
256 char('>'),
257 ),
258 |args| GenericArgs::AngleBracketed { args },
259 )(i)
260}
261
262fn parse_generic_type<'a, E>(i: &'a str) -> IResult<&'a str, Type, E>
263where
264 E: ParseError<&'a str> + ContextError<&'a str>,
265{
266 let (i, gen) = map(take_while1(|c: char| c.is_ascii_uppercase()), |s: &str| {
267 Type::Generic(s.to_owned())
268 })(i)?;
269
270 if i.chars().next().map_or(false, |c| c.is_ascii_lowercase()) {
271 fail(i)
272 } else {
273 Ok((i, gen))
274 }
275}
276
277fn parse_primitive_type<'a, E>(i: &'a str) -> IResult<&'a str, PrimitiveType, E>
278where
279 E: ParseError<&'a str> + ContextError<&'a str>,
280{
281 use PrimitiveType::*;
282 alt((
283 value(Isize, tag("isize")),
284 value(I8, tag("i8")),
285 value(I16, tag("i16")),
286 value(I32, tag("i32")),
287 value(I64, tag("i64")),
288 value(I128, tag("i128")),
289 value(Usize, tag("usize")),
290 value(U8, tag("u8")),
291 value(U16, tag("u16")),
292 value(U32, tag("u32")),
293 value(U64, tag("u64")),
294 value(U128, tag("u128")),
295 value(F32, tag("f32")),
296 value(F64, tag("f64")),
297 value(Char, tag("char")),
298 value(Bool, tag("bool")),
299 value(Str, tag("str")),
300 ))(i)
301}