mod ast;
mod builder;
mod contextual;
mod event;
mod grammar;
mod input;
mod parser;
pub use ast::*;
pub use sql_dialect_fmt_syntax::{Dialect, SyntaxKind, SyntaxNode};
pub use sql_dialect_fmt_text::LineColumn;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParseError {
pub message: String,
pub offset: usize,
pub len: usize,
pub line_column: Option<LineColumn>,
}
impl ParseError {
pub fn range(&self) -> std::ops::Range<usize> {
self.offset..self.offset + self.len
}
}
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.line_column {
Some(pos) => write!(
f,
"{} at line {}, column {} (byte {})",
self.message, pos.line, pos.column, self.offset
),
None => write!(f, "{} at byte {}", self.message, self.offset),
}
}
}
impl std::error::Error for ParseError {}
#[derive(Clone)]
pub struct Parse {
green: rowan::GreenNode,
errors: Vec<ParseError>,
}
impl Parse {
pub fn syntax(&self) -> SyntaxNode {
SyntaxNode::new_root(self.green.clone())
}
pub fn errors(&self) -> &[ParseError] {
&self.errors
}
}
pub fn parse(text: &str) -> Parse {
parse_with_dialect(text, Dialect::Snowflake)
}
pub fn parse_with_dialect(text: &str, dialect: Dialect) -> Parse {
let lexed = sql_dialect_fmt_lexer::tokenize_for_dialect(text, dialect);
parse_lexed(text, dialect, lexed)
}
#[doc(hidden)]
pub fn parse_lexed<'a>(
text: &'a str,
dialect: Dialect,
lexed: sql_dialect_fmt_lexer::Lexed<'a>,
) -> Parse {
let input = input::Input::new(lexed);
let (events, mut errors) = parser::Parser::new(&input, dialect).parse();
let line_index = sql_dialect_fmt_text::LineIndex::new(text);
for error in &mut errors {
error.line_column = Some(line_index.line_column(error.offset));
}
let green = builder::build_tree(input.all(), events);
Parse { green, errors }
}