1mod err;
2mod helper;
3
4use alloc::string::{
5 String,
6 ToString,
7};
8use alloc::vec::Vec;
9use core::str::FromStr;
10
11use err::*;
12use pest::iterators::Pair;
13use pest::Parser;
14
15use self::helper::*;
16use crate::ast::*;
17
18#[derive(Parser)]
19#[grammar = "src/dbml.pest"]
20struct DBMLParser;
21
22pub fn parse(input: &str) -> ParserResult<SchemaBlock> {
58 let pair = DBMLParser::parse(Rule::schema, input)?
59 .next()
60 .ok_or_else(|| unreachable!("unhandled parsing error"))?;
61
62 match pair.as_rule() {
63 Rule::schema => Ok(parse_schema(pair, input)?),
64 _ => throw_rules(&[Rule::schema], pair)?,
65 }
66}
67
68fn parse_schema<'a>(pair: Pair<Rule>, input: &'a str) -> ParserResult<SchemaBlock<'a>> {
69 let init = SchemaBlock {
70 span_range: s2r(pair.as_span()),
71 input,
72 ..Default::default()
73 };
74
75 pair.into_inner().try_fold(init, |mut acc, p1| {
76 match p1.as_rule() {
77 Rule::project_decl => acc.blocks.push(TopLevelBlock::Project(parse_project_decl(p1)?)),
78 Rule::table_decl => acc.blocks.push(TopLevelBlock::Table(parse_table_decl(p1)?)),
79 Rule::enum_decl => acc.blocks.push(TopLevelBlock::Enum(parse_enum_decl(p1)?)),
80 Rule::ref_decl => acc.blocks.push(TopLevelBlock::Ref(parse_ref_decl(p1)?)),
81 Rule::note_decl => acc.blocks.push(TopLevelBlock::Note(parse_note_decl(p1)?)),
82 Rule::table_group_decl => acc.blocks.push(TopLevelBlock::TableGroup(parse_table_group_decl(p1)?)),
83 Rule::EOI => (),
84 _ => {
85 throw_rules(
86 &[
87 Rule::project_decl,
88 Rule::table_decl,
89 Rule::enum_decl,
90 Rule::ref_decl,
91 Rule::table_group_decl,
92 ],
93 p1,
94 )?
95 }
96 };
97
98 Ok(acc)
99 })
100}
101
102fn parse_project_decl(pair: Pair<Rule>) -> ParserResult<ProjectBlock> {
103 let init = ProjectBlock {
104 span_range: s2r(pair.as_span()),
105 ..Default::default()
106 };
107
108 pair.into_inner().try_fold(init, |mut acc, p1| {
109 match p1.as_rule() {
110 Rule::ident => acc.ident = parse_ident(p1)?,
111 Rule::project_block => {
112 for p2 in p1.into_inner() {
113 match p2.as_rule() {
114 Rule::property => {
115 let prop = parse_property(p2.clone())?;
116
117 match prop.key.to_string.as_str() {
118 "database_type" => {
119 if let Value::String(db_name) = prop.value.value.clone() {
120 acc.database_type = match DatabaseType::from_str(&db_name) {
121 Ok(val) => Some(val),
122 Err(msg) => throw_msg(msg, p2)?,
123 }
124 }
125 }
126 _ => (),
127 }
128
129 acc.properties.push(prop)
130 }
131 Rule::note_decl => acc.note = Some(parse_note_decl(p2)?),
132 _ => throw_rules(&[Rule::property, Rule::note_decl], p2)?,
133 };
134 }
135 }
136 _ => throw_rules(&[Rule::project_block], p1)?,
137 }
138
139 Ok(acc)
140 })
141}
142
143fn parse_table_decl(pair: Pair<Rule>) -> ParserResult<TableBlock> {
144 let init = TableBlock {
145 span_range: s2r(pair.as_span()),
146 ..Default::default()
147 };
148
149 pair.into_inner().try_fold(init, |mut acc, p1| {
150 match p1.as_rule() {
151 Rule::decl_ident => {
152 acc.ident.span_range = s2r(p1.as_span());
153
154 let (schema, name) = parse_decl_ident(p1)?;
155
156 acc.ident.name = name;
157 acc.ident.schema = schema;
158 }
159 Rule::table_alias => {
160 for p2 in p1.into_inner() {
161 match p2.as_rule() {
162 Rule::ident => acc.ident.alias = Some(parse_ident(p2)?),
163 _ => throw_rules(&[Rule::ident], p2)?,
164 }
165 }
166 }
167 Rule::table_block => {
168 for p2 in p1.into_inner() {
169 match p2.as_rule() {
170 Rule::table_col => acc.cols.push(parse_table_col(p2)?),
171 Rule::note_decl => acc.note = Some(parse_note_decl(p2)?),
172 Rule::indexes_decl => acc.indexes = Some(parse_indexes_decl(p2)?),
173 _ => throw_rules(&[Rule::table_col, Rule::note_decl, Rule::indexes_decl], p2)?,
174 }
175 }
176 }
177 Rule::block_settings => {
178 acc.settings = Some(parse_table_settings(p1)?);
179 }
180 _ => {
181 throw_rules(
182 &[
183 Rule::decl_ident,
184 Rule::table_alias,
185 Rule::table_block,
186 Rule::block_settings,
187 ],
188 p1,
189 )?
190 }
191 }
192
193 Ok(acc)
194 })
195}
196
197fn parse_table_settings(pair: Pair<Rule>) -> ParserResult<TableSettings> {
198 Ok(TableSettings {
199 span_range: s2r(pair.as_span()),
200 attributes: pair
201 .into_inner()
202 .map(|p1| {
203 match p1.as_rule() {
204 Rule::attribute => parse_attribute(p1),
205 _ => throw_rules(&[Rule::attribute], p1),
206 }
207 })
208 .collect::<ParserResult<_>>()?,
209 })
210}
211
212fn parse_table_col(pair: Pair<Rule>) -> ParserResult<TableColumn> {
213 let init = TableColumn {
214 span_range: s2r(pair.as_span()),
215 ..Default::default()
216 };
217
218 pair.into_inner().try_fold(init, |mut acc, p1| {
219 match p1.as_rule() {
220 Rule::ident => acc.name = parse_ident(p1)?,
221 Rule::col_type => {
222 acc.r#type = parse_col_type(p1)?;
223 }
224 Rule::col_settings => acc.settings = Some(parse_col_settings(p1)?),
225 _ => throw_rules(&[Rule::ident, Rule::col_type, Rule::col_settings], p1)?,
226 }
227
228 Ok(acc)
229 })
230}
231
232fn build_type_name_with_schema(schema: Option<&Ident>, type_name: Pair<Rule>) -> String {
233 let mut type_name = type_name.as_str().to_string();
234 if let Some(schema) = schema {
235 type_name = format!("{}.{}", schema.to_string, type_name);
236 }
237 type_name
238}
239
240fn parse_col_type(pair: Pair<Rule>) -> ParserResult<ColumnType> {
241 let mut out = ColumnType {
242 span_range: s2r(pair.as_span()),
243 raw: pair.as_str().to_string(),
244 ..Default::default()
245 };
246
247 let mut schema = None;
248
249 for p1 in pair.into_inner() {
250 match p1.as_rule() {
251 Rule::ident => {
252 schema = Some(parse_ident(p1)?);
253 }
254 Rule::col_type_quoted | Rule::col_type_unquoted => {
255 for p2 in p1.into_inner() {
256 match p2.as_rule() {
257 Rule::var | Rule::spaced_var => {
258 out.type_name = ColumnTypeName::Raw(build_type_name_with_schema(schema.as_ref(), p2))
259 }
260 Rule::col_type_arg => out.args = parse_col_type_arg(p2)?,
261 Rule::col_type_array => {
262 let val = p2.into_inner().try_fold(None, |_, p3| {
263 match p3.as_rule() {
264 Rule::integer => {
265 let val = match p3.as_str().parse::<u32>() {
266 Ok(val) => Some(val),
267 Err(err) => throw_msg(err.to_string(), p3)?,
268 };
269
270 Ok(val)
271 }
272 _ => throw_rules(&[Rule::integer], p3)?,
273 }
274 })?;
275
276 out.arrays.push(val)
277 }
278 _ => {
279 throw_rules(
280 &[Rule::var, Rule::spaced_var, Rule::col_type_arg, Rule::col_type_array],
281 p2,
282 )?
283 }
284 }
285 }
286 }
287 _ => throw_rules(&[Rule::col_type_quoted, Rule::col_type_unquoted], p1)?,
288 }
289 }
290
291 Ok(out)
292}
293
294fn parse_col_type_arg(pair: Pair<Rule>) -> ParserResult<Vec<Value>> {
295 pair.into_inner().try_fold(vec![], |mut acc, p1| {
296 match p1.as_rule() {
297 Rule::value => acc.push(parse_value(p1)?),
298 _ => throw_rules(&[Rule::value], p1)?,
299 }
300
301 Ok(acc)
302 })
303}
304
305fn parse_col_settings(pair: Pair<Rule>) -> ParserResult<ColumnSettings> {
306 let init = ColumnSettings {
307 span_range: s2r(pair.as_span()),
308 ..Default::default()
309 };
310
311 pair.into_inner().try_fold(init, |mut acc, p1| {
312 match p1.as_rule() {
313 Rule::col_attribute => {
314 for p2 in p1.into_inner() {
315 match p2.as_rule() {
316 Rule::attribute => {
317 let attr = parse_attribute(p2)?;
318
319 match attr.key.to_string.as_str() {
320 "unique" => acc.is_unique = true,
321 "primary key" | "pk" => acc.is_pk = true,
322 "null" => acc.nullable = Some(Nullable::Null),
323 "not null" => acc.nullable = Some(Nullable::NotNull),
324 "increment" => acc.is_incremental = true,
325 "default" => acc.default = attr.value.clone().map(|v| v.value),
326 "note" => acc.note = attr.value.clone().map(|v| v.value.to_string()),
327 _ => (),
328 }
329
330 acc.attributes.push(attr);
331 }
332 Rule::ref_inline => acc.refs.push(parse_ref_inline(p2)?),
333 _ => throw_rules(&[Rule::ref_inline, Rule::attribute], p2)?,
334 }
335 }
336 }
337 _ => throw_rules(&[Rule::col_attribute], p1)?,
338 }
339
340 Ok(acc)
341 })
342}
343
344fn parse_enum_decl(pair: Pair<Rule>) -> ParserResult<EnumBlock> {
345 let init = EnumBlock {
346 span_range: s2r(pair.as_span()),
347 ..Default::default()
348 };
349
350 pair.into_inner().try_fold(init, |mut acc, p1| {
351 match p1.as_rule() {
352 Rule::decl_ident => {
353 acc.ident.span_range = s2r(p1.as_span());
354
355 let (schema, name) = parse_decl_ident(p1)?;
356
357 acc.ident.schema = schema;
358 acc.ident.name = name;
359 }
360 Rule::enum_block => acc.values = parse_enum_block(p1)?,
361 _ => throw_rules(&[Rule::decl_ident, Rule::enum_block], p1)?,
362 }
363
364 Ok(acc)
365 })
366}
367
368fn parse_enum_block(pair: Pair<Rule>) -> ParserResult<Vec<EnumValue>> {
369 pair
370 .into_inner()
371 .map(|p1| {
372 match p1.as_rule() {
373 Rule::enum_value => Ok(parse_enum_value(p1)?),
374 _ => throw_rules(&[Rule::enum_value], p1)?,
375 }
376 })
377 .collect()
378}
379
380fn parse_enum_value(pair: Pair<Rule>) -> ParserResult<EnumValue> {
381 let init = EnumValue {
382 span_range: s2r(pair.as_span()),
383 ..Default::default()
384 };
385
386 pair.into_inner().try_fold(init, |mut acc, p1| {
387 match p1.as_rule() {
388 Rule::ident => acc.value = parse_ident(p1)?,
389 Rule::enum_settings => {
390 let mut settings = EnumValueSettings {
391 span_range: s2r(p1.as_span()),
392 ..Default::default()
393 };
394
395 for p2 in p1.into_inner() {
396 match p2.as_rule() {
397 Rule::attribute => {
398 let attr = parse_attribute(p2)?;
399
400 match attr.key.to_string.as_str() {
401 "note" => settings.note = attr.value.clone().map(|v| v.value.to_string()),
402 _ => (),
403 }
404
405 settings.attributes.push(attr);
406 }
407 _ => throw_rules(&[Rule::attribute], p2)?,
408 }
409 }
410
411 acc.settings = Some(settings);
412 }
413 _ => throw_rules(&[Rule::ident, Rule::enum_settings], p1)?,
414 }
415
416 Ok(acc)
417 })
418}
419
420fn parse_ref_decl(pair: Pair<Rule>) -> ParserResult<RefBlock> {
421 for p1 in pair.into_inner() {
422 match p1.as_rule() {
423 Rule::ref_block | Rule::ref_short => {
424 let mut name = None;
425
426 for p2 in p1.into_inner() {
427 match p2.as_rule() {
428 Rule::ref_stmt => {
429 return parse_ref_stmt(p2).map(|mut o| {
430 o.name = name;
431 o
432 });
433 }
434 Rule::ident => {
435 name = Some(parse_ident(p2)?);
436 }
437 _ => throw_rules(&[Rule::ref_stmt, Rule::ident], p2)?,
438 }
439 }
440 }
441 _ => throw_rules(&[Rule::ref_block, Rule::ref_short], p1)?,
442 }
443 }
444
445 unreachable!("something went wrong parsing ref_decl")
446}
447
448fn parse_ref_stmt(pair: Pair<Rule>) -> ParserResult<RefBlock> {
449 let init = RefBlock {
450 span_range: s2r(pair.as_span()),
451 ..Default::default()
452 };
453
454 pair.into_inner().try_fold(init, |mut acc, p1| {
455 match p1.as_rule() {
456 Rule::relation => {
457 acc.rel = match Relation::from_str(p1.as_str()) {
458 Ok(rel) => rel,
459 Err(err) => throw_msg(err, p1)?,
460 }
461 }
462 Rule::ref_ident => {
463 let value = parse_ref_ident(p1)?;
464
465 if acc.rel == Relation::Undef {
466 acc.lhs = value;
467 } else {
468 acc.rhs = value;
469 }
470 }
471 Rule::rel_settings => acc.settings = Some(parse_rel_settings(p1)?),
472 _ => throw_rules(&[Rule::relation, Rule::ref_ident, Rule::rel_settings], p1)?,
473 }
474
475 Ok(acc)
476 })
477}
478
479fn parse_ref_inline(pair: Pair<Rule>) -> ParserResult<RefInline> {
480 let init = RefInline {
481 span_range: s2r(pair.as_span()),
482 ..Default::default()
483 };
484
485 pair.into_inner().try_fold(init, |mut acc, p1| {
486 match p1.as_rule() {
487 Rule::relation => {
488 acc.rel = match Relation::from_str(p1.as_str()) {
489 Ok(rel) => rel,
490 Err(err) => throw_msg(err, p1)?,
491 }
492 }
493 Rule::ref_ident => {
494 acc.rhs = parse_ref_ident(p1)?;
495 }
496 _ => throw_rules(&[Rule::relation, Rule::ref_ident], p1)?,
497 }
498
499 Ok(acc)
500 })
501}
502
503fn parse_ref_ident(pair: Pair<Rule>) -> ParserResult<RefIdent> {
504 let mut out = RefIdent {
505 span_range: s2r(pair.as_span()),
506 ..Default::default()
507 };
508 let mut tmp_tokens = vec![];
509
510 for p1 in pair.into_inner() {
511 match p1.as_rule() {
512 Rule::ident => tmp_tokens.push(parse_ident(p1)?),
513 Rule::ref_composition => {
514 for p2 in p1.into_inner() {
515 match p2.as_rule() {
516 Rule::ident => out.compositions.push(parse_ident(p2)?),
517 _ => throw_rules(&[Rule::ident], p2)?,
518 }
519 }
520 }
521 _ => throw_rules(&[Rule::ident, Rule::ref_composition], p1)?,
522 }
523 }
524
525 match tmp_tokens.len() {
526 1 => out.table = tmp_tokens.remove(0),
527 2 => {
528 out.schema = Some(tmp_tokens.remove(0));
529 out.table = tmp_tokens.remove(0);
530 }
531 _ => unreachable!("unwell formatted ident"),
532 }
533
534 Ok(out)
535}
536
537fn parse_table_group_decl(pair: Pair<Rule>) -> ParserResult<TableGroupBlock> {
538 let init = TableGroupBlock {
539 span_range: s2r(pair.as_span()),
540 ..Default::default()
541 };
542
543 pair.into_inner().try_fold(init, |mut acc, p1| {
544 match p1.as_rule() {
545 Rule::ident => acc.ident = parse_ident(p1)?,
546 Rule::table_group_block => {
547 for p2 in p1.into_inner() {
548 let mut init = TableGroupItem {
549 span_range: s2r(p2.as_span()),
550 ..Default::default()
551 };
552
553 match p2.as_rule() {
554 Rule::decl_ident => {
555 let (schema, name) = parse_decl_ident(p2)?;
556
557 init.schema = schema;
558 init.ident_alias = name;
559
560 acc.items.push(init)
561 }
562 Rule::note_decl => acc.note = Some(parse_note_decl(p2)?),
563 _ => throw_rules(&[Rule::decl_ident, Rule::note_decl], p2)?,
564 }
565 }
566 }
567 Rule::block_settings => {
568 acc.settings = Some(parse_table_group_settings(p1)?);
569 }
570 _ => throw_rules(&[Rule::ident, Rule::table_group_block, Rule::block_settings], p1)?,
571 }
572
573 Ok(acc)
574 })
575}
576
577fn parse_table_group_settings(pair: Pair<Rule>) -> ParserResult<TableGroupSettings> {
578 Ok(TableGroupSettings {
579 span_range: s2r(pair.as_span()),
580 attributes: pair
581 .into_inner()
582 .map(|p1| {
583 match p1.as_rule() {
584 Rule::attribute => parse_attribute(p1),
585 _ => throw_rules(&[Rule::attribute], p1),
586 }
587 })
588 .collect::<ParserResult<_>>()?,
589 })
590}
591
592fn parse_rel_settings(pair: Pair<Rule>) -> ParserResult<RefSettings> {
593 let init = RefSettings {
594 span_range: s2r(pair.as_span()),
595 ..Default::default()
596 };
597
598 pair.into_inner().try_fold(init, |mut acc, p1| {
599 match p1.as_rule() {
600 Rule::attribute => {
601 let attr = parse_attribute(p1.clone())?;
602
603 match attr.key.to_string.as_str() {
604 "update" => {
605 acc.on_update = match &attr.value {
606 Some(Literal {
607 value: Value::Enum(value),
608 ..
609 }) => {
610 match ReferentialAction::from_str(value) {
611 Ok(value) => Some(value),
612 Err(msg) => throw_msg(msg, p1)?,
613 }
614 }
615 _ => None,
616 }
617 }
618 "delete" => {
619 acc.on_delete = match &attr.value {
620 Some(Literal {
621 value: Value::Enum(value),
622 ..
623 }) => {
624 match ReferentialAction::from_str(value) {
625 Ok(value) => Some(value),
626 Err(msg) => throw_msg(msg, p1)?,
627 }
628 }
629 _ => None,
630 }
631 }
632 _ => (),
633 }
634
635 acc.attributes.push(attr);
636 }
637 _ => throw_rules(&[Rule::attribute], p1)?,
638 }
639
640 Ok(acc)
641 })
642}
643
644fn parse_note_decl(pair: Pair<Rule>) -> ParserResult<NoteBlock> {
645 for p1 in pair.into_inner() {
646 match p1.as_rule() {
647 Rule::note_short | Rule::note_block => {
648 for p2 in p1.clone().into_inner() {
649 match p2.as_rule() {
650 Rule::string_value => {
651 return parse_string_value(p2.clone()).map(|value| {
652 NoteBlock {
653 span_range: s2r(p1.as_span()),
654 value: Literal {
655 span_range: s2r(p2.as_span()),
656 raw: p2.as_str().to_string(),
657 value: Value::String(value),
658 },
659 }
660 })
661 }
662 _ => throw_rules(&[Rule::string_value], p2)?,
663 }
664 }
665 }
666 _ => throw_rules(&[Rule::note_short, Rule::note_block], p1)?,
667 }
668 }
669
670 unreachable!("something went wrong parsing note_decl")
671}
672
673fn parse_indexes_decl(pair: Pair<Rule>) -> ParserResult<IndexesBlock> {
674 let p1 = pair
675 .into_inner()
676 .next()
677 .ok_or_else(|| unreachable!("something went wrong parsing indexes_decl"))?;
678
679 match p1.as_rule() {
680 Rule::indexes_block => parse_indexes_block(p1),
681 _ => throw_rules(&[Rule::indexes_block], p1)?,
682 }
683}
684
685fn parse_indexes_block(pair: Pair<Rule>) -> ParserResult<IndexesBlock> {
686 let init = IndexesBlock {
687 span_range: s2r(pair.as_span()),
688 ..Default::default()
689 };
690
691 pair.into_inner().try_fold(init, |mut acc, p1| {
692 match p1.as_rule() {
693 Rule::indexes_single | Rule::indexes_multi => acc.defs.push(parse_indexes_single_multi(p1)?),
694 _ => throw_rules(&[Rule::indexes_single, Rule::indexes_multi], p1)?,
695 }
696
697 Ok(acc)
698 })
699}
700
701fn parse_indexes_single_multi(pair: Pair<Rule>) -> ParserResult<IndexesDef> {
702 let init = IndexesDef {
703 span_range: s2r(pair.as_span()),
704 ..Default::default()
705 };
706
707 pair.into_inner().try_fold(init, |mut acc, p1| {
708 match p1.as_rule() {
709 Rule::indexes_ident => acc.cols.push(parse_indexes_ident(p1)?),
710 Rule::indexes_settings => acc.settings = Some(parse_indexes_settings(p1)?),
711 _ => throw_rules(&[Rule::indexes_ident, Rule::indexes_settings], p1)?,
712 }
713
714 Ok(acc)
715 })
716}
717
718fn parse_indexes_ident(pair: Pair<Rule>) -> ParserResult<IndexesColumnType> {
719 let p1 = pair
720 .into_inner()
721 .next()
722 .ok_or_else(|| unreachable!("something went wrong at indexes_ident"))?;
723
724 match p1.as_rule() {
725 Rule::ident => {
726 let value = parse_ident(p1)?;
727 Ok(IndexesColumnType::String(value))
728 }
729 Rule::backquoted_quoted_string => {
730 let p2 = p1
731 .clone()
732 .into_inner()
733 .next()
734 .ok_or_else(|| unreachable!("something went wrong at indexes_ident"))?;
735
736 match p2.as_rule() {
737 Rule::backquoted_quoted_value => {
738 Ok(IndexesColumnType::Expr(Literal {
739 span_range: s2r(p1.as_span()),
740 raw: p1.as_str().to_string(),
741 value: Value::String(p2.as_str().to_string()),
742 }))
743 }
744 _ => throw_rules(&[Rule::backquoted_quoted_value], p2)?,
745 }
746 }
747 _ => throw_rules(&[Rule::ident, Rule::backquoted_quoted_string], p1)?,
748 }
749}
750
751fn parse_indexes_settings(pair: Pair<Rule>) -> ParserResult<IndexesSettings> {
752 let init = IndexesSettings {
753 span_range: s2r(pair.as_span()),
754 ..Default::default()
755 };
756
757 pair.into_inner().try_fold(init, |mut acc, p1| {
758 match p1.as_rule() {
759 Rule::attribute => {
760 let attr = parse_attribute(p1.clone())?;
761
762 match attr.key.to_string.as_str() {
763 "unique" => acc.is_unique = true,
764 "pk" => acc.is_pk = true,
765 "type" => {
766 acc.r#type = match attr.value.clone().map(|v| IndexesType::from_str(&v.value.to_string())) {
767 Some(val) => {
768 match val {
769 Ok(val) => Some(val),
770 Err(msg) => throw_msg(msg, p1)?,
771 }
772 }
773 None => None,
774 }
775 }
776 "name" => acc.name = attr.value.clone().map(|v| v.value.to_string()),
777 "note" => acc.note = attr.value.clone().map(|v| v.value.to_string()),
778 _ => (),
779 }
780
781 acc.attributes.push(attr);
782 }
783 _ => throw_rules(&[Rule::attribute], p1)?,
784 }
785
786 Ok(acc)
787 })
788}
789
790fn parse_string_value(pair: Pair<Rule>) -> ParserResult<String> {
791 let mut out = String::new();
792
793 for p1 in pair.into_inner() {
794 match p1.as_rule() {
795 Rule::triple_quoted_string => {
796 for p2 in p1.into_inner() {
797 match p2.as_rule() {
798 Rule::triple_quoted_value => out = p2.as_str().to_string(),
799 _ => throw_rules(&[Rule::triple_quoted_value], p2)?,
800 }
801 }
802 }
803 Rule::single_quoted_string => {
804 for p2 in p1.into_inner() {
805 match p2.as_rule() {
806 Rule::single_quoted_value => out = p2.as_str().to_string(),
807 _ => throw_rules(&[Rule::single_quoted_value], p2)?,
808 }
809 }
810 }
811 _ => throw_rules(&[Rule::triple_quoted_string, Rule::single_quoted_string], p1)?,
812 }
813 }
814
815 Ok(out)
816}
817
818fn parse_value(pair: Pair<Rule>) -> ParserResult<Value> {
819 let p1 = pair
820 .into_inner()
821 .next()
822 .ok_or_else(|| unreachable!("something went wrong at value"))?;
823
824 match p1.as_rule() {
825 Rule::string_value => {
826 let value = parse_string_value(p1)?;
827
828 Ok(Value::String(value))
829 }
830 Rule::number_value => {
831 let p2 = p1
832 .into_inner()
833 .next()
834 .ok_or_else(|| unreachable!("something went wrong at value"))?;
835
836 match p2.as_rule() {
837 Rule::decimal => {
838 match p2.as_str().parse::<f64>() {
839 Ok(val) => Ok(Value::Decimal(val)),
840 Err(err) => throw_msg(err.to_string(), p2)?,
841 }
842 }
843 Rule::integer => {
844 match p2.as_str().parse::<i64>() {
845 Ok(val) => Ok(Value::Integer(val)),
846 Err(err) => throw_msg(err.to_string(), p2)?,
847 }
848 }
849 _ => throw_rules(&[Rule::decimal, Rule::integer], p2)?,
850 }
851 }
852 Rule::boolean_value => {
853 if let Ok(v) = Value::from_str(p1.as_str()) {
854 Ok(v)
855 } else {
856 throw_msg(format!("'{}' is incompatible with boolean value", p1.as_str()), p1)?
857 }
858 }
859 Rule::hex_value => Ok(Value::HexColor(p1.as_str().to_string())),
860 Rule::backquoted_quoted_string => Ok(Value::Expr(p1.into_inner().as_str().to_string())),
861 _ => {
862 throw_rules(
863 &[
864 Rule::string_value,
865 Rule::number_value,
866 Rule::boolean_value,
867 Rule::hex_value,
868 Rule::backquoted_quoted_string,
869 ],
870 p1,
871 )?
872 }
873 }
874}
875
876fn parse_decl_ident(pair: Pair<Rule>) -> ParserResult<(Option<Ident>, Ident)> {
877 let mut tmp_tokens = vec![];
878
879 for p1 in pair.into_inner() {
880 match p1.as_rule() {
881 Rule::ident => tmp_tokens.push(parse_ident(p1)?),
882 _ => throw_rules(&[Rule::ident], p1)?,
883 }
884 }
885
886 let (schema, name) = match tmp_tokens.len() {
887 1 => (None, tmp_tokens.remove(0)),
888 2 => {
889 let schema = Some(tmp_tokens.remove(0));
890
891 (schema, tmp_tokens.remove(0))
892 }
893 _ => unreachable!("unwell formatted decl_ident"),
894 };
895
896 Ok((schema, name))
897}
898
899fn parse_ident(pair: Pair<Rule>) -> ParserResult<Ident> {
900 let p1 = pair
901 .into_inner()
902 .next()
903 .ok_or_else(|| unreachable!("something went wrong at ident"))?;
904
905 let ident = match p1.as_rule() {
906 Rule::var => {
907 Ident {
908 span_range: s2r(p1.as_span()),
909 raw: p1.as_str().to_string(),
910 to_string: p1.as_str().to_string(),
911 }
912 }
913 Rule::double_quoted_string => {
914 Ident {
915 span_range: s2r(p1.as_span()),
916 raw: p1.as_str().to_string(),
917 to_string: p1.into_inner().as_str().to_string(),
918 }
919 }
920 _ => throw_rules(&[Rule::var, Rule::double_quoted_string], p1)?,
921 };
922
923 Ok(ident)
924}
925
926pub fn parse_attribute(pair: Pair<Rule>) -> ParserResult<Attribute> {
927 let mut init = Attribute {
928 span_range: s2r(pair.as_span()),
929 ..Default::default()
930 };
931
932 for p1 in pair.into_inner() {
933 match p1.as_rule() {
934 Rule::spaced_var => {
935 if init.key.raw.is_empty() {
936 init.key = Ident {
937 span_range: s2r(p1.as_span()),
938 raw: p1.as_str().to_string(),
939 to_string: p1.as_str().to_string(),
940 };
941 } else {
942 init.value = Some(Literal {
943 span_range: s2r(p1.as_span()),
944 raw: p1.as_str().to_string(),
945 value: Value::Enum(p1.as_str().to_string()),
946 })
947 }
948 }
949 Rule::value => {
950 init.value = Some(Literal {
951 span_range: s2r(p1.as_span()),
952 raw: p1.as_str().to_string(),
953 value: parse_value(p1)?,
954 })
955 }
956 Rule::double_quoted_string => {
957 init.value = Some(Literal {
958 span_range: s2r(p1.as_span()),
959 raw: p1.as_str().to_string(),
960 value: Value::String(p1.into_inner().as_str().to_string()),
961 })
962 }
963 _ => throw_rules(&[Rule::value, Rule::spaced_var, Rule::double_quoted_string], p1)?,
964 }
965 }
966
967 Ok(init)
968}
969
970pub fn parse_property(pair: Pair<Rule>) -> ParserResult<Property> {
971 let init = parse_attribute(pair.clone())?;
972
973 match init.value {
974 Some(value) => {
975 Ok(Property {
976 span_range: init.span_range,
977 key: init.key,
978 value,
979 })
980 }
981 None => throw_rules(&[Rule::property], pair),
982 }
983}