use std::error::Error;
use std::fmt::Display;
use crate::tokenizer::TextPosition;
use crate::wikitext::TextFormatting;
pub type Result<T> = std::result::Result<T, ParserError>;
#[derive(Debug, Eq, PartialEq)]
pub struct ParserError {
pub kind: ParserErrorKind,
pub position: TextPosition,
pub annotations: Vec<String>,
}
#[derive(Debug, Eq, PartialEq)]
pub enum ParserErrorKind {
SecondRootSection {
label: String,
},
SectionLevelTooDeep {
level: usize,
},
UnmatchedDoubleCloseBrace,
UnmatchedDoubleOpenBrace,
UnmatchedDoubleCloseBracket,
UnmatchedDoubleOpenBracket,
UnmatchedNoWikiClose,
UnmatchedNoWikiOpen,
UnexpectedTokenInTag {
token: String,
},
UnexpectedTokenInParameter {
token: String,
},
UnexpectedTokenInLink {
token: String,
},
UnexpectedTokenInLinkLabel {
token: String,
},
UnexpectedTokenInFormattedText {
token: String,
},
UnexpectedTokenInListItem {
token: String,
},
UnexpectedToken {
expected: String,
actual: String,
},
UnclosedTextFormatting {
formatting: TextFormatting,
},
UnexpectedEof,
}
impl Display for ParserErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParserErrorKind::SecondRootSection { label } => {
write!(f, "found second root section {label:?}")
}
ParserErrorKind::SectionLevelTooDeep { level } => {
write!(f, "found a section of a too deep level {level}")
}
ParserErrorKind::UnmatchedDoubleCloseBrace => {
write!(f, "found an unmatched double closing brace }}}}")
}
ParserErrorKind::UnmatchedDoubleOpenBrace => {
write!(f, "found an unmatched double open brace {{{{")
}
ParserErrorKind::UnmatchedDoubleCloseBracket => {
write!(f, "found an unmatched double close bracket ]]")
}
ParserErrorKind::UnmatchedDoubleOpenBracket => {
write!(f, "found an unmatched double open bracket [[")
}
ParserErrorKind::UnmatchedNoWikiClose => {
write!(f, "found an unmatched nowiki close tag </nowiki>")
}
ParserErrorKind::UnmatchedNoWikiOpen => {
write!(f, "found an unmatched nowiki open tag <nowiki>")
}
ParserErrorKind::UnexpectedTokenInTag { token } => {
write!(f, "found an unexpected token {token:?} in a tag")
}
ParserErrorKind::UnexpectedTokenInParameter { token } => {
write!(f, "found an unexpected token {token:?} in a parameter")
}
ParserErrorKind::UnexpectedTokenInLink { token } => {
write!(f, "found an unexpected token {token:?} in a link")
}
ParserErrorKind::UnexpectedTokenInLinkLabel { token } => {
write!(f, "found an unexpected token {token:?} in a link label")
}
ParserErrorKind::UnexpectedTokenInFormattedText { token } => {
write!(f, "found an unexpected token {token:?} in formatted text")
}
ParserErrorKind::UnexpectedTokenInListItem { token } => {
write!(f, "found an unexpected token {token:?} in a list item")
}
ParserErrorKind::UnexpectedToken { expected, actual } => write!(
f,
"found an unexpected token {actual:?} where {expected:?} was expected"
),
ParserErrorKind::UnclosedTextFormatting { formatting } => write!(
f,
"found an unclosed text formatting expression {formatting}:?"
),
ParserErrorKind::UnexpectedEof => {
write!(f, "the file ended, but we expected more content")
}
}
}
}
impl Display for ParserError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} at line {}, column {}",
self.kind, self.position.line, self.position.column
)?;
if !self.annotations.is_empty() {
write!(f, "; additional information: [")?;
let mut once = true;
for annotation in &self.annotations {
if once {
once = false;
} else {
write!(f, ", ")?;
}
write!(f, "{annotation}")?;
}
write!(f, "]")?;
}
Ok(())
}
}
impl Error for ParserError {}
impl ParserError {
pub fn annotate(&mut self, annotation: String) {
self.annotations.push(annotation);
}
pub fn annotate_self(mut self, annotation: String) -> Self {
self.annotations.push(annotation);
self
}
}
impl ParserErrorKind {
pub(crate) fn into_parser_error(self, position: TextPosition) -> ParserError {
ParserError {
kind: self,
position,
annotations: Default::default(),
}
}
}