shannon_brush_parser/
error.rs1use crate::tokenizer;
2
3#[derive(thiserror::Error, Debug)]
5pub enum ParseError {
6 #[error("syntax error at line {} col {}", .0.line, .0.column)]
8 ParsingNear(crate::SourcePosition),
9
10 #[error("syntax error at end of input")]
12 ParsingAtEndOfInput,
13
14 #[error("{} (detected near {})", .inner, .position.as_ref().map_or_else(|| String::from("<unknown position>"), |p| std::format!("line {} col {}", p.line, p.column)))]
16 Tokenizing {
17 inner: tokenizer::TokenizerError,
19 position: Option<crate::SourcePosition>,
21 },
22}
23
24#[cfg(feature = "diagnostics")]
25#[allow(clippy::cast_sign_loss)]
26#[allow(unused)] pub mod miette {
28 use super::ParseError;
29 use miette::SourceOffset;
30
31 impl ParseError {
32 pub fn to_pretty_error(self, input: impl Into<String>) -> PrettyError {
34 let input = input.into();
35 let location = match self {
36 Self::ParsingNear(ref pos) => {
37 Some(SourceOffset::from_location(&input, pos.line, pos.column))
38 }
39 Self::Tokenizing { ref position, .. } => position
40 .as_ref()
41 .map(|p| SourceOffset::from_location(&input, p.line, p.column)),
42 Self::ParsingAtEndOfInput => {
43 Some(SourceOffset::from_location(&input, usize::MAX, usize::MAX))
44 }
45 };
46
47 PrettyError {
48 cause: self,
49 input,
50 location,
51 }
52 }
53 }
54
55 #[derive(thiserror::Error, Debug, miette::Diagnostic)]
57 #[error("Cannot parse the input script")]
58 pub struct PrettyError {
59 cause: ParseError,
60 #[source_code]
61 input: String,
62 #[label("{cause}")]
63 location: Option<SourceOffset>,
64 }
65}
66
67#[derive(Debug, thiserror::Error)]
69#[error(transparent)]
70pub struct ParseErrorLocation {
71 #[from]
72 inner: peg::error::ParseError<peg::str::LineCol>,
73}
74
75#[derive(Debug, thiserror::Error)]
77pub enum WordParseError {
78 #[error("failed to parse arithmetic expression")]
80 ArithmeticExpression(ParseErrorLocation),
81
82 #[error("failed to parse pattern")]
84 Pattern(ParseErrorLocation),
85
86 #[error("failed to parse prompt string")]
88 Prompt(ParseErrorLocation),
89
90 #[error("failed to parse parameter '{0}'")]
92 Parameter(String, ParseErrorLocation),
93
94 #[error("failed to parse for brace expansion: '{0}'")]
96 BraceExpansion(String, ParseErrorLocation),
97
98 #[error("failed to parse word '{0}'")]
100 Word(String, ParseErrorLocation),
101}
102
103#[derive(Debug, thiserror::Error)]
105#[error(transparent)]
106pub struct TestCommandParseError(#[from] peg::error::ParseError<usize>);
107
108#[derive(Debug, thiserror::Error)]
110pub enum BindingParseError {
111 #[error("unknown error while parsing key-binding: '{0}'")]
113 Unknown(String),
114
115 #[error("missing key code in key-binding")]
117 MissingKeyCode,
118}
119
120pub(crate) fn convert_peg_parse_error(
121 err: &peg::error::ParseError<usize>,
122 tokens: &[crate::Token],
123) -> ParseError {
124 let approx_token_index = err.location;
125
126 if approx_token_index < tokens.len() {
127 let token = &tokens[approx_token_index];
128 ParseError::ParsingNear((*token.location().start).clone())
129 } else {
130 ParseError::ParsingAtEndOfInput
131 }
132}