1use crate::source_location::SourceLocation;
2use crate::token::Token;
3
4#[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#[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}