Skip to main content

openpql_pql_parser/
error.rs

1use super::{Expected, Loc, LocInfo, ParseError, Token};
2
3/// Parse failure produced while parsing a PQL source.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum Error {
6    /// Token is not recognized by the lexer.
7    InvalidToken(LocInfo),
8    /// Input ended before the parser expected.
9    UnrecognizedEof(LocInfo, Expected),
10    /// Token is not valid in this position.
11    UnrecognizedToken(LocInfo, Expected),
12    /// Trailing token after a complete parse.
13    ExtraToken(LocInfo),
14
15    /// Selector name is not one of the supported aggregates.
16    UnrecognizedSelector(LocInfo),
17    /// `from` clause contains the same key more than once.
18    DuplicatedKeyInFrom(LocInfo),
19    /// Two selectors share the same alias.
20    DuplicatedSelectorName(LocInfo),
21    /// Numeric literal is not a valid number.
22    InvalidNumericValue(LocInfo),
23}
24
25/// LALRPOP parse error specialized for this grammar.
26pub type LalrError<'input> = ParseError<Loc, Token<'input>, Error>;
27
28/// Result alias for parser entry points.
29pub type ResultE<'input, T> = Result<T, LalrError<'input>>;
30
31pub const fn user_err<'input>(error: Error) -> LalrError<'input> {
32    ParseError::User { error }
33}
34
35impl<'input> From<LalrError<'input>> for Error {
36    fn from(err: LalrError<'input>) -> Self {
37        match err {
38            ParseError::InvalidToken { location: l } => {
39                Self::InvalidToken((l, l + 1))
40            }
41
42            ParseError::UnrecognizedEof {
43                location: l,
44                expected: v,
45            } => Self::UnrecognizedEof((l, l + 1), v),
46
47            ParseError::UnrecognizedToken {
48                token: t,
49                expected: v,
50            } => Self::UnrecognizedToken((t.0, t.2), v),
51
52            ParseError::ExtraToken { token: t } => Self::ExtraToken((t.0, t.2)),
53
54            ParseError::User { error } => error,
55        }
56    }
57}
58
59impl From<&Error> for LocInfo {
60    fn from(e: &Error) -> Self {
61        match e {
62            Error::InvalidToken(loc)
63            | Error::UnrecognizedEof(loc, _)
64            | Error::UnrecognizedToken(loc, _)
65            | Error::ExtraToken(loc)
66            | Error::UnrecognizedSelector(loc)
67            | Error::DuplicatedKeyInFrom(loc)
68            | Error::DuplicatedSelectorName(loc)
69            | Error::InvalidNumericValue(loc) => *loc,
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_into_loc() {
80        let loc = (1, 2);
81
82        assert_eq!(loc, (&Error::InvalidToken(loc)).into());
83        assert_eq!(loc, (&Error::UnrecognizedEof(loc, vec![])).into());
84        assert_eq!(loc, (&Error::UnrecognizedToken(loc, vec![])).into());
85        assert_eq!(loc, (&Error::ExtraToken(loc)).into());
86        assert_eq!(loc, (&Error::UnrecognizedSelector(loc)).into());
87        assert_eq!(loc, (&Error::DuplicatedKeyInFrom(loc)).into());
88        assert_eq!(loc, (&Error::DuplicatedSelectorName(loc)).into());
89        assert_eq!(loc, (&Error::InvalidNumericValue(loc)).into());
90    }
91
92    #[test]
93    fn test_error() {
94        let err = LalrError::ExtraToken {
95            token: (0, Token(0, "a"), 1),
96        };
97
98        assert_eq!(Error::ExtraToken((0, 1)), err.into());
99    }
100}