mod context;
pub(crate) mod grammar;
mod lexer;
mod parser;
mod source;
mod tree;
use std::{
path::{Path, PathBuf},
sync::Arc,
};
pub use lexer::TokenSet;
pub use source::{FileSystemResolver, SourceLoadError, SourceResolver};
pub use tree::ParseTree;
pub(crate) use context::{IncludeStatement, ParseContext};
pub(crate) use parser::Parser;
pub(crate) use source::{FileId, Source, SourceList, SourceMap};
use crate::{DiagnosticSet, GlyphMap};
pub fn parse_root_file(
path: impl Into<PathBuf>,
glyph_map: Option<&GlyphMap>,
project_root: Option<PathBuf>,
) -> Result<(ParseTree, DiagnosticSet), SourceLoadError> {
let path = path.into();
let project_root =
project_root.unwrap_or_else(|| path.parent().map(PathBuf::from).unwrap_or_default());
let resolver = source::FileSystemResolver::new(project_root);
parse_root(path, glyph_map, Box::new(resolver))
}
pub fn parse_root(
path: PathBuf,
glyph_map: Option<&GlyphMap>,
resolver: Box<dyn SourceResolver>,
) -> Result<(ParseTree, DiagnosticSet), SourceLoadError> {
context::ParseContext::parse(path, glyph_map, resolver).map(|ctx| ctx.generate_parse_tree())
}
pub fn parse_string(text: impl Into<Arc<str>>) -> (ParseTree, DiagnosticSet) {
const SRC_NAME: &str = "parse::parse_string";
let text = text.into();
parse_root(
SRC_NAME.into(),
None,
Box::new(move |s: &Path| {
if s == Path::new(SRC_NAME) {
Ok(text.clone())
} else {
Err(SourceLoadError::new(
s.to_path_buf(),
"parse_string cannot handle imports",
))
}
}),
)
.unwrap()
}
#[cfg(test)]
pub(crate) fn parse_node(text: &str, parser_fn: impl FnOnce(&mut Parser)) -> crate::Node {
let mut sink = crate::token_tree::AstSink::new(text, FileId::CURRENT_FILE, None);
let mut parser = Parser::new(text, &mut sink);
parser_fn(&mut parser);
let (root, _errs, _) = sink.finish();
root
}