roogle_engine/query/
parse.rs

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}