librashader_naga/front/glsl/
error.rs

1use super::token::TokenValue;
2use crate::{proc::ConstantEvaluatorError, Span};
3use pp_rs::token::PreprocessorError;
4use std::borrow::Cow;
5use thiserror::Error;
6
7fn join_with_comma(list: &[ExpectedToken]) -> String {
8    let mut string = "".to_string();
9    for (i, val) in list.iter().enumerate() {
10        string.push_str(&val.to_string());
11        match i {
12            i if i == list.len() - 1 => {}
13            i if i == list.len() - 2 => string.push_str(" or "),
14            _ => string.push_str(", "),
15        }
16    }
17    string
18}
19
20/// One of the expected tokens returned in [`InvalidToken`](ErrorKind::InvalidToken).
21#[derive(Debug, PartialEq)]
22pub enum ExpectedToken {
23    /// A specific token was expected.
24    Token(TokenValue),
25    /// A type was expected.
26    TypeName,
27    /// An identifier was expected.
28    Identifier,
29    /// An integer literal was expected.
30    IntLiteral,
31    /// A float literal was expected.
32    FloatLiteral,
33    /// A boolean literal was expected.
34    BoolLiteral,
35    /// The end of file was expected.
36    Eof,
37}
38impl From<TokenValue> for ExpectedToken {
39    fn from(token: TokenValue) -> Self {
40        ExpectedToken::Token(token)
41    }
42}
43impl std::fmt::Display for ExpectedToken {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        match *self {
46            ExpectedToken::Token(ref token) => write!(f, "{token:?}"),
47            ExpectedToken::TypeName => write!(f, "a type"),
48            ExpectedToken::Identifier => write!(f, "identifier"),
49            ExpectedToken::IntLiteral => write!(f, "integer literal"),
50            ExpectedToken::FloatLiteral => write!(f, "float literal"),
51            ExpectedToken::BoolLiteral => write!(f, "bool literal"),
52            ExpectedToken::Eof => write!(f, "end of file"),
53        }
54    }
55}
56
57/// Information about the cause of an error.
58#[derive(Debug, Error)]
59#[cfg_attr(test, derive(PartialEq))]
60pub enum ErrorKind {
61    /// Whilst parsing as encountered an unexpected EOF.
62    #[error("Unexpected end of file")]
63    EndOfFile,
64    /// The shader specified an unsupported or invalid profile.
65    #[error("Invalid profile: {0}")]
66    InvalidProfile(String),
67    /// The shader requested an unsupported or invalid version.
68    #[error("Invalid version: {0}")]
69    InvalidVersion(u64),
70    /// Whilst parsing an unexpected token was encountered.
71    ///
72    /// A list of expected tokens is also returned.
73    #[error("Expected {}, found {0:?}", join_with_comma(.1))]
74    InvalidToken(TokenValue, Vec<ExpectedToken>),
75    /// A specific feature is not yet implemented.
76    ///
77    /// To help prioritize work please open an issue in the github issue tracker
78    /// if none exist already or react to the already existing one.
79    #[error("Not implemented: {0}")]
80    NotImplemented(&'static str),
81    /// A reference to a variable that wasn't declared was used.
82    #[error("Unknown variable: {0}")]
83    UnknownVariable(String),
84    /// A reference to a type that wasn't declared was used.
85    #[error("Unknown type: {0}")]
86    UnknownType(String),
87    /// A reference to a non existent member of a type was made.
88    #[error("Unknown field: {0}")]
89    UnknownField(String),
90    /// An unknown layout qualifier was used.
91    ///
92    /// If the qualifier does exist please open an issue in the github issue tracker
93    /// if none exist already or react to the already existing one to help
94    /// prioritize work.
95    #[error("Unknown layout qualifier: {0}")]
96    UnknownLayoutQualifier(String),
97    /// Unsupported matrix of the form matCx2
98    ///
99    /// Our IR expects matrices of the form matCx2 to have a stride of 8 however
100    /// matrices in the std140 layout have a stride of at least 16
101    #[error("unsupported matrix of the form matCx2 in std140 block layout")]
102    UnsupportedMatrixTypeInStd140,
103    /// A variable with the same name already exists in the current scope.
104    #[error("Variable already declared: {0}")]
105    VariableAlreadyDeclared(String),
106    /// A semantic error was detected in the shader.
107    #[error("{0}")]
108    SemanticError(Cow<'static, str>),
109    /// An error was returned by the preprocessor.
110    #[error("{0:?}")]
111    PreprocessorError(PreprocessorError),
112    /// The parser entered an illegal state and exited
113    ///
114    /// This obviously is a bug and as such should be reported in the github issue tracker
115    #[error("Internal error: {0}")]
116    InternalError(&'static str),
117}
118
119impl From<ConstantEvaluatorError> for ErrorKind {
120    fn from(err: ConstantEvaluatorError) -> Self {
121        ErrorKind::SemanticError(err.to_string().into())
122    }
123}
124
125/// Error returned during shader parsing.
126#[derive(Debug, Error)]
127#[error("{kind}")]
128#[cfg_attr(test, derive(PartialEq))]
129pub struct Error {
130    /// Holds the information about the error itself.
131    pub kind: ErrorKind,
132    /// Holds information about the range of the source code where the error happened.
133    pub meta: Span,
134}