rem_utils/
parser.rs

1use nom::{
2    branch::alt,
3    bytes::complete::tag,
4    character::complete::{multispace0, u64},
5    sequence::delimited,
6    IResult,
7};
8
9use crate::typ::RustType;
10use crate::{labelling::Label, typ::CIntegralSize};
11
12/// A combinator that takes a parser `inner` and produces a parser that also consumes both leading and
13/// trailing whitespace, returning the output of `inner`.
14pub fn ws<'a, F: 'a, O, E: nom::error::ParseError<&'a str>>(
15    inner: F,
16) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
17where
18    F: Fn(&'a str) -> IResult<&'a str, O, E>,
19{
20    delimited(multispace0, inner, multispace0)
21}
22
23pub fn rust_type(s: &str) -> IResult<&str, RustType> {
24    fn int(s: &str) -> IResult<&str, RustType> {
25        tag("c_int")(s).map(|(rest, _)| {
26            (
27                rest,
28                RustType::CInt {
29                    unsigned: false,
30                    size: CIntegralSize::Int,
31                },
32            )
33        })
34    }
35    fn ulong(s: &str) -> IResult<&str, RustType> {
36        tag("c_ulong")(s).map(|(rest, _)| {
37            (
38                rest,
39                RustType::CInt {
40                    unsigned: true,
41                    size: CIntegralSize::Long,
42                },
43            )
44        })
45    }
46    fn void(s: &str) -> IResult<&str, RustType> {
47        tag("c_void")(s).map(|(rest, _)| (rest, RustType::CVoid))
48    }
49    fn i32_ty(s: &str) -> IResult<&str, RustType> {
50        tag("i32")(s).map(|(rest, _)| (rest, RustType::I32))
51    }
52    fn isize(s: &str) -> IResult<&str, RustType> {
53        tag("isize")(s).map(|(rest, _)| (rest, RustType::Isize))
54    }
55    fn usize(s: &str) -> IResult<&str, RustType> {
56        tag("usize")(s).map(|(rest, _)| (rest, RustType::Usize))
57    }
58    fn size_t(s: &str) -> IResult<&str, RustType> {
59        tag("size_t")(s).map(|(rest, _)| (rest, RustType::Usize))
60    }
61    fn uint(s: &str) -> IResult<&str, RustType> {
62        tag("c_uint")(s).map(|(rest, _)| {
63            (
64                rest,
65                RustType::CInt {
66                    unsigned: true,
67                    size: CIntegralSize::Int,
68                },
69            )
70        })
71    }
72    fn uchar(s: &str) -> IResult<&str, RustType> {
73        tag("c_uchar")(s).map(|(rest, _)| {
74            (
75                rest,
76                RustType::CInt {
77                    unsigned: true,
78                    size: CIntegralSize::Char,
79                },
80            )
81        })
82    }
83    fn int_ptr(s: &str) -> IResult<&str, RustType> {
84        tag("mut_ptr_c_int")(s).map(|(rest, _)| {
85            (
86                rest,
87                RustType::Pointer(Box::new(RustType::CInt {
88                    unsigned: false,
89                    size: CIntegralSize::Int,
90                })),
91            )
92        })
93    }
94    fn uint_ptr(s: &str) -> IResult<&str, RustType> {
95        tag("mut_ptr_c_uint")(s).map(|(rest, _)| {
96            (
97                rest,
98                RustType::Pointer(Box::new(RustType::CInt {
99                    unsigned: true,
100                    size: CIntegralSize::Int,
101                })),
102            )
103        })
104    }
105    fn uchar_ptr(s: &str) -> IResult<&str, RustType> {
106        tag("mut_ptr_c_uchar")(s).map(|(rest, _)| {
107            (
108                rest,
109                RustType::Pointer(Box::new(RustType::CInt {
110                    unsigned: true,
111                    size: CIntegralSize::Char,
112                })),
113            )
114        })
115    }
116    fn void_ptr(s: &str) -> IResult<&str, RustType> {
117        tag("mut_ptr_c_void")(s)
118            .map(|(rest, _)| (rest, RustType::Pointer(Box::new(RustType::CVoid))))
119    }
120    // not sure how to make wildcard/recursively handle nested pointers so hardcoding it in for now...
121    fn nested_int_ptr(s: &str) -> IResult<&str, RustType> {
122        tag("mut_ptr_mut_ptr_c_int")(s).map(|(rest, _)| {
123            (
124                rest,
125                RustType::Pointer(Box::new(RustType::Pointer(Box::new(RustType::CInt {
126                    unsigned: true,
127                    size: CIntegralSize::Int,
128                })))),
129            )
130        })
131    }
132    fn nested_uint_ptr(s: &str) -> IResult<&str, RustType> {
133        tag("mut_ptr_mut_ptr_c_uint")(s).map(|(rest, _)| {
134            (
135                rest,
136                RustType::Pointer(Box::new(RustType::Pointer(Box::new(RustType::CInt {
137                    unsigned: true,
138                    size: CIntegralSize::Int,
139                })))),
140            )
141        })
142    }
143
144    alt((
145        nested_int_ptr,
146        nested_uint_ptr,
147        uint_ptr,
148        uchar_ptr,
149        void_ptr,
150        int_ptr,
151        uint,
152        size_t,
153        uchar,
154        int,
155        ulong,
156        void,
157        i32_ty,
158        isize,
159        usize,
160    ))(s)
161}
162
163pub fn label(s: &str) -> IResult<&str, Label> {
164    let (s, _) = tag("A")(s)?;
165    let (s, digits) = u64(s)?;
166    Ok((s, Label::of_raw(digits as usize)))
167}