nyar_error/parsing/
mod.rs

1use diagnostic::{Color, Diagnostic, Label, ReportKind, SourceID, SourceSpan};
2use std::{
3    char::ParseCharError,
4    fmt::{Display, Formatter},
5    ops::Range,
6    str::ParseBoolError,
7};
8
9use crate::{NyarError, NyarErrorKind};
10
11#[cfg(feature = "dashu")]
12mod for_dashu;
13#[cfg(feature = "json5")]
14mod for_json5;
15
16mod for_number;
17#[cfg(feature = "peginator")]
18mod for_peginator;
19#[cfg(feature = "toml")]
20mod for_toml;
21
22#[cfg(feature = "pratt")]
23mod for_pratt;
24#[cfg(feature = "yggdrasil-rt")]
25mod for_ygg;
26
27#[derive(Clone, Debug, Eq, PartialEq)]
28pub struct SyntaxError {
29    pub info: String,
30    pub hint: String,
31    pub span: SourceSpan,
32}
33
34#[derive(Debug, Copy, Clone)]
35pub enum ForeignInterfaceError {
36    MissingForeignMark { span: SourceSpan },
37    MissingForeignFlag { kind: &'static str, hint: &'static str, span: SourceSpan },
38    InvalidForeignModule { span: SourceSpan },
39    InvalidForeignName { span: SourceSpan },
40}
41
42impl Display for SyntaxError {
43    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44        f.write_str(&self.info)
45    }
46}
47
48impl SyntaxError {
49    /// Create a new syntax error with given message
50    pub fn new(info: impl Into<String>) -> Self {
51        Self { span: SourceSpan::default(), info: info.into(), hint: "".to_string() }
52    }
53    /// Set the excepted hint
54    pub fn with_hint<S: ToString>(mut self, hint: S) -> Self {
55        self.hint = hint.to_string();
56        self
57    }
58    /// Set the file id
59    pub fn with_file(mut self, file: SourceID) -> Self {
60        self.span.set_file(file);
61        self
62    }
63    /// Set the file range
64    pub fn with_range(mut self, range: &Range<u32>) -> Self {
65        self.span.set_range(range.clone());
66        self
67    }
68    /// Set the file span
69    pub fn with_span(mut self, span: SourceSpan) -> Self {
70        self.span = span;
71        self
72    }
73}
74
75impl SyntaxError {
76    pub fn as_error(self, kind: ReportKind) -> NyarError {
77        NyarErrorKind::Parsing(self).as_error(kind)
78    }
79    pub fn as_report(&self, kind: ReportKind) -> Diagnostic {
80        let mut report = Diagnostic::new(kind).with_location(self.span.get_file(), Some(self.span.get_start()));
81        report.set_message(&self.info);
82        report.add_label(Label::new(self.span).with_message(&self.hint).with_color(Color::Red));
83        report.finish()
84    }
85}
86
87impl From<SyntaxError> for NyarError {
88    fn from(value: SyntaxError) -> Self {
89        NyarErrorKind::Parsing(value).as_error(ReportKind::Error)
90    }
91}
92
93macro_rules! wrap_parse_error {
94    ($($type:ty),*) => {
95        $(
96            impl From<$type> for NyarError {
97                fn from(value: $type) -> Self {
98                    SyntaxError::new(value.to_string()).into()
99                }
100            }
101        )*
102    };
103}
104
105wrap_parse_error!(ParseBoolError, ParseCharError, url::ParseError);
106
107#[cfg(feature = "dashu")]
108wrap_parse_error!(dashu::base::ParseError);