#![warn(missing_docs)]
#![forbid(unsafe_code)]
use ast::Schema;
use ir::SchemaIr;
pub mod analysis;
pub mod ast;
pub mod bool_expr;
pub mod diagnostic;
mod error;
pub mod formatter;
pub mod ir;
mod lexer;
pub mod parser;
mod span;
pub mod sql_expr;
mod token;
mod validator;
pub mod visitor;
pub use analysis::{
analyze, completion, completion_with_analysis, goto_definition, goto_definition_with_analysis,
hover, hover_with_analysis, semantic_tokens, AnalysisResult, CompletionItem, CompletionKind,
HoverInfo, SemanticKind, SemanticToken,
};
pub use ast::ComputedKind;
pub use diagnostic::{Diagnostic, Severity};
pub use error::{Result, SchemaError};
pub use formatter::format_schema;
pub use lexer::Lexer;
pub use parser::Parser;
pub use span::{Position, Span};
pub use token::{Token, TokenKind};
pub use validator::validate_schema;
#[derive(Debug, Clone)]
pub struct ParsedSchema {
pub ast: Schema,
pub recovered_errors: Vec<SchemaError>,
}
#[derive(Debug, Clone)]
pub struct ValidatedSchema {
pub ast: Schema,
pub ir: SchemaIr,
}
fn lex_source(source: &str) -> Result<Vec<Token>> {
let mut lexer = Lexer::new(source);
let mut tokens = Vec::new();
loop {
let token = lexer.next_token()?;
let is_eof = matches!(token.kind, TokenKind::Eof);
tokens.push(token);
if is_eof {
break;
}
}
Ok(tokens)
}
pub fn parse_schema_source_with_recovery(source: &str) -> Result<ParsedSchema> {
let tokens = lex_source(source)?;
let mut parser = Parser::new(&tokens, source);
let ast = parser.parse_schema()?;
let recovered_errors = parser.take_errors();
Ok(ParsedSchema {
ast,
recovered_errors,
})
}
pub fn parse_schema_source(source: &str) -> Result<Schema> {
let parsed = parse_schema_source_with_recovery(source)?;
if let Some(error) = parsed.recovered_errors.into_iter().next() {
return Err(error);
}
Ok(parsed.ast)
}
pub fn validate_schema_source(source: &str) -> Result<ValidatedSchema> {
let ast = parse_schema_source(source)?;
let ir = validate_schema(ast.clone())?;
Ok(ValidatedSchema { ast, ir })
}
pub fn resolve_env_url(raw: &str) -> std::result::Result<String, String> {
if raw.starts_with("env(") && raw.ends_with(')') {
let var = &raw[4..raw.len() - 1];
std::env::var(var).map_err(|_| format!("environment variable '{}' is not set", var))
} else {
Ok(raw.to_string())
}
}