orql 0.1.0

A toy SQL parser for a subset of the Oracle dialect.
Documentation
use std::fmt::Display;

use super::Location;

pub type Result<T> = std::result::Result<T, Error>;

/// [Scanner](super::Scanner) specific errors
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Error {
    pub etype: ErrorType,
    pub loc: Location,
}

/// The various types of [scanner](super::Scanner) errors
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ErrorType {
    UnexpectedEof {
        expected: Option<&'static str>,
    },
    InvalidChar {
        char: char,
        expected: Option<&'static str>,
    },
    InvalidPlaceholder {
        details: &'static str,
    },
    UnterminatedString,
    EmptyIdent,
    UnterminatedIdent,
}

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self.etype {
            ErrorType::UnexpectedEof { expected } => {
                write!(f, "Unexpected end-of-file")?;
                if let Some(expected) = expected {
                    write!(f, ", expected {expected}")?;
                }
            }
            ErrorType::InvalidChar { char, expected } => {
                write!(f, "Invalid character '{}'", char.escape_debug())?;
                if let Some(expected) = expected {
                    write!(f, ", expected {expected}")?;
                }
            }
            ErrorType::InvalidPlaceholder { details } => {
                write!(f, "Invalid placeholder; {details}")?;
            }
            ErrorType::UnterminatedString => {
                write!(f, "Unterminated string literal")?;
            }
            ErrorType::EmptyIdent => {
                write!(f, "Empty identifier")?;
            }
            ErrorType::UnterminatedIdent => {
                write!(f, "Unterminated identifier")?;
            }
        }
        write!(f, " {}", self.loc)
    }
}