1use std::error::Error;
2use std::fmt;
3
4#[derive(Debug, Clone, PartialEq)]
6pub enum ParseErrorKind {
7 UnexpectedToken,
9
10 InvalidSelectorValue,
12
13 NestingTooDeep,
15
16 SyntaxError,
18
19 MultipleTextSelectors,
21
22 ElementAfterTextSelector,
24}
25
26impl fmt::Display for ParseErrorKind {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 ParseErrorKind::UnexpectedToken => write!(f, "Unexpected token"),
30 ParseErrorKind::InvalidSelectorValue => write!(f, "Invalid selector value"),
31 ParseErrorKind::NestingTooDeep => write!(f, "Nesting level too deep"),
32 ParseErrorKind::SyntaxError => write!(f, "Syntax error"),
33 ParseErrorKind::MultipleTextSelectors => write!(f, "Multiple text query directives"),
34 ParseErrorKind::ElementAfterTextSelector => write!(f, "Element query after text query"),
35 }
36 }
37}
38
39#[derive(Debug, Clone)]
41pub struct ParseError {
42 pub kind: ParseErrorKind,
44
45 pub message: String,
47
48 pub line: usize,
50
51 pub column: usize,
53
54 pub recovery_hint: Option<String>,
56}
57
58impl ParseError {
59 #[allow(dead_code)]
61 pub fn new(
62 kind: ParseErrorKind,
63 message: String,
64 line: usize,
65 column: usize,
66 recovery_hint: Option<String>,
67 ) -> Self {
68 ParseError {
69 kind,
70 message,
71 line,
72 column,
73 recovery_hint,
74 }
75 }
76
77 pub fn unexpected_token(expected: &str, found: &str, line: usize, column: usize) -> Self {
79 ParseError {
80 kind: ParseErrorKind::UnexpectedToken,
81 message: format!("Expected {} but found {}", expected, found),
82 line,
83 column,
84 recovery_hint: Some(format!("Please check if {} is missing here", expected)),
85 }
86 }
87
88 pub fn syntax_error(msg: &str, line: usize, column: usize) -> Self {
89 ParseError {
90 kind: ParseErrorKind::SyntaxError,
91 message: msg.to_string(),
92 line,
93 column,
94 recovery_hint: None,
95 }
96 }
97
98
99 pub fn invalid_selector_value(value: &str, line: usize, column: usize) -> Self {
101 ParseError {
102 kind: ParseErrorKind::InvalidSelectorValue,
103 message: format!("Invalid selector value: {}", value),
104 line,
105 column,
106 recovery_hint: Some("Please check if the selector value format is correct".to_string()),
107 }
108 }
109
110 pub fn nesting_too_deep(max_depth: usize, line: usize, column: usize) -> Self {
112 ParseError {
113 kind: ParseErrorKind::NestingTooDeep,
114 message: format!("Expression nesting exceeds maximum depth ({})", max_depth),
115 line,
116 column,
117 recovery_hint: Some("Please simplify the expression, reduce nesting levels".to_string()),
118 }
119 }
120
121 pub fn multiple_text_selectors(line: usize, column: usize) -> Self {
123 ParseError {
124 kind: ParseErrorKind::MultipleTextSelectors,
125 message: "Query operation can only contain one text query directive".to_string(),
126 line,
127 column,
128 recovery_hint: Some("Please remove extra text query directives or separate them with set operations (+, *, -)".to_string()),
129 }
130 }
131
132 pub fn element_after_text_selector(line: usize, column: usize) -> Self {
134 ParseError {
135 kind: ParseErrorKind::ElementAfterTextSelector,
136 message: "Element query directives cannot appear after text query directives".to_string(),
137 line,
138 column,
139 recovery_hint: Some("Please place element query directives before text query directives".to_string()),
140 }
141 }
142}
143
144impl fmt::Display for ParseError {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 write!(
147 f,
148 "Parse error (line {}, column {}): {} - {}",
149 self.line, self.column, self.kind, self.message
150 )?;
151
152 if let Some(hint) = &self.recovery_hint {
153 write!(f, "\nHint: {}", hint)?;
154 }
155
156 Ok(())
157 }
158}
159
160impl Error for ParseError {}
161