1use std::collections::hash_map;
2
3use pest::iterators::{Pair, Pairs};
4use pest::Parser;
5
6use crate::grammar::{Grammar, Rule};
7use crate::tokens::{BuiltinConstructor, Constructor, Field, OutputType, Scheme, Type};
8
9impl<'a> Scheme<'a> {
10 pub fn parse(s: &'a str) -> Result<Self, ParserError> {
11 let mut scheme = Scheme::default();
12
13 let pairs = Grammar::parse(Rule::tl_scheme, s)
14 .map_err(|e| ParserError::InvalidInput(e.to_string()))?;
15 for pair in pairs {
16 parse_declarations(&mut scheme, pair)?;
17 }
18
19 Ok(scheme)
20 }
21}
22
23impl<'a> Constructor<'a> {
24 pub fn parse(s: &'a str) -> Result<Self, ParserError> {
25 let pairs = Grammar::parse(Rule::tl_constructor, s)
26 .map_err(|e| ParserError::InvalidInput(e.to_string()))?;
27 let pair = pairs.into_iter().next().ok_or(ParserError::ExpectedEof)?;
28
29 parse_declaration(pair)
30 }
31}
32
33fn parse_declarations<'a>(
34 scheme: &mut Scheme<'a>,
35 pair: Pair<'a, Rule>,
36) -> Result<(), ParserError> {
37 let (declarations, is_type) = match pair.as_rule() {
38 Rule::type_declarations => (&mut scheme.types, true),
39 Rule::fn_declarations => (&mut scheme.functions, false),
40 _ => return Ok(()),
41 };
42
43 for pair in pair.into_inner() {
44 if pair.as_rule() == Rule::builtin_combinator_decl {
45 let decl = parse_builtin_declaration(pair)?;
46 scheme
47 .boxed_types
48 .entry(decl.output)
49 .or_default()
50 .push(decl.variant);
51
52 if scheme.builtins.insert(decl.variant, decl).is_some() {
53 return Err(ParserError::DuplicateVariant(decl.variant.to_owned()));
54 }
55 } else {
56 let decl = parse_declaration(pair)?;
57 if is_type {
58 scheme
59 .boxed_types
60 .entry(decl.output.ty)
61 .or_default()
62 .push(decl.variant);
63 }
64
65 match declarations.entry(decl.variant) {
66 hash_map::Entry::Vacant(entry) => {
67 entry.insert(decl);
68 }
69 hash_map::Entry::Occupied(_) => {
70 return Err(ParserError::DuplicateVariant(decl.variant.to_owned()));
71 }
72 }
73 }
74 }
75
76 Ok(())
77}
78
79fn parse_builtin_declaration(pair: Pair<'_, Rule>) -> Result<BuiltinConstructor<'_>, ParserError> {
80 let mut pairs = pair.into_inner();
81
82 let (variant, tl_id) = pairs
83 .next()
84 .ok_or(ParserError::ExpectedEof)
85 .and_then(parse_variant)?;
86
87 let output = pairs.next().ok_or(ParserError::ExpectedEof)?.as_str();
88
89 Ok(BuiltinConstructor {
90 variant,
91 tl_id,
92 output,
93 })
94}
95
96fn parse_declaration(pair: Pair<'_, Rule>) -> Result<Constructor<'_>, ParserError> {
97 let mut pairs = pair.into_inner();
98
99 let (variant, tl_id) = pairs
100 .next()
101 .ok_or(ParserError::ExpectedEof)
102 .and_then(parse_variant)?;
103
104 let mut type_parameters = Vec::new();
105 read_same_rules(&mut pairs, Rule::type_arg, |pair| {
106 type_parameters.push(parse_type_arg(pair)?);
107 Ok(())
108 })?;
109
110 let mut fields = Vec::new();
111 read_same_rules(&mut pairs, Rule::field, |pair| {
112 fields.push(parse_field(pair)?);
113 Ok(())
114 })?;
115
116 let output_type = pairs.next().ok_or(ParserError::ExpectedEof)?;
117 let output = parse_output_type(output_type)?;
118
119 Ok(Constructor {
120 variant,
121 tl_id,
122 type_parameters,
123 fields,
124 output,
125 })
126}
127
128fn parse_variant(pair: Pair<'_, Rule>) -> Result<(&'_ str, Option<u32>), ParserError> {
129 let mut pairs = pair.into_inner();
130
131 let name = pairs.next().ok_or(ParserError::ExpectedEof)?;
132 let tl_id = pairs
133 .next()
134 .map(|pair| u32::from_str_radix(pair.as_str(), 16))
135 .transpose()
136 .map_err(ParserError::InvalidTlId)?;
137
138 Ok((name.as_str(), tl_id))
139}
140
141fn parse_type_arg(pair: Pair<'_, Rule>) -> Result<Field<'_>, ParserError> {
142 let mut pairs = pair.into_inner();
143
144 let name = pairs.next().ok_or(ParserError::ExpectedEof)?;
145
146 Ok(Field {
147 name: Some(name.as_str()),
148 ty: pairs
149 .next()
150 .ok_or(ParserError::ExpectedEof)
151 .and_then(parse_type_expr)?,
152 })
153}
154
155fn parse_field(pair: Pair<'_, Rule>) -> Result<Field<'_>, ParserError> {
156 let pair = pair.into_inner().next().ok_or(ParserError::ExpectedEof)?;
157
158 match pair.as_rule() {
159 Rule::field_simple => {
160 let mut pairs = pair.into_inner();
161 let name = pairs.next().ok_or(ParserError::ExpectedEof)?.as_str();
162
163 let mut pair = pairs.next().ok_or(ParserError::ExpectedEof)?;
164 let ty = if pair.as_rule() == Rule::conditional_def {
165 let mut conditional = pair.into_inner();
166 let flags_field = conditional.next().ok_or(ParserError::ExpectedEof)?.as_str();
167
168 let bit = conditional
169 .next()
170 .map(|pair| pair.as_str().parse::<u8>())
171 .transpose()
172 .map_err(ParserError::InvalidFlagsBit)?
173 .ok_or(ParserError::ExpectedEof)?;
174
175 pair = pairs.next().ok_or(ParserError::ExpectedEof)?;
176
177 Type::Flagged {
178 flags_field,
179 bit,
180 ty: Box::new(parse_type_expr(pair)?),
181 }
182 } else {
183 parse_type_expr(pair)?
184 };
185
186 Ok(Field {
187 name: Some(name),
188 ty,
189 })
190 }
191 Rule::field_repeated => {
192 let mut pairs = pair.into_inner();
193 let mut pair = pairs.peek().ok_or(ParserError::ExpectedEof)?;
194
195 let mut name = None;
196 if pair.as_rule() == Rule::field_ident_opt {
197 name = Some(pair.as_str());
198 pairs.next();
199
200 pair = pairs.peek().ok_or(ParserError::ExpectedEof)?;
201 }
202
203 let mut multiplicity = None;
204 if pair.as_rule() == Rule::nat_const {
205 multiplicity = pair
206 .as_str()
207 .parse::<u32>()
208 .map(Some)
209 .map_err(ParserError::InvalidRepetition)?;
210 pairs.next();
211 }
212
213 let ty = pairs.map(parse_field).collect::<Result<Vec<_>, _>>()?;
214
215 Ok(Field {
216 name,
217 ty: Type::Repeated { multiplicity, ty },
218 })
219 }
220 Rule::type_expr => Ok(Field {
221 name: None,
222 ty: parse_type_expr(pair)?,
223 }),
224 rule => Err(ParserError::UnexpectedRule(format!("{rule:?}"))),
225 }
226}
227
228fn parse_output_type(pair: Pair<'_, Rule>) -> Result<OutputType<'_>, ParserError> {
229 let mut pairs = pair.into_inner();
230
231 let ty = pairs.next().ok_or(ParserError::ExpectedEof)?.as_str();
232
233 let ty_param = pairs.next().map(parse_type_expr).transpose()?.map(Box::new);
234
235 Ok(OutputType { ty, ty_param })
236}
237
238fn parse_type_expr(pair: Pair<'_, Rule>) -> Result<Type<'_>, ParserError> {
239 if pair.as_rule() != Rule::type_expr {
240 return Err(ParserError::ExpectedEof);
241 }
242
243 let mut pairs = pair.into_inner();
244
245 let param = pairs.next().ok_or(ParserError::ExpectedEof)?;
246 let ty = match param.as_rule() {
247 Rule::type_ident => param.as_str(),
248 Rule::nat_type => return Ok(Type::Int),
249 rule => return Err(ParserError::UnexpectedRule(format!("{rule:?}"))),
250 };
251
252 Ok(if let Some(param) = pairs.next() {
253 Type::Generic {
254 ty,
255 ty_param: Box::new(parse_type_expr(param)?),
256 }
257 } else {
258 Type::Named { ty }
259 })
260}
261
262fn read_same_rules<'a, F>(
263 pairs: &mut Pairs<'a, Rule>,
264 rule: Rule,
265 mut f: F,
266) -> Result<(), ParserError>
267where
268 F: FnMut(Pair<'a, Rule>) -> Result<(), ParserError>,
269{
270 while pairs
271 .peek()
272 .map(|pair| pair.as_rule() == rule)
273 .unwrap_or_default()
274 {
275 if let Some(pair) = pairs.next() {
276 f(pair)?;
277 }
278 }
279 Ok(())
280}
281
282#[derive(thiserror::Error, Debug)]
283pub enum ParserError {
284 #[error("invalid input:\n{0}")]
285 InvalidInput(String),
286 #[error("duplicate variant: {0}")]
287 DuplicateVariant(String),
288 #[error("unexpected rule: {0:?}")]
289 UnexpectedRule(String),
290 #[error("unexpected end of input")]
291 ExpectedEof,
292 #[error("invalid TL id")]
293 InvalidTlId(#[source] std::num::ParseIntError),
294 #[error("invalid flags bit")]
295 InvalidFlagsBit(#[source] std::num::ParseIntError),
296 #[error("invalid repetition")]
297 InvalidRepetition(#[source] std::num::ParseIntError),
298}