Skip to main content

rhai/types/
parse_error.rs

1//! Module containing error definitions for the parsing process.
2
3use crate::tokenizer::is_valid_identifier;
4use crate::{Position, RhaiError, ERR};
5#[cfg(feature = "no_std")]
6use core_error::Error;
7#[cfg(not(feature = "no_std"))]
8use std::error::Error;
9use std::fmt;
10#[cfg(feature = "no_std")]
11use std::prelude::v1::*;
12
13/// Error encountered when tokenizing the script text.
14#[derive(Debug, Eq, PartialEq, Clone, Hash)]
15#[non_exhaustive]
16#[must_use]
17pub enum LexError {
18    /// An unexpected symbol is encountered.
19    UnexpectedInput(String),
20    /// A string literal is not terminated before a new-line or EOF.
21    UnterminatedString,
22    /// An identifier or string literal is longer than the maximum allowed length.
23    StringTooLong(usize),
24    /// An string/character/numeric escape sequence is in an invalid format.
25    MalformedEscapeSequence(String),
26    /// An numeric literal is in an invalid format.
27    MalformedNumber(String),
28    /// An character literal is in an invalid format.
29    MalformedChar(String),
30    /// An identifier is in an invalid format.
31    MalformedIdentifier(String),
32    /// Bad symbol encountered.
33    ImproperSymbol(String, String),
34    /// Runtime error occurred.
35    Runtime(String),
36}
37
38impl Error for LexError {}
39
40impl fmt::Display for LexError {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        match self {
43            Self::UnexpectedInput(s) => write!(f, "Unexpected '{s}'"),
44            Self::MalformedEscapeSequence(s) => write!(f, "Invalid escape sequence: '{s}'"),
45            Self::MalformedNumber(s) => write!(f, "Invalid number: '{s}'"),
46            Self::MalformedChar(s) => write!(f, "Invalid character: '{s}'"),
47            Self::MalformedIdentifier(s) => write!(f, "Variable name is not proper: '{s}'"),
48            Self::UnterminatedString => f.write_str("Open string is not terminated"),
49            Self::StringTooLong(max) => write!(f, "String is too long (max {max})"),
50            Self::ImproperSymbol(s, d) if d.is_empty() => {
51                write!(f, "Invalid symbol encountered: '{s}'")
52            }
53            Self::ImproperSymbol(.., d) | Self::Runtime(d) => f.write_str(d),
54        }
55    }
56}
57
58impl LexError {
59    /// Convert a [`LexError`] into a [`ParseError`].
60    #[cold]
61    #[inline(never)]
62    pub fn into_err(self, pos: Position) -> ParseError {
63        ParseError(Box::new(self.into()), pos)
64    }
65}
66
67/// Error encountered when parsing a script.
68///
69/// Some errors never appear when certain features are turned on.
70/// They still exist so that the application can turn features on and off without going through
71/// massive code changes to remove/add back enum variants in match statements.
72#[derive(Debug, Eq, PartialEq, Clone, Hash)]
73#[non_exhaustive]
74#[must_use]
75pub enum ParseErrorType {
76    /// The script ends prematurely.
77    UnexpectedEOF,
78    /// Error in the script text. Wrapped value is the lex error.
79    BadInput(LexError),
80    /// An unknown operator is encountered. Wrapped value is the operator.
81    UnknownOperator(String),
82    /// Expecting a particular token but not finding one. Wrapped values are the token and description.
83    MissingToken(String, String),
84    /// Expecting a particular symbol but not finding one. Wrapped value is the description.
85    MissingSymbol(String),
86    /// An expression in function call arguments `()` has syntax error. Wrapped value is the error
87    /// description (if any).
88    ///
89    /// # Deprecated
90    ///
91    /// This error is no longer used and will be removed in the next major version.
92    #[deprecated(
93        since = "1.16.0",
94        note = "This error variant is no longer used and will be removed in the next major version."
95    )]
96    MalformedCallExpr(String),
97    /// An expression in indexing brackets `[]` has syntax error. Wrapped value is the error
98    /// description (if any).
99    MalformedIndexExpr(String),
100    /// An expression in an `in` expression has syntax error. Wrapped value is the error description (if any).
101    ///
102    /// # Deprecated
103    ///
104    /// This error is no longer used and will be removed in the next major version.
105    #[deprecated(
106        since = "1.16.0",
107        note = "This error variant is no longer used and will be removed in the next major version."
108    )]
109    MalformedInExpr(String),
110    /// A capturing  has syntax error. Wrapped value is the error description (if any).
111    MalformedCapture(String),
112    /// A map definition has duplicated property names. Wrapped value is the property name.
113    DuplicatedProperty(String),
114    /// A `switch` case is duplicated.
115    ///
116    /// # Deprecated
117    ///
118    /// This error is no longer used and will be removed in the next major version.
119    #[deprecated(
120        since = "1.9.0",
121        note = "This error variant is no longer used and will be removed in the next major version."
122    )]
123    DuplicatedSwitchCase,
124    /// A variable name is duplicated. Wrapped value is the variable name.
125    DuplicatedVariable(String),
126    /// A numeric case of a `switch` statement is in an appropriate place.
127    WrongSwitchIntegerCase,
128    /// The default case of a `switch` statement is in an appropriate place.
129    WrongSwitchDefaultCase,
130    /// The case condition of a `switch` statement is not appropriate.
131    WrongSwitchCaseCondition,
132    /// Missing a property name for custom types and maps.
133    PropertyExpected,
134    /// Missing a variable name after the `let`, `const`, `for` or `catch` keywords.
135    VariableExpected,
136    /// Forbidden variable name.  Wrapped value is the variable name.
137    ForbiddenVariable(String),
138    /// An identifier is a reserved symbol.
139    Reserved(String),
140    /// An expression is of the wrong type.
141    /// Wrapped values are the type requested and type of the actual result.
142    MismatchedType(String, String),
143    /// Missing an expression. Wrapped value is the expression type.
144    ExprExpected(String),
145    /// Defining a doc-comment in an appropriate place (e.g. not at global level).
146    WrongDocComment,
147    /// Defining a function `fn` in an appropriate place (e.g. inside another function).
148    WrongFnDefinition,
149    /// Defining a function with a name that conflicts with an existing function.
150    /// Wrapped values are the function name and number of parameters.
151    FnDuplicatedDefinition(String, usize),
152    /// Missing a function name after the `fn` keyword.
153    FnMissingName,
154    /// A function definition is missing the parameters list. Wrapped value is the function name.
155    FnMissingParams(String),
156    /// A function definition has duplicated parameters. Wrapped values are the function name and
157    /// parameter name.
158    FnDuplicatedParam(String, String),
159    /// A function definition is missing the body. Wrapped value is the function name.
160    FnMissingBody(String),
161    /// Export statement not at global level.
162    WrongExport,
163    /// Assignment to an a constant variable. Wrapped value is the constant variable name.
164    AssignmentToConstant(String),
165    /// Assignment to an inappropriate LHS (left-hand-side) expression.
166    /// Wrapped value is the error message (if any).
167    AssignmentToInvalidLHS(String),
168    /// A variable is already defined.
169    ///
170    /// Only appears when variables shadowing is disabled.
171    VariableExists(String),
172    /// A variable is not found.
173    ///
174    /// Only appears when strict variables mode is enabled.
175    VariableUndefined(String),
176    /// An imported module is not found.
177    ///
178    /// Only appears when strict variables mode is enabled.
179    ModuleUndefined(String),
180    /// Expression exceeding the maximum levels of complexity.
181    ExprTooDeep,
182    /// Number of scripted functions over maximum limit.
183    TooManyFunctions,
184    /// Literal exceeding the maximum size. Wrapped values are the data type name and the maximum size.
185    LiteralTooLarge(String, usize),
186    /// Break statement not inside a loop.
187    LoopBreak,
188}
189
190impl fmt::Display for ParseErrorType {
191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192        match self {
193            Self::BadInput(err) => write!(f, "{err}"),
194
195            Self::UnknownOperator(s) => write!(f, "Unknown operator: '{s}'"),
196
197            Self::MalformedIndexExpr(s) if s.is_empty() => f.write_str("Invalid index in indexing expression"),
198            Self::MalformedIndexExpr(s) =>  f.write_str(s),
199
200            Self::MalformedCapture(s) if s.is_empty()  => f.write_str("Invalid capturing"),
201            Self::MalformedCapture(s) => f.write_str(s),
202
203            Self::FnDuplicatedDefinition(s, n) => {
204                write!(f, "Function {s} with ")?;
205                match n {
206                    0 => f.write_str("no parameters already exists"),
207                    1 => f.write_str("1 parameter already exists"),
208                    _ => write!(f, "{n} parameters already exists"),
209                }
210            }
211
212            Self::FnMissingBody(s) if s.is_empty()  => f.write_str("Expecting body statement block for anonymous function"),
213            Self::FnMissingBody(s) =>  write!(f, "Expecting body statement block for function {s}"),
214
215            Self::FnMissingParams(s) => write!(f, "Expecting parameters for function {s}"),
216            Self::FnDuplicatedParam(s, arg) => write!(f, "Duplicated parameter {arg} for function {s}"),
217
218            Self::DuplicatedProperty(s) => write!(f, "Duplicated property for object map literal: {s}"),
219            Self::DuplicatedVariable(s) => write!(f, "Duplicated variable name: {s}"),
220
221            Self::VariableExists(s) => write!(f, "Variable already defined: {s}"),
222            Self::VariableUndefined(s) => write!(f, "Undefined variable: {s}"),
223            Self::ModuleUndefined(s) => write!(f, "Undefined module: {s}"),
224
225            Self::MismatchedType(r, a) => write!(f, "Expecting {r}, not {a}"),
226            Self::ExprExpected(s) => write!(f, "Expecting {s} expression"),
227            Self::MissingToken(token, s) => write!(f, "Expecting '{token}' {s}"),
228
229            Self::MissingSymbol(s) if s.is_empty() => f.write_str("Expecting a symbol"),
230            Self::MissingSymbol(s) => f.write_str(s),
231
232            Self::AssignmentToConstant(s) if s.is_empty() => f.write_str("Cannot assign to a constant value"),
233            Self::AssignmentToConstant(s) =>  write!(f, "Cannot assign to constant {s}"),
234
235            Self::AssignmentToInvalidLHS(s) if s.is_empty() => f.write_str("Expression cannot be assigned to"),
236            Self::AssignmentToInvalidLHS(s) => f.write_str(s),
237
238            Self::LiteralTooLarge(typ, max) => write!(f, "{typ} exceeds the maximum limit ({max})"),
239            Self::Reserved(s) if is_valid_identifier(s) => write!(f, "'{s}' is a reserved keyword"),
240            Self::Reserved(s) => write!(f, "'{s}' is a reserved symbol"),
241            Self::UnexpectedEOF => f.write_str("Script is incomplete"),
242            Self::WrongSwitchIntegerCase => f.write_str("Numeric switch case cannot follow a range case"),
243            Self::WrongSwitchDefaultCase => f.write_str("Default switch case must be the last"),
244            Self::WrongSwitchCaseCondition => f.write_str("This switch case cannot have a condition"),
245            Self::PropertyExpected => f.write_str("Expecting name of a property"),
246            Self::VariableExpected => f.write_str("Expecting name of a variable"),
247            Self::ForbiddenVariable(s) => write!(f, "Forbidden variable name: {s}"),
248            Self::WrongFnDefinition => f.write_str("Function definitions must be at global level and cannot be inside a block or another function"),
249            Self::FnMissingName => f.write_str("Expecting function name in function declaration"),
250            Self::WrongDocComment => f.write_str("Doc-comment must be followed immediately by a function definition"),
251            Self::WrongExport => f.write_str("Export statement can only appear at global level"),
252            Self::ExprTooDeep => f.write_str("Expression exceeds maximum complexity"),
253            Self::TooManyFunctions => f.write_str("Number of functions defined exceeds maximum limit"),
254            Self::LoopBreak => f.write_str("Break statement should only be used inside a loop"),
255
256            #[allow(deprecated)]
257            Self::DuplicatedSwitchCase => f.write_str("Duplicated switch case"),
258
259            #[allow(deprecated)]
260            Self::MalformedCallExpr(s)  if s.is_empty() => f.write_str(s),
261            #[allow(deprecated)]
262            Self::MalformedCallExpr(..) => f.write_str("Invalid expression in function call arguments"),
263
264            #[allow(deprecated)]
265            Self::MalformedInExpr(s) if s.is_empty() => f.write_str("Invalid 'in' expression"),
266            #[allow(deprecated)]
267            Self::MalformedInExpr(s) =>  f.write_str(s),
268        }
269    }
270}
271
272impl From<LexError> for ParseErrorType {
273    #[cold]
274    #[inline(never)]
275    fn from(err: LexError) -> Self {
276        match err {
277            LexError::StringTooLong(max) => {
278                Self::LiteralTooLarge("Length of string".to_string(), max)
279            }
280            _ => Self::BadInput(err),
281        }
282    }
283}
284
285/// Error when parsing a script.
286#[derive(Debug, Eq, PartialEq, Clone, Hash)]
287#[must_use]
288pub struct ParseError(
289    /// Parse error type.
290    pub Box<ParseErrorType>,
291    /// [Position] of the parse error.
292    pub Position,
293);
294
295impl Error for ParseError {}
296
297impl fmt::Display for ParseError {
298    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299        fmt::Display::fmt(&self.0, f)?;
300
301        // Do not write any position if None
302        if !self.1.is_none() {
303            write!(f, " ({})", self.1)?;
304        }
305
306        Ok(())
307    }
308}
309
310impl ParseError {
311    /// Get the [type][ParseErrorType] of this parse error.
312    #[cold]
313    #[inline(never)]
314    pub const fn err_type(&self) -> &ParseErrorType {
315        &self.0
316    }
317    /// Get the [position][Position] of this parse error.
318    #[cold]
319    #[inline(never)]
320    #[must_use]
321    pub const fn position(&self) -> Position {
322        self.1
323    }
324}
325
326impl From<ParseErrorType> for RhaiError {
327    #[cold]
328    #[inline(never)]
329    fn from(err: ParseErrorType) -> Self {
330        Self::new(err.into())
331    }
332}
333
334impl From<ParseErrorType> for ERR {
335    #[cold]
336    #[inline(never)]
337    fn from(err: ParseErrorType) -> Self {
338        Self::ErrorParsing(err, Position::NONE)
339    }
340}
341
342impl From<ParseError> for RhaiError {
343    #[cold]
344    #[inline(never)]
345    fn from(err: ParseError) -> Self {
346        Self::new(err.into())
347    }
348}
349
350impl From<ParseError> for ERR {
351    #[cold]
352    #[inline(never)]
353    fn from(err: ParseError) -> Self {
354        Self::ErrorParsing(*err.0, err.1)
355    }
356}