use std::error::Error;
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum ParseErrorKind {
UnexpectedToken,
InvalidSelectorValue,
NestingTooDeep,
SyntaxError,
MultipleTextSelectors,
ElementAfterTextSelector,
}
impl fmt::Display for ParseErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseErrorKind::UnexpectedToken => write!(f, "Unexpected token"),
ParseErrorKind::InvalidSelectorValue => write!(f, "Invalid selector value"),
ParseErrorKind::NestingTooDeep => write!(f, "Nesting level too deep"),
ParseErrorKind::SyntaxError => write!(f, "Syntax error"),
ParseErrorKind::MultipleTextSelectors => write!(f, "Multiple text query directives"),
ParseErrorKind::ElementAfterTextSelector => write!(f, "Element query after text query"),
}
}
}
#[derive(Debug, Clone)]
pub struct ParseError {
pub kind: ParseErrorKind,
pub message: String,
pub line: usize,
pub column: usize,
pub recovery_hint: Option<String>,
}
impl ParseError {
#[allow(dead_code)]
pub fn new(
kind: ParseErrorKind,
message: String,
line: usize,
column: usize,
recovery_hint: Option<String>,
) -> Self {
ParseError {
kind,
message,
line,
column,
recovery_hint,
}
}
pub fn unexpected_token(expected: &str, found: &str, line: usize, column: usize) -> Self {
ParseError {
kind: ParseErrorKind::UnexpectedToken,
message: format!("Expected {} but found {}", expected, found),
line,
column,
recovery_hint: Some(format!("Please check if {} is missing here", expected)),
}
}
pub fn syntax_error(msg: &str, line: usize, column: usize) -> Self {
ParseError {
kind: ParseErrorKind::SyntaxError,
message: msg.to_string(),
line,
column,
recovery_hint: None,
}
}
pub fn invalid_selector_value(value: &str, line: usize, column: usize) -> Self {
ParseError {
kind: ParseErrorKind::InvalidSelectorValue,
message: format!("Invalid selector value: {}", value),
line,
column,
recovery_hint: Some("Please check if the selector value format is correct".to_string()),
}
}
pub fn nesting_too_deep(max_depth: usize, line: usize, column: usize) -> Self {
ParseError {
kind: ParseErrorKind::NestingTooDeep,
message: format!("Expression nesting exceeds maximum depth ({})", max_depth),
line,
column,
recovery_hint: Some("Please simplify the expression, reduce nesting levels".to_string()),
}
}
pub fn multiple_text_selectors(line: usize, column: usize) -> Self {
ParseError {
kind: ParseErrorKind::MultipleTextSelectors,
message: "Query operation can only contain one text query directive".to_string(),
line,
column,
recovery_hint: Some("Please remove extra text query directives or separate them with set operations (+, *, -)".to_string()),
}
}
pub fn element_after_text_selector(line: usize, column: usize) -> Self {
ParseError {
kind: ParseErrorKind::ElementAfterTextSelector,
message: "Element query directives cannot appear after text query directives".to_string(),
line,
column,
recovery_hint: Some("Please place element query directives before text query directives".to_string()),
}
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Parse error (line {}, column {}): {} - {}",
self.line, self.column, self.kind, self.message
)?;
if let Some(hint) = &self.recovery_hint {
write!(f, "\nHint: {}", hint)?;
}
Ok(())
}
}
impl Error for ParseError {}