1#![warn(missing_docs)]
49#![forbid(unsafe_code)]
50
51use ast::Schema;
52use ir::SchemaIr;
53
54pub mod analysis;
55pub mod ast;
56pub mod bool_expr;
57pub mod diagnostic;
58mod error;
59pub mod formatter;
60pub mod ir;
61mod lexer;
62pub mod parser;
63mod span;
64pub mod sql_expr;
65mod token;
66mod validator;
67pub mod visitor;
68
69pub use analysis::{
70 analyze, completion, completion_with_analysis, goto_definition, goto_definition_with_analysis,
71 hover, hover_with_analysis, semantic_tokens, AnalysisResult, CompletionItem, CompletionKind,
72 HoverInfo, SemanticKind, SemanticToken,
73};
74pub use ast::ComputedKind;
75pub use diagnostic::{Diagnostic, Severity};
76pub use error::{Result, SchemaError};
77pub use formatter::format_schema;
78pub use lexer::Lexer;
79pub use parser::Parser;
80pub use span::{Position, Span};
81pub use token::{Token, TokenKind};
82pub use validator::validate_schema;
83
84#[derive(Debug, Clone)]
86pub struct ParsedSchema {
87 pub ast: Schema,
89 pub recovered_errors: Vec<SchemaError>,
91}
92
93#[derive(Debug, Clone)]
95pub struct ValidatedSchema {
96 pub ast: Schema,
98 pub ir: SchemaIr,
100}
101
102fn lex_source(source: &str) -> Result<Vec<Token>> {
103 let mut lexer = Lexer::new(source);
104 let mut tokens = Vec::new();
105 loop {
106 let token = lexer.next_token()?;
107 let is_eof = matches!(token.kind, TokenKind::Eof);
108 tokens.push(token);
109 if is_eof {
110 break;
111 }
112 }
113 Ok(tokens)
114}
115
116pub fn parse_schema_source_with_recovery(source: &str) -> Result<ParsedSchema> {
118 let tokens = lex_source(source)?;
119 let mut parser = Parser::new(&tokens, source);
120 let ast = parser.parse_schema()?;
121 let recovered_errors = parser.take_errors();
122 Ok(ParsedSchema {
123 ast,
124 recovered_errors,
125 })
126}
127
128pub fn parse_schema_source(source: &str) -> Result<Schema> {
130 let parsed = parse_schema_source_with_recovery(source)?;
131 if let Some(error) = parsed.recovered_errors.into_iter().next() {
132 return Err(error);
133 }
134 Ok(parsed.ast)
135}
136
137pub fn validate_schema_source(source: &str) -> Result<ValidatedSchema> {
139 let ast = parse_schema_source(source)?;
140 let ir = validate_schema(ast.clone())?;
141 Ok(ValidatedSchema { ast, ir })
142}
143
144pub fn resolve_env_url(raw: &str) -> std::result::Result<String, String> {
149 if raw.starts_with("env(") && raw.ends_with(')') {
150 let var = &raw[4..raw.len() - 1];
151 std::env::var(var).map_err(|_| format!("environment variable '{}' is not set", var))
152 } else {
153 Ok(raw.to_string())
154 }
155}