orql 0.1.0

A toy SQL parser for a subset of the Oracle dialect.
Documentation
use super::*;

mod literal;
use literal::{Literal, LiteralWith};

/// Defines different rendering / "to string" formats.
enum Style {
    Default,
    Debug,
    DebugVerbose,
    WithMeta,
    DebugWithMeta,
    #[allow(dead_code)]
    DebugVerboseWithMeta,
}

fn parse_to_string<'s, P, T>(s: &'s str, style: Style, p: P) -> String
where
    P: FnOnce(&mut ParserInner<'s, DefaultTracker<'s>>) -> Result<T>,
    T: Literal<'s, Id> + LiteralWith<'s, Id>,
{
    let mut parser = ParserInner::new(Scanner::new(s), DefaultTracker::default());
    let r = p(&mut parser).and_then(|t| parser.finish().map(|meta| (t, meta)));
    match r {
        Ok((t, meta)) => match style {
            Style::Default => t.literal().to_string(),
            Style::Debug => format!("{:#}", t.literal()),
            Style::DebugVerbose => format!("{:+#}", t.literal()),
            Style::WithMeta => t.literal().with(&meta).to_string(),
            Style::DebugWithMeta => format!("{:#}", t.literal().with(&meta)),
            Style::DebugVerboseWithMeta => format!("{:+#}", t.literal().with(&meta)),
        },
        Err(e) => e.to_string(),
    }
}

/// Fully parses `s` into a single expression and returns its rendered
/// representation.
fn parse_expr_to_string(s: &str, style: Style) -> String {
    parse_to_string(s, style, |p| p.parse_expr())
}

/// Fully parses `s` into a condition and returns its rendered
/// representation.
fn parse_cond_to_string(s: &str, style: Style) -> String {
    parse_to_string(s, style, |p| p.condition_parser().parse_condition())
}

/// Fully parses `s` into a single statement and returns its rendered
/// representation.
fn parse_stmt_to_string(s: &str, style: Style) -> String {
    parse_to_string(s, style, |p| match p.parse_statements() {
        Ok(mut stmts) => {
            if stmts.len() == 1 {
                Ok(stmts.pop().expect("missing element"))
            } else {
                Err(Error::Unexpected {
                    unexpected: format!("number of statements ({})", stmts.len()).into(),
                    expected: "exactly one statement",
                    loc: (0, 0).into(),
                })
            }
        }
        Err(e) => Err(e),
    })
}

/// Parses `input` and asserts its rendered form is equal to `expected`.
macro_rules! assert_sql {
    (@ $parse_f:ident $input:expr, $expected:expr, $style:ident) => {{
        pretty_assertions::assert_eq!($crate::parser::tests::$parse_f($input, $crate::parser::tests::Style::$style), $expected)
    }};

    (stmt($input:expr), $expected:literal) => {
        assert_sql!(@ parse_stmt_to_string $input, $expected, Default)
    };
    (stmt($input:expr), debug($expected:literal)) => {
        assert_sql!(@ parse_stmt_to_string $input, $expected, Debug)
    };
    (stmt($input:expr), debug_verbose($expected:literal)) => {
        assert_sql!(@ parse_stmt_to_string $input, $expected, DebugVerbose)
    };
    (stmt($input:expr), with_meta($expected:literal)) => {
        assert_sql!(@ parse_stmt_to_string $input, $expected, WithMeta)
    };
    (stmt($input:expr), debug(with_meta($expected:literal))) => {
        assert_sql!(@ parse_stmt_to_string $input, $expected, DebugWithMeta)
    };
    (stmt($input:expr), debug_verbose(with_meta($expected:literal))) => {
        assert_sql!(@ parse_stmt_to_string $input, $expected, DebugVerboseWithMeta)
    };

    (expr($input:expr), $expected:literal) => {
        assert_sql!(@ parse_expr_to_string $input, $expected, Default)
    };
    (expr($input:expr), debug($expected:literal)) => {
        assert_sql!(@ parse_expr_to_string $input, $expected, Debug)
    };
    (expr($input:expr), debug_verbose($expected:literal)) => {
        assert_sql!(@ parse_expr_to_string $input, $expected, DebugVerbose)
    };
    (expr($input:expr), with_meta($expected:literal)) => {
        assert_sql!(@ parse_expr_to_string $input, $expected, WithMeta)
    };
    (expr($input:expr), debug(with_meta($expected:literal))) => {
        assert_sql!(@ parse_expr_to_string $input, $expected, DebugWithMeta)
    };
    (expr($input:expr), debug_verbose(with_meta($expected:literal))) => {
        assert_sql!(@ parse_expr_to_string $input, $expected, DebugVerboseWithMeta)
    };

    (cond($input:expr), $expected:literal) => {
        assert_sql!(@ parse_cond_to_string $input, $expected, Default)
    };
    (cond($input:expr), debug($expected:literal)) => {
        assert_sql!(@ parse_cond_to_string $input, $expected, Debug)
    };
    (cond($input:expr), debug_verbose($expected:literal)) => {
        assert_sql!(@ parse_cond_to_string $input, $expected, DebugVerbose)
    };
    (cond($input:expr), with_meta($expected:literal)) => {
        assert_sql!(@ parse_cond_to_string $input, $expected, WithMeta)
    };
    (cond($input:expr), debug(with_meta($expected:literal))) => {
        assert_sql!(@ parse_cond_to_string $input, $expected, DebugWithMeta)
    };
    (cond($input:expr), debug_verbose(with_meta($expected:literal))) => {
        assert_sql!(@ parse_cond_to_string $input, $expected, DebugVerboseWithMeta)
    };
}

macro_rules! let_expect {
    ($p:pat = $expr:expr) => {
        let $p = $expr else {
            panic!("expected: {}", stringify!($p),);
        };
    };
}

mod comments;
mod conditions;
mod expressions;
mod functions;
mod iter;
mod statements;

mod realworld;