Skip to main content

tyml_generator/style/
language.rs

1use std::{borrow::Cow, iter::once, ops::Range};
2
3use allocator_api2::vec::Vec;
4use auto_enums::auto_enum;
5use serde::{Deserialize, Serialize};
6use tyml_formatter::FormatterTokenKind;
7use tyml_source::AsUtf8ByteRange;
8use tyml_validate::validate::{SetValue, ValueTree, ValueTypeChecker};
9
10use crate::{
11    lexer::{GeneratorTokenKind, GeneratorTokenizer},
12    style::value::ValueAST,
13};
14
15use super::{
16    AST, NamedParserPart, Parser, ParserGenerator, ParserPart,
17    comment::Comment,
18    error::{GeneratedParseError, recover_until_or_lf},
19    key_value::{KeyValue, KeyValueAST, KeyValueParser},
20    section::{Section, SectionAST, SectionParser},
21};
22
23#[derive(Debug, Serialize, Deserialize)]
24pub enum LanguageStyle {
25    Section(SectionStyle),
26    Value(KeyValue),
27    Empty,
28}
29
30#[derive(Debug, Serialize, Deserialize)]
31pub struct SectionStyle {
32    pub section: Section,
33    pub key_value: KeyValue,
34    pub comments: std::vec::Vec<Comment>,
35    pub allow_non_section_key_value: bool,
36}
37
38pub enum LanguageParser {
39    Section {
40        section: SectionParser,
41        key_value: KeyValueParser,
42        comments: Vec<GeneratorTokenKind>,
43        allow_non_section_key_value: bool,
44    },
45    Value {
46        key_value: KeyValueParser,
47    },
48    Empty {
49        empty_lexer: GeneratorTokenKind,
50    },
51}
52
53#[derive(Debug)]
54pub enum LanguageAST<'input> {
55    Section {
56        non_section_key_values: Vec<KeyValueAST<'input>>,
57        sections: Vec<(SectionAST<'input>, Vec<KeyValueAST<'input>>, Range<usize>)>,
58        span: Range<usize>,
59    },
60    Value {
61        value: Option<ValueAST<'input>>,
62    },
63    Empty {
64        span: Range<usize>,
65    },
66}
67
68impl<'input> ParserGenerator<'input, LanguageAST<'input>, LanguageParser> for LanguageStyle {
69    fn generate(&self, registry: &mut crate::lexer::TokenizerRegistry) -> LanguageParser {
70        match self {
71            LanguageStyle::Section(section) => LanguageParser::Section {
72                section: section.section.generate(registry),
73                key_value: section.key_value.generate(registry),
74                comments: section
75                    .comments
76                    .iter()
77                    .map(|comment| registry.register(GeneratorTokenizer::Regex(comment.regex())))
78                    .collect(),
79                allow_non_section_key_value: section.allow_non_section_key_value,
80            },
81            LanguageStyle::Value(key_value) => LanguageParser::Value {
82                key_value: key_value.generate(registry),
83            },
84            LanguageStyle::Empty => LanguageParser::Empty {
85                empty_lexer: registry.register(GeneratorTokenizer::regex(".*")),
86            },
87        }
88    }
89}
90
91impl<'input> Parser<'input, LanguageAST<'input>> for LanguageParser {
92    fn parse(
93        &self,
94        lexer: &mut crate::lexer::GeneratorLexer<'input, '_>,
95        errors: &mut Vec<GeneratedParseError>,
96    ) -> Option<LanguageAST<'input>>
97    where
98        Self: Sized,
99    {
100        let anchor = lexer.cast_anchor();
101
102        match self {
103            LanguageParser::Section {
104                section,
105                key_value,
106                comments,
107                allow_non_section_key_value,
108            } => {
109                let mut non_section_key_values = Vec::new();
110                let mut sections = Vec::new();
111
112                lexer.comments.extend(comments.iter().cloned());
113
114                if *allow_non_section_key_value {
115                    loop {
116                        lexer.skip_lf();
117
118                        let Some(key_value) = key_value.parse(lexer, errors) else {
119                            break;
120                        };
121
122                        non_section_key_values.push(key_value);
123                    }
124                }
125
126                loop {
127                    lexer.skip_lf();
128
129                    if lexer.is_reached_eof() {
130                        break;
131                    }
132
133                    let anchor = lexer.cast_anchor();
134
135                    let section_ast = match section.parse(lexer, errors) {
136                        Some(section) => section,
137                        None => {
138                            let error =
139                                recover_until_or_lf(lexer, section.first_token_kinds(), section);
140                            errors.push(error);
141
142                            continue;
143                        }
144                    };
145
146                    if !lexer.is_current_lf() {
147                        let error = recover_until_or_lf(
148                            lexer,
149                            [GeneratorTokenKind::LineFeed].into_iter(),
150                            &NamedParserPart::LINE_FEED,
151                        );
152                        errors.push(error);
153                    }
154                    lexer.skip_lf();
155
156                    let mut key_values = Vec::new();
157
158                    loop {
159                        if lexer.is_reached_eof() {
160                            break;
161                        }
162
163                        lexer.skip_lf();
164
165                        let key_value = match key_value.parse(lexer, errors) {
166                            Some(key_value) => key_value,
167                            None => {
168                                // next token must be start of section
169                                if section
170                                    .first_token_kinds()
171                                    .any(|kind| lexer.current_contains(kind))
172                                {
173                                    break;
174                                }
175
176                                let error = recover_until_or_lf(
177                                    lexer,
178                                    key_value
179                                        .first_token_kinds()
180                                        .chain(section.first_token_kinds()),
181                                    key_value,
182                                );
183                                errors.push(error);
184
185                                if section
186                                    .first_token_kinds()
187                                    .any(|kind| lexer.current_contains(kind))
188                                {
189                                    break;
190                                }
191
192                                continue;
193                            }
194                        };
195
196                        if !lexer.is_current_lf() && !lexer.is_reached_eof() {
197                            let error = recover_until_or_lf(
198                                lexer,
199                                [GeneratorTokenKind::LineFeed].into_iter(),
200                                &NamedParserPart::LINE_FEED,
201                            );
202                            errors.push(error);
203                        }
204                        lexer.skip_lf();
205
206                        key_values.push(key_value);
207                    }
208
209                    sections.push((section_ast, key_values, anchor.elapsed(lexer)));
210                }
211
212                Some(LanguageAST::Section {
213                    non_section_key_values,
214                    sections,
215                    span: anchor.elapsed(lexer),
216                })
217            }
218            LanguageParser::Value { key_value } => {
219                lexer.skip_lf();
220
221                let value = key_value.value.parse(key_value, lexer, errors);
222
223                lexer.skip_lf();
224
225                Some(LanguageAST::Value { value })
226            }
227            LanguageParser::Empty { empty_lexer: _ } => {
228                lexer.next();
229
230                Some(LanguageAST::Empty {
231                    span: anchor.elapsed(lexer),
232                })
233            }
234        }
235    }
236
237    #[auto_enum(Iterator)]
238    fn first_token_kinds(&self) -> impl Iterator<Item = crate::lexer::GeneratorTokenKind> {
239        match self {
240            LanguageParser::Section {
241                section,
242                key_value: _,
243                comments: _,
244                allow_non_section_key_value: _,
245            } => section.first_token_kinds(),
246            LanguageParser::Value { key_value } => key_value.value.first_token_kinds(),
247            LanguageParser::Empty { empty_lexer } => once(*empty_lexer),
248        }
249    }
250
251    fn map_formatter_token_kind(
252        &self,
253        map: &mut std::collections::HashMap<GeneratorTokenKind, tyml_formatter::FormatterTokenKind>,
254    ) {
255        match self {
256            LanguageParser::Section {
257                section,
258                key_value,
259                comments,
260                allow_non_section_key_value: _,
261            } => {
262                section.map_formatter_token_kind(map);
263                key_value.map_formatter_token_kind(map);
264
265                for comment in comments.iter() {
266                    map.insert(*comment, FormatterTokenKind::Comment);
267                }
268            }
269            LanguageParser::Value { key_value } => {
270                key_value.map_formatter_token_kind(map);
271            }
272            LanguageParser::Empty { empty_lexer: _ } => {}
273        }
274    }
275}
276
277impl ParserPart for LanguageParser {
278    fn parse_error_code(&self) -> usize {
279        0001
280    }
281
282    fn expected_format(&self) -> Option<std::borrow::Cow<'static, str>> {
283        None
284    }
285}
286
287impl<'input> AST<'input> for LanguageAST<'input> {
288    fn span(&self) -> Range<usize> {
289        match self {
290            LanguageAST::Section {
291                non_section_key_values: _,
292                sections: _,
293                span,
294            } => span.clone(),
295            LanguageAST::Value { value } => {
296                value.as_ref().map(|value| value.span()).unwrap_or(0..0)
297            }
298            LanguageAST::Empty { span } => span.clone(),
299        }
300    }
301
302    fn take_value(
303        &self,
304        section_name_stack: &mut allocator_api2::vec::Vec<
305            (Cow<'input, str>, Range<usize>, Range<usize>, bool),
306            &bumpalo::Bump,
307        >,
308        validator: &mut ValueTypeChecker<'_, '_, '_, 'input, 'input>,
309    ) {
310        if let ValueTree::Section {
311            elements: _,
312            name_span,
313            define_span,
314        } = &mut validator.value_tree
315        {
316            // set root span
317            *name_span = self.span().as_utf8_byte_range();
318            *define_span = self.span().as_utf8_byte_range();
319        }
320
321        match self {
322            LanguageAST::Section {
323                non_section_key_values,
324                sections,
325                span: _,
326            } => {
327                for key_value in non_section_key_values.iter() {
328                    key_value.take_value(section_name_stack, validator);
329                }
330
331                for (section, key_values, span) in sections.iter() {
332                    // stack this section
333                    let stacked = if section.sections.is_empty() {
334                        section_name_stack.push((
335                            "unknown".into(),
336                            section.span.clone(),
337                            section.span.clone(),
338                            false,
339                        ));
340
341                        1
342                    } else {
343                        section_name_stack.extend(
344                            section
345                                .sections
346                                .iter()
347                                .map(|literal| literal.to_section_name(span.clone()))
348                                .flatten()
349                                .enumerate()
350                                .map(|(index, (literal, name_span, define_span, _))| {
351                                    (
352                                        literal,
353                                        name_span,
354                                        define_span,
355                                        section.is_array
356                                            && index == (section.sections.len() - 1)
357                                            && section.is_complete,
358                                    )
359                                }),
360                        );
361
362                        section.sections.len()
363                    };
364
365                    validator.set_value(
366                        section_name_stack.iter().map(
367                            |(name, name_span, define_span, is_array)| {
368                                (
369                                    name.clone(),
370                                    name_span.as_utf8_byte_range(),
371                                    define_span.as_utf8_byte_range(),
372                                    *is_array,
373                                )
374                            },
375                        ),
376                        SetValue::CreateSection,
377                    );
378
379                    for key_value in key_values.iter() {
380                        key_value.take_value(section_name_stack, validator);
381                    }
382
383                    for _ in 0..stacked {
384                        section_name_stack.pop().unwrap();
385                    }
386                }
387            }
388            LanguageAST::Value { value } => {
389                if let Some(value) = value {
390                    value.take_value(section_name_stack, validator);
391                }
392            }
393            LanguageAST::Empty { span: _ } => {}
394        }
395    }
396
397    fn take_token(
398        &self,
399        tokens: &mut std::collections::BTreeMap<usize, (super::ASTTokenKind, Range<usize>)>,
400    ) {
401        match self {
402            LanguageAST::Section {
403                non_section_key_values,
404                sections,
405                span: _,
406            } => {
407                for key_value in non_section_key_values.iter() {
408                    key_value.take_token(tokens);
409                }
410
411                for (section, key_values, _) in sections.iter() {
412                    section.take_token(tokens);
413
414                    for key_value in key_values.iter() {
415                        key_value.take_token(tokens);
416                    }
417                }
418            }
419            LanguageAST::Value { value } => {
420                if let Some(value) = value {
421                    value.take_token(tokens);
422                }
423            }
424            LanguageAST::Empty { span: _ } => {}
425        }
426    }
427
428    fn take_formatter_token_space(&self, tokens: &mut Vec<super::FormatterTokenInfo>) {
429        match self {
430            LanguageAST::Section {
431                non_section_key_values,
432                sections,
433                span: _,
434            } => {
435                for key_value in non_section_key_values.iter() {
436                    key_value.take_formatter_token_space(tokens);
437                }
438
439                for (section, key_values, _) in sections.iter() {
440                    section.take_formatter_token_space(tokens);
441
442                    for key_value in key_values.iter() {
443                        key_value.take_formatter_token_space(tokens);
444                    }
445                }
446            }
447            LanguageAST::Value { value } => {
448                if let Some(value) = value {
449                    value.take_formatter_token_space(tokens);
450                }
451            }
452            LanguageAST::Empty { span: _ } => {}
453        }
454    }
455}