1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
use thiserror::Error;

use crate::parser::{Error as ParseError, LSpan};

/// Error with a location info.
pub trait LocatedError {
    /// get error happened location in source input.
    fn location(&self) -> (usize, usize);
}

/// Error type for [compile][super::compile] function.
///
/// Display this error in `{}` formatter will show a error message with detailed reason.
/// So usually you don't need check variants.
#[derive(Debug, PartialEq, Eq, Error)]
pub enum Error<'a, GE> {
    /// Parsing step failed, usually means there is invalid syntax in source string
    #[error("parse failed: {0}")]
    Parse(ParseError<'a>),

    /// Invalid or unsupported tag.
    #[error("unsupported tag: {0}")]
    Tag(LSpan<'a>),

    /// Generating step failed, see document of generator type for detail.
    #[error("generator failed: {0}")]
    Gen(GE),
}

impl<'a, GE: LocatedError> LocatedError for Error<'a, GE> {
    fn location(&self) -> (usize, usize) {
        match self {
            Self::Parse(e) => e.location(),
            Self::Tag(span) => (span.extra, span.get_column()),
            Self::Gen(e) => e.location(),
        }
    }
}

impl<'a, GE> From<ParseError<'a>> for Error<'a, GE> {
    fn from(e: ParseError<'a>) -> Self {
        Self::Parse(e)
    }
}