use crate::{
ast::{Ast, AstAlloc, typ::Type},
error::{ParseError, ParseErrors},
files::FileId,
identifier::LocIdent,
position::RawSpan,
};
use lalrpop_util::lalrpop_mod;
lalrpop_mod!(
#[allow(clippy::all)]
#[allow(unused_parens)]
#[allow(unused_imports)]
pub grammar, "/grammar.rs");
use grammar::__ToTriple;
pub mod ast;
pub mod combine;
pub mod environment;
pub mod error;
pub mod files;
pub mod identifier;
pub mod lexer;
pub mod metrics;
pub mod position;
pub mod traverse;
pub mod typ;
pub(crate) mod uniterm;
pub mod utils;
#[cfg(test)]
mod tests;
pub enum ExtendedTerm<T> {
Term(T),
ToplevelLet(LocIdent, T),
}
trait LalrpopParser<'ast, T> {
fn parse<'input, 'err, 'wcard, __TOKEN, __TOKENS>(
&self,
alloc: &'ast AstAlloc,
src_id: FileId,
errors: &'err mut Vec<
lalrpop_util::ErrorRecovery<usize, lexer::Token<'input>, self::error::ParseOrLexError>,
>,
next_wildcard_id: &'wcard mut usize,
__tokens0: __TOKENS,
) -> Result<
T,
lalrpop_util::ParseError<usize, lexer::Token<'input>, self::error::ParseOrLexError>,
>
where
__TOKEN: __ToTriple<'input, 'ast, 'err, 'wcard>,
__TOKENS: IntoIterator<Item = __TOKEN>;
}
macro_rules! generate_lalrpop_parser_impl {
($parser:ty, $output:ty) => {
impl<'ast> LalrpopParser<'ast, $output> for $parser {
fn parse<'input, 'err, 'wcard, __TOKEN, __TOKENS>(
&self,
alloc: &'ast AstAlloc,
src_id: FileId,
errors: &'err mut Vec<
lalrpop_util::ErrorRecovery<
usize,
lexer::Token<'input>,
self::error::ParseOrLexError,
>,
>,
next_wildcard_id: &'wcard mut usize,
__tokens0: __TOKENS,
) -> Result<
$output,
lalrpop_util::ParseError<usize, lexer::Token<'input>, self::error::ParseOrLexError>,
>
where
__TOKEN: __ToTriple<'input, 'ast, 'err, 'wcard>,
__TOKENS: IntoIterator<Item = __TOKEN>,
{
Self::parse(self, alloc, src_id, errors, next_wildcard_id, __tokens0)
}
}
};
}
generate_lalrpop_parser_impl!(grammar::ExtendedTermParser, ExtendedTerm<Ast<'ast>>);
generate_lalrpop_parser_impl!(grammar::TermParser, Ast<'ast>);
generate_lalrpop_parser_impl!(grammar::FixedTypeParser, Type<'ast>);
generate_lalrpop_parser_impl!(grammar::StaticFieldPathParser, Vec<LocIdent>);
generate_lalrpop_parser_impl!(
grammar::CliFieldAssignmentParser,
(Vec<LocIdent>, Ast<'ast>, RawSpan)
);
pub trait ErrorTolerantParser<'ast, T> {
fn parse_tolerant<'input>(
&self,
alloc: &'ast AstAlloc,
file_id: FileId,
lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
) -> Result<(T, ParseErrors), ParseError>;
fn parse_strict<'input>(
&self,
alloc: &'ast AstAlloc,
file_id: FileId,
lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
) -> Result<T, ParseErrors>;
}
impl<'ast, T, P> ErrorTolerantParser<'ast, T> for P
where
P: LalrpopParser<'ast, T>,
{
fn parse_tolerant<'input>(
&self,
alloc: &'ast AstAlloc,
file_id: FileId,
lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
) -> Result<(T, ParseErrors), ParseError> {
let mut parse_errors = Vec::new();
let mut next_wildcard_id = 0;
let result = self
.parse(
alloc,
file_id,
&mut parse_errors,
&mut next_wildcard_id,
lexer.map(|x| x.map_err(error::ParseOrLexError::from)),
)
.map_err(|err| ParseError::from_lalrpop(err, file_id));
let parse_errors = ParseErrors::from_recoverable(parse_errors, file_id);
match result {
Ok(t) => Ok((t, parse_errors)),
Err(e) => Err(e),
}
}
fn parse_strict<'input>(
&self,
alloc: &'ast AstAlloc,
file_id: FileId,
lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
) -> Result<T, ParseErrors> {
match self.parse_tolerant(alloc, file_id, lexer) {
Ok((t, e)) if e.no_errors() => Ok(t),
Ok((_, e)) => Err(e),
Err(e) => Err(e.into()),
}
}
}
pub trait FullyErrorTolerantParser<'ast, T> {
fn parse_fully_tolerant<'input>(
&self,
alloc: &'ast AstAlloc,
file_id: FileId,
lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
full_span: RawSpan,
) -> (T, ParseErrors);
}
impl<'ast, P> FullyErrorTolerantParser<'ast, Ast<'ast>> for P
where
P: ErrorTolerantParser<'ast, Ast<'ast>>,
{
fn parse_fully_tolerant<'input>(
&self,
alloc: &'ast AstAlloc,
file_id: FileId,
lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
full_span: RawSpan,
) -> (Ast<'ast>, ParseErrors) {
match self.parse_tolerant(alloc, file_id, lexer) {
Ok((ast, e)) => (ast, e),
Err(e) => {
let ast = alloc.parse_error(e.clone()).spanned(full_span.into());
(ast, e.into())
}
}
}
}