eventql_parser/
error.rs

1//! Error types for lexical analysis and parsing.
2//!
3//! This module defines the error types that can occur during tokenization
4//! and parsing of EventQL queries. All errors include position information
5//! (line and column numbers) to help diagnose issues in query strings.
6
7use crate::{Type, token::Symbol};
8use serde::Serialize;
9use thiserror::Error;
10
11/// Top-level error type for the EventQL parser.
12///
13/// This enum wraps both lexer and parser errors, providing a unified
14/// error type for the entire parsing pipeline.
15#[derive(Debug, Error, Serialize)]
16pub enum Error {
17    /// Error during lexical analysis (tokenization).
18    #[error(transparent)]
19    Lexer(LexerError),
20
21    /// Error during syntactic analysis (parsing).
22    #[error(transparent)]
23    Parser(ParserError),
24
25    /// Error during static analysis.
26    #[error(transparent)]
27    Analysis(AnalysisError),
28}
29
30/// Errors that can occur during lexical analysis.
31///
32/// These errors are produced by the tokenizer when the input string
33/// contains invalid characters or ends unexpectedly.
34#[derive(Debug, Error, Serialize)]
35pub enum LexerError {
36    /// The input ended unexpectedly while parsing a token.
37    ///
38    /// This typically occurs when a string literal or other multi-character
39    /// token is not properly closed.
40    #[error("unexpected end of input")]
41    IncompleteInput,
42
43    /// An invalid character was encountered at the specified position.
44    ///
45    /// The tuple contains `(line_number, column_number)`.
46    #[error("{0}:{1}: invalid character")]
47    InvalidSymbol(u32, u32),
48}
49
50/// Errors that can occur during syntactic analysis.
51///
52/// These errors are produced by the parser when the token sequence
53/// does not match the expected grammar of EventQL.
54#[derive(Debug, Error, Serialize)]
55pub enum ParserError {
56    /// Expected an identifier but found something else.
57    ///
58    /// Fields: `(line, column, found_token)`
59    #[error("{0}:{1}: expected identifier but got {2}")]
60    ExpectedIdent(u32, u32, String),
61
62    #[error("{0}:{1}: missing FROM statement")]
63    MissingFromStatement(u32, u32),
64
65    /// Expected a specific keyword but found something else.
66    ///
67    /// Fields: `(line, column, expected_keyword, found_token)`
68    #[error("{0}:{1}: expected keyword {2} but got {3}")]
69    ExpectedKeyword(u32, u32, &'static str, String),
70
71    /// Expected a specific symbol but found something else.
72    ///
73    /// Fields: `(line, column, expected_symbol, found_token)`
74    /// ```
75    #[error("{0}:{1}: expected {2} but got {3}")]
76    ExpectedSymbol(u32, u32, Symbol, String),
77
78    /// An unexpected token was encountered.
79    ///
80    /// Fields: `(line, column, found_token)`
81    ///
82    /// This is a general error for tokens that don't fit the current parse context.
83    #[error("{0}:{1}: unexpected token {2}")]
84    UnexpectedToken(u32, u32, String),
85
86    /// Expected a type name but found something else.
87    ///
88    /// Fields: `(line, column, found_token)`
89    ///
90    /// This occurs when defining a type conversion operation but the left side is
91    /// not a type.
92    #[error("{0}:{1}: expected a type")]
93    ExpectedType(u32, u32),
94
95    /// The input ended unexpectedly while parsing.
96    ///
97    /// This occurs when the parser expects more tokens but encounters
98    /// the end of the token stream.
99    #[error("unexpected end of file")]
100    UnexpectedEof,
101}
102
103/// Errors that can occur during static analysis.
104///
105/// These errors are produced by the type checker when it encounters
106/// type mismatches, undeclared variables, or other semantic issues
107/// in the query.
108#[derive(Debug, Error, Serialize)]
109pub enum AnalysisError {
110    /// A binding with the same name already exists in the current scope.
111    ///
112    /// Fields: `(line, column, binding_name)`
113    ///
114    /// This occurs when trying to declare a variable that shadows an existing
115    /// binding in the same scope, such as using the same alias for multiple
116    /// FROM sources.
117    #[error("{0}:{1}: binding '{2}' already exists")]
118    BindingAlreadyExists(u32, u32, String),
119
120    /// A variable was referenced but not declared in any accessible scope.
121    ///
122    /// Fields: `(line, column, variable_name)`
123    ///
124    /// This occurs when referencing a variable that hasn't been bound by a
125    /// FROM clause or defined in the default scope.
126    #[error("{0}:{1}: variable '{2}' is undeclared")]
127    VariableUndeclared(u32, u32, String),
128
129    /// A type mismatch occurred between expected and actual types.
130    ///
131    /// Fields: `(line, column, expected_type, actual_type)`
132    ///
133    /// This occurs when an expression has a different type than what is
134    /// required by its context (e.g., using a string where a number is expected).
135    #[error("{0}:{1}: type mismatch: expected {2:?} but got {3:?} ")]
136    TypeMismatch(u32, u32, Type, Type),
137
138    /// A record field was accessed but doesn't exist in the record type.
139    ///
140    /// Fields: `(line, column, field_name)`
141    ///
142    /// This occurs when trying to access a field that is not defined in the
143    /// record's type definition.
144    #[error("{0}:{1}: record field '{2:?}' is undeclared ")]
145    FieldUndeclared(u32, u32, String),
146
147    /// A function was called but is not declared in the scope.
148    ///
149    /// Fields: `(line, column, function_name)`
150    ///
151    /// This occurs when calling a function that is not defined in the default
152    /// scope or any accessible scope.
153    #[error("{0}:{1}: function '{2:?}' is undeclared ")]
154    FuncUndeclared(u32, u32, String),
155
156    /// Expected a record type but found a different type.
157    ///
158    /// Fields: `(line, column, actual_type)`
159    ///
160    /// This occurs when a record type is required (e.g., for field access)
161    /// but a different type was found.
162    #[error("{0}:{1}: expected record but got {2:?}")]
163    ExpectRecord(u32, u32, Type),
164
165    /// Expected an array type but found a different type.
166    ///
167    /// Fields: `(line, column, actual_type)`
168    ///
169    /// This occurs when an array type is required but a different type was found.
170    #[error("{0}:{1}: expected an array but got {2:?}")]
171    ExpectArray(u32, u32, Type),
172
173    /// Expected a field literal but found a different expression.
174    ///
175    /// Fields: `(line, column)`
176    ///
177    /// This occurs in contexts where only a simple field reference is allowed,
178    /// such as in GROUP BY or ORDER BY clauses.
179    #[error("{0}:{1}: expected a field")]
180    ExpectFieldLiteral(u32, u32),
181
182    /// Expected a record literal but found a different expression.
183    ///
184    /// Fields: `(line, column)`
185    ///
186    /// This occurs when a record literal is required, such as in the
187    /// SELECT projection clause.
188    #[error("{0}:{1}: expected a record")]
189    ExpectRecordLiteral(u32, u32),
190
191    /// When a custom type (meaning a type not supported by EventQL by default) is used but
192    /// not registered in the `AnalysisOptions` custom type set.
193    #[error("{0}:{1}: unsupported custom type '{2}'")]
194    UnsupportedCustomType(u32, u32, String),
195}
196
197impl From<LexerError> for Error {
198    fn from(value: LexerError) -> Self {
199        Self::Lexer(value)
200    }
201}
202
203impl From<ParserError> for Error {
204    fn from(value: ParserError) -> Self {
205        Self::Parser(value)
206    }
207}
208
209impl From<AnalysisError> for Error {
210    fn from(value: AnalysisError) -> Self {
211        Self::Analysis(value)
212    }
213}