duskphantom_frontend/parse/
typed.rs1use super::*;
18
19pub fn atom_type(input: &mut &str) -> PResult<Type> {
20 alt((
21 token("void").value(Type::Void),
22 token("int").value(Type::Int),
23 token("float").value(Type::Float),
24 token("string").value(Type::String),
25 token("char").value(Type::Char),
26 token("bool").value(Type::Bool),
27 (token("enum"), ident).map(|(_, ty)| Type::Enum(ty)),
28 (token("union"), ident).map(|(_, ty)| Type::Union(ty)),
29 (token("struct"), ident).map(|(_, ty)| Type::Struct(ty)),
30 ))
31 .parse_next(input)
32}
33
34pub fn lval(input: &mut &str) -> PResult<LVal> {
36 let atom = alt((
37 pad(ident).map(LVal::Var),
38 paren(lval),
39 empty.value(LVal::Nothing),
40 ));
41 let access_tail = alt((
42 bracket(opt(pad(expr))).map(|x| {
43 BoxF::new(move |acc| match x {
45 Some(ix) => LVal::Index(acc, ix.into()),
46 None => LVal::Pointer(acc),
47 })
48 }),
49 paren(vec_typed).map(|x| BoxF::new(|acc| LVal::Call(acc, x))),
50 ));
51 let access = lrec(atom, repeat(0.., access_tail));
52 let unary_init = token("*").map(|_op| BoxF::new(LVal::Pointer));
53 rrec(repeat(0.., unary_init), access).parse_next(input)
54}
55
56pub fn acc_lval(ty: Type, usage: LVal) -> TypedIdent {
59 match usage {
60 LVal::Nothing => TypedIdent::new(ty, None),
61 LVal::Var(id) => TypedIdent::new(ty, Some(id)),
62 LVal::Index(inner, ix) => acc_lval(Type::Array(Box::new(ty), ix), *inner),
63 LVal::Call(inner, arg) => acc_lval(Type::Function(Box::new(ty), arg), *inner),
64 LVal::Pointer(inner) => acc_lval(Type::Pointer(Box::new(ty)), *inner),
65 }
66}
67
68pub fn typed_ident(input: &mut &str) -> PResult<TypedIdent> {
70 let ty = atom_type.parse_next(input)?;
71 let us = lval.parse_next(input)?;
72 Ok(acc_lval(ty, us))
73}
74
75pub fn single_type(input: &mut &str) -> PResult<Type> {
77 typed_ident.map(|ti| ti.ty).parse_next(input)
78}
79
80pub fn box_type(input: &mut &str) -> PResult<Box<Type>> {
82 single_type.map(Box::new).parse_next(input)
83}
84
85pub fn vec_typed(input: &mut &str) -> PResult<Vec<TypedIdent>> {
87 separated(0.., typed_ident, token(",")).parse_next(input)
88}
89
90#[cfg(test)]
92pub mod tests_typed {
93 use super::*;
94
95 #[test]
96 fn test_atom() {
97 let code = "int";
98 match atom_type.parse(code) {
99 Ok(result) => assert_eq!(result, Type::Int),
100 Err(err) => panic!("failed to parse {}: {}", code, err),
101 }
102 }
103
104 #[test]
105 fn test_space() {
106 let code = "int ( * ) ( int u )";
108 match single_type.parse(code) {
109 Ok(result) => assert_eq!(
110 result,
111 Type::Pointer(Box::new(Type::Function(
112 Box::new(Type::Int),
113 vec![TypedIdent::new(Type::Int, Some("u".to_string()))],
114 )))
115 ),
116 Err(err) => panic!("failed to parse {}: {}", code, err),
117 }
118 }
119
120 #[test]
121 fn test_function_pointer() {
122 let code = "int (*)(int)";
123 match single_type.parse(code) {
124 Ok(result) => assert_eq!(
125 result,
126 Type::Pointer(Box::new(Type::Function(
127 Box::new(Type::Int),
128 vec![TypedIdent::new(Type::Int, None)],
129 )))
130 ),
131 Err(err) => panic!("failed to parse {}: {}", code, err),
132 }
133 }
134
135 #[test]
136 fn test_name_pointer_function() {
137 let code = "int *u(int)";
139 match single_type.parse(code) {
140 Ok(result) => assert_eq!(
141 result,
142 Type::Function(
143 Box::new(Type::Pointer(Box::new(Type::Int))),
144 vec![TypedIdent::new(Type::Int, None)],
145 )
146 ),
147 Err(err) => panic!("failed to parse {}: {}", code, err),
148 }
149 }
150
151 #[test]
152 fn test_argname_pointer_function() {
153 let code = "int *(int u)";
154 match single_type.parse(code) {
155 Ok(result) => assert_eq!(
156 result,
157 Type::Function(
158 Box::new(Type::Pointer(Box::new(Type::Int))),
159 vec![TypedIdent::new(Type::Int, Some("u".to_string()))],
160 )
161 ),
162 Err(err) => panic!("failed to parse {}: {}", code, err),
163 }
164 }
165
166 #[test]
167 fn test_usage() {
168 let code = "*(int)";
169 match lval.parse(code) {
170 Ok(result) => assert_eq!(
171 result,
172 LVal::Pointer(Box::new(LVal::Call(
173 Box::new(LVal::Nothing),
174 vec![TypedIdent::new(Type::Int, None)],
175 )))
176 ),
177 Err(err) => panic!("failed to parse {}: {}", code, err),
178 }
179 }
180
181 #[test]
182 fn test_pointer_function() {
183 let code = "int *(int)";
184 match single_type.parse(code) {
185 Ok(result) => assert_eq!(
186 result,
187 Type::Function(
188 Box::new(Type::Pointer(Box::new(Type::Int))),
189 vec![TypedIdent::new(Type::Int, None)],
190 )
191 ),
192 Err(err) => panic!("failed to parse {}: {}", code, err),
193 }
194 }
195
196 #[test]
197 fn test_array_pointer() {
198 let code = "int x[][4]";
199 match single_type.parse(code) {
200 Ok(result) => assert_eq!(
201 result,
202 Type::Pointer(Box::new(Type::Array(
203 Box::new(Type::Int),
204 Box::new(Expr::Int(4))
205 )))
206 ),
207 Err(err) => panic!("failed to parse {}: {}", code, err),
208 }
209 }
210
211 #[test]
212 fn test_complicated() {
213 let code = "int (*(*app)(int (*)(int)))(int)";
216 match typed_ident.parse(code) {
217 Ok(result) => assert_eq!(
218 result,
219 TypedIdent::new(
220 Type::Pointer(Box::new(Type::Function(
221 Box::new(Type::Pointer(Box::new(Type::Function(
222 Box::new(Type::Int),
223 vec![TypedIdent::new(Type::Int, None)],
224 )))),
225 vec![TypedIdent::new(
226 Type::Pointer(Box::new(Type::Function(
227 Box::new(Type::Int),
228 vec![TypedIdent::new(Type::Int, None)],
229 ))),
230 None
231 )],
232 ))),
233 Some("app".to_string()),
234 ),
235 ),
236 Err(err) => panic!("failed to parse {}: {}", code, err),
237 }
238 }
239}