Skip to main content

regast_syntax/
error.rs

1use std::{fmt, sync::Arc};
2
3use serde::{Deserialize, Serialize};
4
5use crate::Span;
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(tag = "kind", rename_all = "snake_case")]
9pub enum ParseErrorKind {
10    UnbalancedParen,
11    UnclosedClass,
12    InvalidEscape(char),
13    DanglingQuantifier,
14    InvalidRange { lo: char, hi: char },
15    InvalidCounted,
16    DuplicateGroupName(Box<str>),
17    UnsupportedFeature(&'static str),
18}
19
20#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct ParseError {
22    pub kind: ParseErrorKind,
23    pub span: Span,
24    pub src: Arc<str>,
25}
26
27impl ParseError {
28    pub(crate) fn new(kind: ParseErrorKind, span: Span, src: &Arc<str>) -> Self {
29        Self {
30            kind,
31            span,
32            src: Arc::clone(src),
33        }
34    }
35}
36
37impl fmt::Display for ParseError {
38    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39        let message = match &self.kind {
40            ParseErrorKind::UnbalancedParen => "unbalanced closing parenthesis".to_owned(),
41            ParseErrorKind::UnclosedClass => "unclosed character class".to_owned(),
42            ParseErrorKind::InvalidEscape(c) => format!("invalid escape: \\{c}"),
43            ParseErrorKind::DanglingQuantifier => "quantifier has no preceding atom".to_owned(),
44            ParseErrorKind::InvalidRange { lo, hi } => format!("invalid class range: {lo}-{hi}"),
45            ParseErrorKind::InvalidCounted => "invalid counted repetition".to_owned(),
46            ParseErrorKind::DuplicateGroupName(name) => format!("duplicate group name: {name}"),
47            ParseErrorKind::UnsupportedFeature(feature) => {
48                format!("unsupported regular-expression feature: {feature}")
49            }
50        };
51        writeln!(formatter, "{message}")?;
52        writeln!(formatter, "{}", self.src)?;
53        let width = (self.span.end - self.span.start).max(1) as usize;
54        write!(
55            formatter,
56            "{}{}",
57            " ".repeat(self.span.start as usize),
58            "^".repeat(width)
59        )
60    }
61}
62
63impl std::error::Error for ParseError {}