1use std::error::Error;
2use std::fmt::Display;
3
4use crate::tokenizer::TextPosition;
5use crate::wikitext::TextFormatting;
6
7pub type Result<T> = std::result::Result<T, ParserError>;
8
9#[derive(Debug, Eq, PartialEq)]
11pub struct ParserError {
12 pub kind: ParserErrorKind,
14 pub position: TextPosition,
16 pub annotations: Vec<String>,
18}
19
20#[derive(Debug, Eq, PartialEq)]
22pub enum ParserErrorKind {
23 SecondRootSection {
25 label: String,
27 },
28
29 SectionLevelTooDeep {
31 level: usize,
33 },
34
35 UnmatchedDoubleCloseBrace,
37
38 UnmatchedDoubleOpenBrace,
40
41 UnmatchedDoubleCloseBracket,
43
44 UnmatchedDoubleOpenBracket,
46
47 UnmatchedNoWikiClose,
49
50 UnmatchedNoWikiOpen,
52
53 UnexpectedTokenInTag {
55 token: String,
57 },
58
59 UnexpectedTokenInParameter {
61 token: String,
63 },
64
65 UnexpectedTokenInLink {
67 token: String,
69 },
70
71 UnexpectedTokenInLinkLabel {
73 token: String,
75 },
76
77 UnexpectedTokenInFormattedText {
79 token: String,
81 },
82
83 UnexpectedTokenInListItem {
85 token: String,
87 },
88
89 UnexpectedToken {
91 expected: String,
93 actual: String,
95 },
96
97 UnclosedTextFormatting {
99 formatting: TextFormatting,
101 },
102
103 UnexpectedEof,
105}
106
107impl Display for ParserErrorKind {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 match self {
110 ParserErrorKind::SecondRootSection { label } => {
111 write!(f, "found second root section {label:?}")
112 }
113 ParserErrorKind::SectionLevelTooDeep { level } => {
114 write!(f, "found a section of a too deep level {level}")
115 }
116 ParserErrorKind::UnmatchedDoubleCloseBrace => {
117 write!(f, "found an unmatched double closing brace }}}}")
118 }
119 ParserErrorKind::UnmatchedDoubleOpenBrace => {
120 write!(f, "found an unmatched double open brace {{{{")
121 }
122 ParserErrorKind::UnmatchedDoubleCloseBracket => {
123 write!(f, "found an unmatched double close bracket ]]")
124 }
125 ParserErrorKind::UnmatchedDoubleOpenBracket => {
126 write!(f, "found an unmatched double open bracket [[")
127 }
128 ParserErrorKind::UnmatchedNoWikiClose => {
129 write!(f, "found an unmatched nowiki close tag </nowiki>")
130 }
131 ParserErrorKind::UnmatchedNoWikiOpen => {
132 write!(f, "found an unmatched nowiki open tag <nowiki>")
133 }
134 ParserErrorKind::UnexpectedTokenInTag { token } => {
135 write!(f, "found an unexpected token {token:?} in a tag")
136 }
137 ParserErrorKind::UnexpectedTokenInParameter { token } => {
138 write!(f, "found an unexpected token {token:?} in a parameter")
139 }
140 ParserErrorKind::UnexpectedTokenInLink { token } => {
141 write!(f, "found an unexpected token {token:?} in a link")
142 }
143 ParserErrorKind::UnexpectedTokenInLinkLabel { token } => {
144 write!(f, "found an unexpected token {token:?} in a link label")
145 }
146 ParserErrorKind::UnexpectedTokenInFormattedText { token } => {
147 write!(f, "found an unexpected token {token:?} in formatted text")
148 }
149 ParserErrorKind::UnexpectedTokenInListItem { token } => {
150 write!(f, "found an unexpected token {token:?} in a list item")
151 }
152 ParserErrorKind::UnexpectedToken { expected, actual } => write!(
153 f,
154 "found an unexpected token {actual:?} where {expected:?} was expected"
155 ),
156 ParserErrorKind::UnclosedTextFormatting { formatting } => write!(
157 f,
158 "found an unclosed text formatting expression {formatting}:?"
159 ),
160 ParserErrorKind::UnexpectedEof => {
161 write!(f, "the file ended, but we expected more content")
162 }
163 }
164 }
165}
166
167impl Display for ParserError {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 write!(
170 f,
171 "{} at line {}, column {}",
172 self.kind, self.position.line, self.position.column
173 )?;
174
175 if !self.annotations.is_empty() {
176 write!(f, "; additional information: [")?;
177 let mut once = true;
178 for annotation in &self.annotations {
179 if once {
180 once = false;
181 } else {
182 write!(f, ", ")?;
183 }
184 write!(f, "{annotation}")?;
185 }
186 write!(f, "]")?;
187 }
188
189 Ok(())
190 }
191}
192
193impl Error for ParserError {}
194
195impl ParserError {
196 pub fn annotate(&mut self, annotation: String) {
198 self.annotations.push(annotation);
199 }
200
201 pub fn annotate_self(mut self, annotation: String) -> Self {
203 self.annotations.push(annotation);
204 self
205 }
206}
207
208impl ParserErrorKind {
209 pub(crate) fn into_parser_error(self, position: TextPosition) -> ParserError {
210 ParserError {
211 kind: self,
212 position,
213 annotations: Default::default(),
214 }
215 }
216}