use crate::gremlin::ast::Span;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum GremlinError {
#[error("Parse error: {0}")]
Parse(#[from] ParseError),
#[error("Compile error: {0}")]
Compile(#[from] CompileError),
#[error("Execution error: {0}")]
Execution(String),
}
#[derive(Debug, Error)]
pub enum ParseError {
#[error("Syntax error at position {span:?}: {message}")]
SyntaxAt { span: Span, message: String },
#[error("Syntax error: {0}")]
Syntax(String),
#[error("Empty query")]
Empty,
#[error("Invalid literal '{value}' at {span:?}: {reason}")]
InvalidLiteral {
value: String,
span: Span,
reason: &'static str,
},
#[error("Unexpected token at {span:?}: found '{found}', expected {expected}")]
UnexpectedToken {
span: Span,
found: String,
expected: String,
},
#[error("Missing source step (query must start with g.V(), g.E(), etc.)")]
MissingSource,
#[error("Invalid step '{step}' at {span:?}: {reason}")]
InvalidStep {
step: String,
span: Span,
reason: String,
},
}
#[derive(Debug, Error)]
pub enum CompileError {
#[error("Unsupported step: {step}")]
UnsupportedStep { step: String },
#[error("Invalid arguments for {step}: {message}")]
InvalidArguments { step: String, message: String },
#[error("Type mismatch: {message}")]
TypeMismatch { message: String },
#[error("Undefined label: '{label}'")]
UndefinedLabel { label: String },
#[error("Invalid predicate: {message}")]
InvalidPredicate { message: String },
#[error("Step '{step}' requires preceding '{required}'")]
MissingPrecedingStep { step: String, required: String },
}
impl ParseError {
pub fn at(span: Span, message: impl Into<String>) -> Self {
ParseError::SyntaxAt {
span,
message: message.into(),
}
}
pub fn from_pest(error: pest::error::Error<crate::gremlin::parser::Rule>) -> Self {
ParseError::Syntax(error.to_string())
}
}