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