#![feature(entry_insert)]
use miette::Diagnostic;
use nom::combinator::all_consuming;
use nom::Finish;
use nom_locate::LocatedSpan;
use nom_supreme::error::{BaseErrorKind, ErrorTree, GenericErrorTree, StackContext};
use thiserror::Error;
use crate::ast::Span;
pub mod ast;
#[doc(hidden)]
mod deps;
pub mod parser;
pub mod translate;
pub mod validate;
#[derive(thiserror::Error, Debug, Diagnostic)]
#[error("Parse Error")]
pub struct FormattedError<'b> {
#[source_code]
src: &'b str,
#[label("{kind}")]
span: miette::SourceSpan,
kind: BaseErrorKind<&'b str, Box<dyn std::error::Error + Send + Sync + 'static>>,
#[related]
others: Vec<FormattedErrorContext<'b>>,
}
#[derive(Error, Debug, Diagnostic)]
#[error("Parse Error Context")]
pub struct FormattedErrorContext<'b> {
#[source_code]
src: &'b str,
#[label("{context}")]
span: miette::SourceSpan,
context: StackContext<&'b str>,
}
pub type MyParseError<'a> = ErrorTree<Span<'a>>;
pub type IResult<'a, T> = nom::IResult<Span<'a>, T, MyParseError<'a>>;
pub fn format_parse_error<'a>(input: &'a str, e: MyParseError<'a>) -> FormattedError<'a> {
match e {
GenericErrorTree::Base { location, kind } => {
let offset = location.location_offset().into();
FormattedError {
src: input,
span: miette::SourceSpan::new(offset, 0.into()),
kind,
others: Vec::new(),
}
}
GenericErrorTree::Stack { base, contexts } => {
let mut base = format_parse_error(input, *base);
let mut contexts: Vec<FormattedErrorContext> = contexts
.into_iter()
.map(|(location, context)| {
let offset = location.location_offset().into();
FormattedErrorContext {
src: input,
span: miette::SourceSpan::new(offset, 0.into()),
context,
}
})
.collect();
base.others.append(&mut contexts);
base
}
GenericErrorTree::Alt(alt_errors) => {
alt_errors
.into_iter()
.map(|e| format_parse_error(input, e))
.max_by_key(|formatted| formatted.others.len())
.unwrap()
}
}
}
pub trait Parse<'a>: Sized {
fn parse(input: Span<'a>) -> IResult<'a, Self>;
fn parse_from_raw(input: &'a str) -> IResult<'a, Self> {
let i = Span::new(input);
Self::parse(i)
}
fn parse_format_error(i: &'a str) -> Result<Self, FormattedError<'a>> {
let input = LocatedSpan::new(i);
match all_consuming(Self::parse)(input).finish() {
Ok((_, query)) => Ok(query),
Err(e) => Err(format_parse_error(i, e)),
}
}
}