use std::path::PathBuf;
use anyhow::Context;
use chumsky::{Parser as _, extra::SimpleState};
use crate::{
dsl::{error::DslError, parser::config},
process::Rule,
};
mod error;
pub mod ast;
pub mod lexer;
#[cfg(test)]
pub mod lexer_tests;
pub mod parser;
#[cfg(test)]
mod parser_tests;
pub mod resolver;
pub struct File {
pub file_name: String,
pub contents: String,
pub lexer_spans: Option<Vec<logos::Span>>,
}
impl File {
pub fn new<P: AsRef<std::path::Path>>(path: P) -> anyhow::Result<Self> {
let path = path.as_ref();
let input_str = std::fs::read_to_string(path)?;
Ok(Self {
contents: input_str,
file_name: path.to_str().unwrap().to_owned(),
lexer_spans: None,
})
}
pub fn parse_to_rules(&mut self) -> anyhow::Result<Vec<Rule>> {
let tokens = lexer::process_tokens(self).map_err(|err| {
err.iter().for_each(|err_in| err_in.print_error(self));
anyhow::format_err!("Lexing error.")
})?;
let (only_tokens, only_spans): (Vec<lexer::Token>, Vec<logos::Span>) =
tokens.into_iter().unzip();
self.lexer_spans = Some(only_spans.clone());
let mut state = SimpleState::from(&only_spans[..]);
let res = config().parse_with_state(&only_tokens, &mut state);
if res.has_errors() {
res.errors().for_each(|err| {
err.print_error(self);
});
return Err(anyhow::format_err!("Parsing error."));
}
if res.has_output() {
let config = res.output().unwrap().clone();
let rules = config.to_rules().map_err(|err| {
err.print_error(self);
anyhow::format_err!("Resolution error.")
})?;
Ok(rules)
} else {
Err(anyhow::format_err!("No output from parser."))
}
}
}