ghoti_syntax/
error.rs

1use std::ops::Range;
2
3use thiserror::Error;
4
5#[derive(Debug, PartialEq, Error)]
6#[error("parse error at {start_pos}..{end_pos}: {kind}")]
7pub struct ParseError {
8    pub start_pos: usize,
9    pub end_pos: usize,
10    pub kind: ParseErrorKind,
11}
12
13impl ParseError {
14    pub fn span(&self) -> Range<usize> {
15        self.start_pos..self.end_pos
16    }
17}
18
19#[derive(Debug, PartialEq, Error)]
20pub enum ParseErrorKind {
21    #[error("invalid token")]
22    Lex,
23    #[error("unexpected token, expecting: {0}")]
24    UnexpectedToken(String),
25    #[error("unexpected EOF, expecting: {0}")]
26    UnexpectedEof(String),
27    #[error("extra tokens")]
28    ExtraToken,
29    #[error("too many dereferences")]
30    TooManyDeref,
31
32    #[error("invalid redirection port")]
33    InvalidRedirectPort,
34
35    #[error("invalid '{0}' at this location")]
36    Validation(&'static str),
37}
38
39impl ParseError {
40    pub fn new(start_pos: usize, end_pos: usize, kind: ParseErrorKind) -> Self {
41        Self {
42            start_pos,
43            end_pos,
44            kind,
45        }
46    }
47}
48
49impl<T> From<lalrpop_util::ParseError<usize, T, ParseError>> for ParseError {
50    fn from(err: lalrpop_util::ParseError<usize, T, ParseError>) -> Self {
51        use lalrpop_util::ParseError as E;
52
53        let (start_pos, end_pos, kind) = match err {
54            E::UnrecognizedEof { location, expected } => (
55                location,
56                location,
57                ParseErrorKind::UnexpectedEof(expected.join(", ")),
58            ),
59            E::UnrecognizedToken { token, expected } => (
60                token.0,
61                token.2,
62                ParseErrorKind::UnexpectedToken(expected.join(", ")),
63            ),
64            E::ExtraToken { token } => (token.0, token.2, ParseErrorKind::ExtraToken),
65            E::User { error } => return error,
66            E::InvalidToken { .. } => unreachable!(),
67        };
68
69        Self::new(start_pos, end_pos, kind)
70    }
71}