use std::fmt::{Display, Formatter};
use std::io;
use crate::pretty::{
PrettyOptions, PrettyReport, PrettyTree, format_tokens, format_tree, print_report,
};
use crate::{
CellStream, Lex, NativeParseError, SourceFile, Span, Spanned, TokenStream, parse_native,
};
#[cfg(feature = "tree-sitter")]
use crate::{ParseError, parse_file};
#[derive(Debug)]
pub struct ParsedFile {
original_source: String,
cst: SourceFile,
}
impl ParsedFile {
#[cfg(feature = "tree-sitter")]
pub fn from_source(source: impl Into<String>) -> Result<Self, ParseError> {
let original_source = source.into();
let cst = parse_file(&original_source)?;
Ok(Self {
original_source,
cst,
})
}
pub fn from_source_native(source: impl Into<String>) -> Result<Self, NativeParseError> {
let original_source = source.into();
let cst = parse_native(&original_source)?;
Ok(Self {
original_source,
cst,
})
}
pub fn original_source(&self) -> &str {
&self.original_source
}
pub fn cst(&self) -> &SourceFile {
&self.cst
}
pub fn cst_mut(&mut self) -> &mut SourceFile {
&mut self.cst
}
pub fn edit(mut self, edit: impl FnOnce(&mut SourceFile)) -> Self {
edit(&mut self.cst);
self
}
pub fn into_cst(self) -> SourceFile {
self.cst
}
pub fn token_stream(&self) -> TokenStream {
self.cst.to_token_stream()
}
pub fn cell_stream(&self) -> CellStream {
CellStream::from_source_file(&self.cst)
}
pub fn to_source(&self) -> String {
self.cell_stream().to_string()
}
pub fn pretty_tokens(&self) -> String {
format_tokens(&self.token_stream(), PrettyOptions::PLAIN)
}
pub fn pretty_cst(&self) -> String {
format_tree(&self.cst.pretty_tree(), PrettyOptions::PLAIN)
}
pub fn pretty_report(&self) -> PrettyReport<'_> {
PrettyReport::new(
&self.original_source,
self.token_stream(),
self.cst.pretty_tree(),
)
}
pub fn print_pretty(&self) -> io::Result<()> {
print_report(self.pretty_report())
}
}
impl AsRef<SourceFile> for ParsedFile {
fn as_ref(&self) -> &SourceFile {
self.cst()
}
}
impl AsMut<SourceFile> for ParsedFile {
fn as_mut(&mut self) -> &mut SourceFile {
self.cst_mut()
}
}
impl Display for ParsedFile {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
self.cell_stream().fmt(formatter)
}
}
impl Spanned for ParsedFile {
fn span(&self) -> Span {
self.cst.span()
}
}
impl Lex for ParsedFile {
fn to_tokens(&self, output: &mut TokenStream) {
self.cst.to_tokens(output);
}
}