use crate::tokenizer;
#[derive(thiserror::Error, Debug)]
pub enum ParseError {
#[error("syntax error at line {} col {}", .0.line, .0.column)]
ParsingNear(crate::SourcePosition),
#[error("syntax error at end of input")]
ParsingAtEndOfInput,
#[error("{} (detected near {})", .inner, .position.as_ref().map_or_else(|| String::from("<unknown position>"), |p| std::format!("line {} col {}", p.line, p.column)))]
Tokenizing {
inner: tokenizer::TokenizerError,
position: Option<crate::SourcePosition>,
},
}
#[cfg(feature = "diagnostics")]
#[allow(clippy::cast_sign_loss)]
#[allow(unused)] pub mod miette {
use super::ParseError;
use miette::SourceOffset;
impl ParseError {
pub fn to_pretty_error(self, input: impl Into<String>) -> PrettyError {
let input = input.into();
let location = match self {
Self::ParsingNear(ref pos) => {
Some(SourceOffset::from_location(&input, pos.line, pos.column))
}
Self::Tokenizing { ref position, .. } => position
.as_ref()
.map(|p| SourceOffset::from_location(&input, p.line, p.column)),
Self::ParsingAtEndOfInput => {
Some(SourceOffset::from_location(&input, usize::MAX, usize::MAX))
}
};
PrettyError {
cause: self,
input,
location,
}
}
}
#[derive(thiserror::Error, Debug, miette::Diagnostic)]
#[error("Cannot parse the input script")]
pub struct PrettyError {
cause: ParseError,
#[source_code]
input: String,
#[label("{cause}")]
location: Option<SourceOffset>,
}
}
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct ParseErrorLocation {
#[from]
inner: peg::error::ParseError<peg::str::LineCol>,
}
#[derive(Debug, thiserror::Error)]
pub enum WordParseError {
#[error("failed to parse arithmetic expression")]
ArithmeticExpression(ParseErrorLocation),
#[error("failed to parse pattern")]
Pattern(ParseErrorLocation),
#[error("failed to parse prompt string")]
Prompt(ParseErrorLocation),
#[error("failed to parse parameter '{0}'")]
Parameter(String, ParseErrorLocation),
#[error("failed to parse for brace expansion: '{0}'")]
BraceExpansion(String, ParseErrorLocation),
#[error("failed to parse word '{0}'")]
Word(String, ParseErrorLocation),
}
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct TestCommandParseError(#[from] peg::error::ParseError<usize>);
#[derive(Debug, thiserror::Error)]
pub enum BindingParseError {
#[error("unknown error while parsing key-binding: '{0}'")]
Unknown(String),
#[error("missing key code in key-binding")]
MissingKeyCode,
}
pub(crate) fn convert_peg_parse_error(
err: &peg::error::ParseError<usize>,
tokens: &[crate::Token],
) -> ParseError {
let approx_token_index = err.location;
if approx_token_index < tokens.len() {
let token = &tokens[approx_token_index];
ParseError::ParsingNear((*token.location().start).clone())
} else {
ParseError::ParsingAtEndOfInput
}
}