use super::{ExtractedToken, Token, rule::Rule};
use crate::utf16::Utf16IndexMap;
use serde::{Serializer, ser::SerializeTuple};
use std::borrow::Cow;
use std::ops::Range;
use strum_macros::IntoStaticStr;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct ParseError {
token: Token,
rule: Cow<'static, str>,
#[serde(serialize_with = "serialize_span")]
span: Range<usize>,
kind: ParseErrorKind,
}
impl ParseError {
#[inline]
pub fn new(kind: ParseErrorKind, rule: Rule, current: &ExtractedToken) -> Self {
let token = current.token;
let span = Range::clone(¤t.span);
let rule = cow!(rule.name());
ParseError {
token,
rule,
span,
kind,
}
}
#[inline]
pub fn token(&self) -> Token {
self.token
}
#[inline]
pub fn rule(&self) -> &str {
&self.rule
}
#[inline]
pub fn span(&self) -> Range<usize> {
Range::clone(&self.span)
}
#[inline]
pub fn kind(&self) -> ParseErrorKind {
self.kind
}
#[must_use]
pub fn to_utf16_indices(&self, map: &Utf16IndexMap) -> Self {
let ParseError {
token,
rule,
span,
kind,
} = self.clone();
let start = map.get_index(span.start);
let end = map.get_index(span.end);
let span = start..end;
ParseError {
token,
rule,
span,
kind,
}
}
}
#[derive(Serialize, Deserialize, IntoStaticStr, Debug, Copy, Clone, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum ParseErrorKind {
RecursionDepthExceeded,
EndOfInput,
NoRulesMatch,
RuleFailed,
NotSupportedMode,
NotStartOfLine,
InvalidInclude,
ListEmpty,
ListContainsNonItem,
ListItemOutsideList,
ListDepthExceeded,
TableContainsNonRow,
TableRowContainsNonCell,
TableRowOutsideTable,
TableCellOutsideTable,
TabViewEmpty,
TabViewContainsNonTab,
TabOutsideTabView,
FootnotesNested,
BlockquoteDepthExceeded,
RubyTextOutsideRuby,
BibliographyContainsNonDefinitionList,
NoSuchBlock,
BlockDisallowsStar,
BlockDisallowsScore,
BlockMissingName,
BlockMissingCloseBrackets,
BlockMalformedArguments,
BlockMissingArguments,
BlockExpectedEnd,
BlockEndMismatch,
NoSuchEmbed,
NoSuchModule,
ModuleMissingName,
NoSuchPage,
NoSuchVariable,
InvalidUrl,
}
impl ParseErrorKind {
#[inline]
pub fn name(self) -> &'static str {
self.into()
}
}
fn serialize_span<S>(span: &Range<usize>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut tuple = serializer.serialize_tuple(2)?;
tuple.serialize_element(&span.start)?;
tuple.serialize_element(&span.end)?;
tuple.end()
}