math_core/latex_parser/
error.rs1use std::fmt;
2
3use strum_macros::IntoStaticStr;
4
5use super::token::Token;
8
9#[derive(Debug)]
11pub struct LatexError<'source>(pub usize, pub LatexErrKind<'source>);
12
13#[derive(Debug)]
14pub enum LatexErrKind<'source> {
15 UnexpectedToken {
16 expected: &'static Token<'static>,
17 got: Token<'source>,
18 },
19 UnclosedGroup(Token<'source>),
20 UnexpectedClose(Token<'source>),
21 UnexpectedEOF,
22 MissingParenthesis {
23 location: &'static Token<'static>,
24 got: Token<'source>,
25 },
26 DisallowedChars,
27 UnknownEnvironment(&'source str),
28 UnknownCommand(&'source str),
29 UnknownColor(&'source str),
30 MismatchedEnvironment {
31 expected: &'source str,
32 got: &'source str,
33 },
34 CannotBeUsedHere {
35 got: Token<'source>,
36 correct_place: Place,
37 },
38 ExpectedText(&'static str),
39 ExpectedLength(&'source str),
40 ExpectedColSpec(&'source str),
41 RenderError,
42 NotValidInTextMode(Token<'source>),
43 InvalidMacroName(&'source str),
44}
45
46#[derive(Debug, IntoStaticStr)]
47#[repr(u32)] pub enum Place {
49 #[strum(serialize = r"after \int, \sum, ...")]
50 AfterBigOp,
51 #[strum(serialize = r"before supported operators")]
52 BeforeSomeOps,
53 #[strum(serialize = r"after an identifier or operator")]
54 AfterOpOrIdent,
55}
56
57impl LatexErrKind<'_> {
58 pub fn string(&self) -> String {
63 match self {
64 LatexErrKind::UnexpectedToken { expected, got } => {
65 "Expected token \"".to_string()
66 + <&str>::from(*expected)
67 + "\", but found token \""
68 + <&str>::from(got)
69 + "\"."
70 }
71 LatexErrKind::UnclosedGroup(expected) => {
72 "Expected token \"".to_string() + <&str>::from(expected) + "\", but not found."
73 }
74 LatexErrKind::UnexpectedClose(got) => {
75 "Unexpected closing token: \"".to_string() + <&str>::from(got) + "\"."
76 }
77 LatexErrKind::UnexpectedEOF => "Unexpected end of file.".to_string(),
78 LatexErrKind::MissingParenthesis { location, got } => {
79 "There must be a parenthesis after \"".to_string()
80 + <&str>::from(*location)
81 + "\", but not found. Instead, \""
82 + <&str>::from(got)
83 + "\" was found."
84 }
85 LatexErrKind::DisallowedChars => "Disallowed characters in text group.".to_string(),
86 LatexErrKind::UnknownEnvironment(environment) => {
87 "Unknown environment \"".to_string() + environment + "\"."
88 }
89 LatexErrKind::UnknownCommand(cmd) => "Unknown command \"\\".to_string() + cmd + "\".",
90 LatexErrKind::UnknownColor(color) => "Unknown color \"".to_string() + color + "\".",
91 LatexErrKind::MismatchedEnvironment { expected, got } => {
92 "Expected \"\\end{".to_string() + expected + "}\", but got \"\\end{" + got + "}\"."
93 }
94 LatexErrKind::CannotBeUsedHere { got, correct_place } => {
95 "Got \"".to_string()
96 + <&str>::from(got)
97 + "\", which may only appear "
98 + <&str>::from(correct_place)
99 + "."
100 }
101 LatexErrKind::ExpectedText(place) => "Expected text in ".to_string() + place + ".",
102 LatexErrKind::ExpectedLength(got) => {
103 "Expected length with units, got \"".to_string() + got + "\"."
104 }
105 LatexErrKind::ExpectedColSpec(got) => {
106 "Expected column specification, got \"".to_string() + got + "\"."
107 }
108 LatexErrKind::RenderError => "Render error".to_string(),
109 LatexErrKind::NotValidInTextMode(got) => {
110 "Got \"".to_string() + <&str>::from(got) + "\", which is not valid in text mode."
111 }
112 LatexErrKind::InvalidMacroName(name) => {
113 "Invalid macro name: \"\\".to_string() + name + "\"."
114 }
115 }
116 }
117}
118
119impl fmt::Display for LatexError<'_> {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 write!(f, "{}: {}", self.0, self.1.string())
122 }
123}
124
125impl std::error::Error for LatexError<'_> {}
126
127pub trait GetUnwrap {
128 fn get_unwrap(&self, range: std::ops::Range<usize>) -> &str;
130}
131
132impl GetUnwrap for str {
133 #[cfg(target_arch = "wasm32")]
134 #[inline]
135 fn get_unwrap(&self, range: std::ops::Range<usize>) -> &str {
136 unsafe { self.get_unchecked(range) }
139 }
140 #[cfg(not(target_arch = "wasm32"))]
141 #[inline]
142 fn get_unwrap(&self, range: std::ops::Range<usize>) -> &str {
143 self.get(range).expect("valid range")
144 }
145}
146
147