Skip to main content

katex_parser/
error.rs

1use crate::source_location::SourceLocation;
2use crate::token::Token;
3
4/// A parse failure, mirroring MoonBit's `ParseFailure` suberror.
5#[derive(Debug, Clone, PartialEq)]
6pub enum ParseError {
7    UnexpectedCharacter {
8        message: String,
9        loc: Option<SourceLocation>,
10    },
11    ExpectedToken {
12        expected: String,
13        actual: Diagnostic,
14    },
15    UndefinedControlSequence {
16        name: String,
17        loc: Option<SourceLocation>,
18    },
19    InvalidArgument {
20        message: String,
21        loc: Option<SourceLocation>,
22    },
23    DoubleSuperscript {
24        loc: Option<SourceLocation>,
25    },
26    DoubleSubscript {
27        loc: Option<SourceLocation>,
28    },
29    ExpectedGroupAfter {
30        symbol: String,
31        loc: Option<SourceLocation>,
32    },
33    FunctionNotAllowed {
34        func_name: String,
35        context: String,
36        loc: Option<SourceLocation>,
37    },
38    MissingFunctionHandler {
39        func_name: String,
40        loc: Option<SourceLocation>,
41    },
42    TooManyExpansions {
43        limit: usize,
44    },
45    InternalInvariant {
46        message: String,
47    },
48}
49
50impl std::fmt::Display for ParseError {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        match self {
53            ParseError::UnexpectedCharacter { message, .. } => write!(f, "{message}"),
54            ParseError::ExpectedToken { expected, actual } => {
55                write!(f, "Expected token {expected:?}, got {:?}", actual.text)
56            }
57            ParseError::UndefinedControlSequence { name, .. } => {
58                write!(f, "Undefined control sequence: {name}")
59            }
60            ParseError::InvalidArgument { message, .. } => write!(f, "{message}"),
61            ParseError::DoubleSuperscript { .. } => write!(f, "Double superscript"),
62            ParseError::DoubleSubscript { .. } => write!(f, "Double subscript"),
63            ParseError::ExpectedGroupAfter { symbol, .. } => {
64                write!(f, "Expected group after {symbol}")
65            }
66            ParseError::FunctionNotAllowed {
67                func_name,
68                context,
69                ..
70            } => write!(f, "Function {func_name} is not allowed in {context} context"),
71            ParseError::MissingFunctionHandler { func_name, .. } => {
72                write!(f, "No handler defined for function {func_name}")
73            }
74            ParseError::TooManyExpansions { limit } => {
75                write!(f, "Too many expansions: reached limit of {limit}")
76            }
77            ParseError::InternalInvariant { message } => write!(f, "{message}"),
78        }
79    }
80}
81
82impl std::error::Error for ParseError {}
83
84/// Diagnostic information attached to an offending token.
85#[derive(Debug, Clone, PartialEq)]
86pub struct Diagnostic {
87    pub text: String,
88    pub loc: Option<SourceLocation>,
89}
90
91impl Diagnostic {
92    pub fn from_token(token: &Token) -> Self {
93        Diagnostic {
94            text: token.text.clone(),
95            loc: token.loc.clone(),
96        }
97    }
98}