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 /// The input ended unexpectedly while parsing.
87 ///
88 /// This occurs when the parser expects more tokens but encounters
89 /// the end of the token stream.
90 #[error("unexpected end of file")]
91 UnexpectedEof,
92}
93
94/// Errors that can occur during static analysis.
95///
96/// These errors are produced by the type checker when it encounters
97/// type mismatches, undeclared variables, or other semantic issues
98/// in the query.
99#[derive(Debug, Error, Serialize)]
100pub enum AnalysisError {
101 /// A binding with the same name already exists in the current scope.
102 ///
103 /// Fields: `(line, column, binding_name)`
104 ///
105 /// This occurs when trying to declare a variable that shadows an existing
106 /// binding in the same scope, such as using the same alias for multiple
107 /// FROM sources.
108 #[error("{0}:{1}: binding '{2}' already exists")]
109 BindingAlreadyExists(u32, u32, String),
110
111 /// A variable was referenced but not declared in any accessible scope.
112 ///
113 /// Fields: `(line, column, variable_name)`
114 ///
115 /// This occurs when referencing a variable that hasn't been bound by a
116 /// FROM clause or defined in the default scope.
117 #[error("{0}:{1}: variable '{2}' is undeclared")]
118 VariableUndeclared(u32, u32, String),
119
120 /// A type mismatch occurred between expected and actual types.
121 ///
122 /// Fields: `(line, column, expected_type, actual_type)`
123 ///
124 /// This occurs when an expression has a different type than what is
125 /// required by its context (e.g., using a string where a number is expected).
126 #[error("{0}:{1}: type mismatch: expected {2:?} but got {3:?} ")]
127 TypeMismatch(u32, u32, Type, Type),
128
129 /// A record field was accessed but doesn't exist in the record type.
130 ///
131 /// Fields: `(line, column, field_name)`
132 ///
133 /// This occurs when trying to access a field that is not defined in the
134 /// record's type definition.
135 #[error("{0}:{1}: record field '{2:?}' is undeclared ")]
136 FieldUndeclared(u32, u32, String),
137
138 /// A function was called but is not declared in the scope.
139 ///
140 /// Fields: `(line, column, function_name)`
141 ///
142 /// This occurs when calling a function that is not defined in the default
143 /// scope or any accessible scope.
144 #[error("{0}:{1}: function '{2:?}' is undeclared ")]
145 FuncUndeclared(u32, u32, String),
146
147 /// Expected a record type but found a different type.
148 ///
149 /// Fields: `(line, column, actual_type)`
150 ///
151 /// This occurs when a record type is required (e.g., for field access)
152 /// but a different type was found.
153 #[error("{0}:{1}: expected record but got {2:?}")]
154 ExpectRecord(u32, u32, Type),
155
156 /// Expected a field literal but found a different expression.
157 ///
158 /// Fields: `(line, column)`
159 ///
160 /// This occurs in contexts where only a simple field reference is allowed,
161 /// such as in GROUP BY or ORDER BY clauses.
162 #[error("{0}:{1}: expected a field")]
163 ExpectFieldLiteral(u32, u32),
164
165 /// Expected a record literal but found a different expression.
166 ///
167 /// Fields: `(line, column)`
168 ///
169 /// This occurs when a record literal is required, such as in the
170 /// SELECT projection clause.
171 #[error("{0}:{1}: expected a record")]
172 ExpectRecordLiteral(u32, u32),
173}