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 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 *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 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}