mod lexer;
mod parser;
mod pretty;
pub use parser::{ParseError, ParseErrorKind};
use pretty::ScopedPrettifier;
use crate::{
ast::Query,
resolve::RuleResolver,
search::{self, SolutionIter},
universe::{RuleSet, SymbolOverlay, SymbolStore},
};
pub use self::{parser::Parser, pretty::Prettifier};
pub struct TextualUniverse {
pub symbols: SymbolStore,
pub rules: RuleSet,
}
impl TextualUniverse {
pub fn new() -> Self {
Self {
symbols: SymbolStore::new(),
rules: RuleSet::new(),
}
}
pub fn load_str(&mut self, rules: &str) -> Result<(), ParseError> {
let rules = Parser::new(&mut self.symbols).parse_rules_str(rules)?;
for rule in rules {
self.rules.insert(rule);
}
Ok(())
}
pub fn prepare_query(&self, query: &str) -> Result<UniverseQuery<'_>, ParseError> {
let symbols = SymbolOverlay::new(&self.symbols);
let mut parser = Parser::new(symbols);
let query = parser.parse_query_str(query)?;
Ok(UniverseQuery::new(parser.into_symbols(), query))
}
pub fn query_dfs(&mut self, query: &str) -> Result<SolutionIter<RuleResolver>, ParseError> {
let query = self.prepare_query(query)?;
Ok(search::query_dfs(
RuleResolver::new(&self.rules),
query.query(),
))
}
pub fn pretty(&self) -> Prettifier<SymbolStore> {
Prettifier::new(&self.symbols)
}
pub fn parse(&mut self) -> Parser<&mut SymbolStore> {
Parser::new(&mut self.symbols)
}
pub fn resolver(&self) -> RuleResolver {
RuleResolver::new(&self.rules)
}
}
impl Default for TextualUniverse {
fn default() -> Self {
Self::new()
}
}
pub struct UniverseQuery<'a> {
symbols: SymbolOverlay<'a>,
query: Query,
}
impl<'a> UniverseQuery<'a> {
pub fn new(symbols: SymbolOverlay<'a>, query: Query) -> Self {
Self { symbols, query }
}
pub fn query(&self) -> &Query {
&self.query
}
pub fn symbols(&self) -> &SymbolOverlay<'a> {
&self.symbols
}
pub fn symbols_mut(&mut self) -> &mut SymbolOverlay<'a> {
&mut self.symbols
}
pub fn pretty(&self) -> ScopedPrettifier<SymbolOverlay> {
ScopedPrettifier::new(&self.symbols, self.query().scope.as_ref())
}
}