use crate::ast::Ast;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::document::Document;
use crate::processors::exercises::ExercisesConfig;
use crate::processors::{AstPreprocessor, AstPreprocessorConfig, PreprocessorContext};
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct Parser {
#[serde(default = "default_preprocessors")]
pub preprocessors: Vec<Box<dyn AstPreprocessorConfig>>,
#[serde(default)]
pub settings: ParserSettings,
}
fn default_preprocessors() -> Vec<Box<dyn AstPreprocessorConfig>> {
vec![Box::new(ExercisesConfig) as Box<dyn AstPreprocessorConfig>]
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct ParserSettings {
#[serde(default)]
pub solutions: bool,
#[serde(default)]
pub notebook_outputs: bool,
}
impl Parser {
pub fn parse(
&self,
doc: &Document<Ast>,
ctx: &PreprocessorContext,
) -> Result<Document<Ast>, anyhow::Error> {
let doc_ast = self.run_ast_processors(doc.clone(), ctx)?;
Ok(doc_ast)
}
pub fn run_ast_processors(
&self,
doc: Document<Ast>,
ctx: &PreprocessorContext,
) -> Result<Document<Ast>, anyhow::Error> {
let mut built = self
.preprocessors
.iter()
.map(|p| p.build(ctx, &self.settings))
.collect::<anyhow::Result<Vec<Box<dyn AstPreprocessor>>>>()?;
let doc = built.iter_mut().fold(Ok(doc), |c, ast_processor| {
c.and_then(|c| ast_processor.process(c))
})?;
Ok(doc)
}
}
#[allow(unused)]
struct HeadingNode {
id: String,
children: Vec<HeadingNode>,
}
#[derive(Error, Debug)]
pub enum ParserError {
#[error("IO Error: ")]
IoError(#[from] std::io::Error),
#[error("Error in template")]
TemplateError(#[from] tera::Error),
#[error("JSON Error: ")]
JSONError(#[from] serde_json::error::Error),
#[error("Error parsing frontmatter: ")]
FrontMatter(#[from] serde_yaml::Error),
#[error(transparent)]
ExtensionError(#[from] crate::processors::Error),
#[cfg(feature = "katex")]
#[error(transparent)]
KaTeX(#[from] katex::Error),
#[error(transparent)]
Std(#[from] Box<dyn std::error::Error>),
#[error(transparent)]
Anyhow(#[from] anyhow::Error),
}
#[cfg(test)]
mod tests {
}