use super::AirPos;
use crate::parser::Span;
use thiserror::Error as ThisError;
use std::num::ParseFloatError;
use std::num::ParseIntError;
use std::ops::Range;
#[derive(ThisError, Debug, Clone, PartialEq, Eq)]
pub enum LexerError {
#[error("this string literal has unclosed quote")]
UnclosedQuote(Span),
#[error("empty string aren't allowed in this position")]
EmptyString(Span),
#[error("only alphanumeric, '_', and '-' characters are allowed in this position")]
IsNotAlphanumeric(Span),
#[error("a tagged name should be non empty")]
EmptyTaggedName(Span),
#[error("a canon name should be non empty")]
EmptyCanonName(Span),
#[error("this variable or constant shouldn't have empty name")]
EmptyVariableOrConst(Span),
#[error("invalid character in lambda")]
InvalidLambda(Span),
#[error("a digit could contain only digits or one dot")]
UnallowedCharInNumber(Span),
#[error("{1}")]
ParseIntError(Span, #[source] ParseIntError),
#[error("{1}")]
ParseFloatError(Span, #[source] ParseFloatError),
#[error("{se_lambda_parser_error}")]
LambdaParserError {
span: Span,
se_lambda_parser_error: String,
},
#[error("{error_path} is an incorrect path for %last_error%, only .$.instruction, .$.msg, and .$.peer_id are allowed")]
LastErrorPathError { span: Span, error_path: String },
#[error("this float is too big, a float could contain less than 12 digits")]
TooBigFloat(Span),
#[error("leading dot without any symbols before - please write 0 if it's float or variable name if it's a lambda")]
LeadingDot(Span),
}
impl LexerError {
pub fn span(&self) -> Span {
let span = match self {
Self::UnclosedQuote(span) => span,
Self::EmptyString(span) => span,
Self::IsNotAlphanumeric(span) => span,
Self::EmptyTaggedName(span) => span,
Self::EmptyCanonName(span) => span,
Self::EmptyVariableOrConst(span) => span,
Self::InvalidLambda(span) => span,
Self::UnallowedCharInNumber(span) => span,
Self::ParseIntError(span, _) => span,
Self::ParseFloatError(span, _) => span,
Self::LambdaParserError { span, .. } => span,
Self::LastErrorPathError { span, .. } => span,
Self::TooBigFloat(span) => span,
Self::LeadingDot(span) => span,
};
*span
}
pub fn unclosed_quote(range: Range<AirPos>) -> Self {
Self::UnclosedQuote(range.into())
}
pub fn empty_string(range: Range<AirPos>) -> Self {
Self::EmptyString(range.into())
}
pub fn is_not_alphanumeric(range: Range<AirPos>) -> Self {
Self::IsNotAlphanumeric(range.into())
}
pub fn empty_tagged_name(range: Range<AirPos>) -> Self {
Self::EmptyTaggedName(range.into())
}
pub fn empty_canon_name(range: Range<AirPos>) -> Self {
Self::EmptyCanonName(range.into())
}
pub fn empty_variable_or_const(range: Range<AirPos>) -> Self {
Self::EmptyVariableOrConst(range.into())
}
pub fn invalid_lambda(range: Range<AirPos>) -> Self {
Self::InvalidLambda(range.into())
}
pub fn unallowed_char_in_number(range: Range<AirPos>) -> Self {
Self::UnallowedCharInNumber(range.into())
}
pub fn parse_int_error(range: Range<AirPos>, parse_int_error: ParseIntError) -> Self {
Self::ParseIntError(range.into(), parse_int_error)
}
pub fn parse_float_error(range: Range<AirPos>, parse_float_error: ParseFloatError) -> Self {
Self::ParseFloatError(range.into(), parse_float_error)
}
pub fn lambda_parser_error(
range: Range<AirPos>,
se_lambda_parser_error: impl Into<String>,
) -> Self {
Self::LambdaParserError {
span: range.into(),
se_lambda_parser_error: se_lambda_parser_error.into(),
}
}
pub fn last_error_path_error(range: Range<AirPos>, error_path: String) -> Self {
Self::LastErrorPathError {
span: range.into(),
error_path,
}
}
pub fn too_big_float(range: Range<AirPos>) -> Self {
Self::TooBigFloat(range.into())
}
pub fn leading_dot(range: Range<AirPos>) -> Self {
Self::LeadingDot(range.into())
}
}
use super::Token;
use crate::parser::air::__ToTriple;
use crate::parser::ParserError;
impl<'err, 'input, 'i> __ToTriple<'err, 'input, 'i>
for Result<(AirPos, Token<'input>, AirPos), LexerError>
{
#[allow(clippy::wrong_self_convention)]
fn to_triple(
value: Self,
) -> Result<
(AirPos, Token<'input>, AirPos),
lalrpop_util::ParseError<AirPos, Token<'input>, ParserError>,
> {
match value {
Ok(v) => Ok(v),
Err(error) => {
let error = ParserError::LexerError(error);
Err(lalrpop_util::ParseError::User { error })
}
}
}
}
impl From<std::convert::Infallible> for LexerError {
fn from(_: std::convert::Infallible) -> Self {
unreachable!()
}
}