scarf_parser/parser/
mod.rs1pub mod declarations;
7pub mod errors;
8pub mod expressions;
9pub mod general;
10pub mod source_text;
11pub mod udp_declaration_and_instantiation;
12pub mod utils;
13use crate::*;
14use ariadne::Report;
15use ariadne::{Color, Label, ReportKind};
16use chumsky::error::{RichPattern, RichReason};
17use chumsky::input::ValueInput;
18use chumsky::prelude::*;
19pub use scarf_syntax::SourceText;
20pub use declarations::*;
21pub use errors::*;
22pub use expressions::*;
23pub use general::*;
24pub use source_text::*;
25pub use udp_declaration_and_instantiation::*;
26pub use utils::*;
27
28pub type ParserSpan = SimpleSpan;
29
30pub fn parse<'a, I>(src: I) -> ParseResult<SourceText<'a>, Rich<'a, Token<'a>>>
31where
32 I: ValueInput<'a, Token = Token<'a>, Span = ParserSpan>,
33{
34 source_text_parser().parse(src)
35}
36
37fn format_pattern<'a>(pattern: &RichPattern<'a, Token<'a>>) -> String {
38 match pattern {
39 RichPattern::Token(tok) => tok.to_string(),
40 RichPattern::Label(l) => l.to_string(),
41 RichPattern::Identifier(i) => i.to_string(),
42 RichPattern::Any => "any".to_owned(),
43 RichPattern::SomethingElse => "something else".to_owned(),
44 RichPattern::EndOfInput => "end of input".to_owned(),
45 }
46}
47
48fn format_reason<'a>(reason: &RichReason<'a, Token<'a>>) -> String {
49 match reason {
50 RichReason::ExpectedFound { expected, found } => {
51 let found_str = match found.as_deref() {
52 Some(tok) => tok.to_string(),
53 None => "end of input".to_owned(),
54 };
55 let expected_str = match &expected[..] {
56 [] => "something else".to_owned(),
57 [expected] => format_pattern(expected),
58 _ => {
59 let mut temp_expected_str = String::new();
60 for expected in &expected[..expected.len() - 1] {
61 temp_expected_str.push_str(format_pattern(expected).as_str());
62 temp_expected_str.push_str(", ");
63 }
64 temp_expected_str.push_str("or ");
65 temp_expected_str.push_str(format_pattern(expected.last().unwrap()).as_str());
66 temp_expected_str
67 }
68 };
69 format!("found {}, expected {}", found_str, expected_str)
70 }
71 RichReason::Custom(str) => str.clone(),
72 }
73}
74
75fn format_reason_short<'a>(reason: &RichReason<'a, Token<'a>>) -> String {
76 match reason {
77 RichReason::ExpectedFound { expected: _, found } => match found.as_deref() {
78 Some(tok) => format!("Didn't expect {}", tok.to_string()),
79 None => "Didn't expect end of input".to_owned(),
80 },
81 RichReason::Custom(str) => str.clone(),
82 }
83}
84
85pub fn report_parse_errors<'a, 'b>(
86 result: ParseResult<SourceText, Rich<'a, Token<'a>, ParserSpan>>,
87 file_path: &'b str,
88) -> Vec<Report<'a, (&'b str, std::ops::Range<usize>)>> {
89 let mut reports: Vec<Report<'a, (&'b str, std::ops::Range<usize>)>> = Vec::new();
90 result.into_errors().into_iter().for_each(|e| {
91 let report = Report::build(ReportKind::Error, (file_path, e.span().into_range()))
92 .with_config(ariadne::Config::new().with_index_type(ariadne::IndexType::Byte))
93 .with_message(format_reason(e.reason()))
94 .with_label(
95 Label::new((file_path, e.span().into_range()))
96 .with_message(format_reason_short(e.reason()))
97 .with_color(Color::Red),
98 )
99 .finish();
100 reports.push(report);
101 });
102 reports
103}