tl_scheme/
parser.rs

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}