Better convert LexError to ParseError.
This commit is contained in:
parent
b51930031b
commit
0c6a939c66
@ -2480,7 +2480,7 @@ engine.set_max_string_size(500); // allow strings only up to 500 byte
|
|||||||
engine.set_max_string_size(0); // allow unlimited string length
|
engine.set_max_string_size(0); // allow unlimited string length
|
||||||
```
|
```
|
||||||
|
|
||||||
A script attempting to create a string literal longer than the maximum will terminate with a parse error.
|
A script attempting to create a string literal longer than the maximum length will terminate with a parse error.
|
||||||
Any script operation that produces a string longer than the maximum also terminates the script with an error result.
|
Any script operation that produces a string longer than the maximum also terminates the script with an error result.
|
||||||
This check can be disabled via the [`unchecked`] feature for higher performance
|
This check can be disabled via the [`unchecked`] feature for higher performance
|
||||||
(but higher risks as well).
|
(but higher risks as well).
|
||||||
|
24
src/error.rs
24
src/error.rs
@ -22,8 +22,8 @@ pub enum LexError {
|
|||||||
MalformedChar(String),
|
MalformedChar(String),
|
||||||
/// An identifier is in an invalid format.
|
/// An identifier is in an invalid format.
|
||||||
MalformedIdentifier(String),
|
MalformedIdentifier(String),
|
||||||
/// Bad keyword encountered when tokenizing the script text.
|
/// Bad symbol encountered when tokenizing the script text.
|
||||||
ImproperKeyword(String),
|
ImproperSymbol(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for LexError {}
|
impl Error for LexError {}
|
||||||
@ -42,11 +42,18 @@ impl fmt::Display for LexError {
|
|||||||
"Length of string literal exceeds the maximum limit ({})",
|
"Length of string literal exceeds the maximum limit ({})",
|
||||||
max
|
max
|
||||||
),
|
),
|
||||||
Self::ImproperKeyword(s) => write!(f, "{}", s),
|
Self::ImproperSymbol(s) => write!(f, "{}", s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LexError {
|
||||||
|
/// Convert a `LexError` into a `ParseError`.
|
||||||
|
pub fn into_err(&self, pos: Position) -> ParseError {
|
||||||
|
ParseError(Box::new(self.into()), pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Type of error encountered when parsing a script.
|
/// Type of error encountered when parsing a script.
|
||||||
///
|
///
|
||||||
/// Some errors never appear when certain features are turned on.
|
/// Some errors never appear when certain features are turned on.
|
||||||
@ -217,6 +224,17 @@ impl fmt::Display for ParseErrorType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&LexError> for ParseErrorType {
|
||||||
|
fn from(err: &LexError) -> Self {
|
||||||
|
match err {
|
||||||
|
LexError::StringTooLong(max) => {
|
||||||
|
Self::LiteralTooLarge("Length of string literal".to_string(), *max)
|
||||||
|
}
|
||||||
|
_ => Self::BadInput(err.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error when parsing a script.
|
/// Error when parsing a script.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||||
pub struct ParseError(pub Box<ParseErrorType>, pub Position);
|
pub struct ParseError(pub Box<ParseErrorType>, pub Position);
|
||||||
|
@ -767,7 +767,7 @@ fn parse_paren_expr(
|
|||||||
// ( xxx )
|
// ( xxx )
|
||||||
(Token::RightParen, _) => Ok(expr),
|
(Token::RightParen, _) => Ok(expr),
|
||||||
// ( <error>
|
// ( <error>
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
// ( xxx ???
|
// ( xxx ???
|
||||||
(_, pos) => Err(PERR::MissingToken(
|
(_, pos) => Err(PERR::MissingToken(
|
||||||
Token::RightParen.into(),
|
Token::RightParen.into(),
|
||||||
@ -800,7 +800,7 @@ fn parse_call_expr(
|
|||||||
.into_err(settings.pos))
|
.into_err(settings.pos))
|
||||||
}
|
}
|
||||||
// id <error>
|
// id <error>
|
||||||
Token::LexError(err) => return Err(PERR::BadInput(err.to_string()).into_err(settings.pos)),
|
Token::LexError(err) => return Err(err.into_err(settings.pos)),
|
||||||
// id()
|
// id()
|
||||||
Token::RightParen => {
|
Token::RightParen => {
|
||||||
eat_token(input, Token::RightParen);
|
eat_token(input, Token::RightParen);
|
||||||
@ -880,9 +880,7 @@ fn parse_call_expr(
|
|||||||
.into_err(*pos))
|
.into_err(*pos))
|
||||||
}
|
}
|
||||||
// id(...args <error>
|
// id(...args <error>
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(*pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(*pos))
|
|
||||||
}
|
|
||||||
// id(...args ???
|
// id(...args ???
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
@ -1065,7 +1063,7 @@ fn parse_index_chain(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(*pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(*pos)),
|
||||||
(_, pos) => Err(PERR::MissingToken(
|
(_, pos) => Err(PERR::MissingToken(
|
||||||
Token::RightBracket.into(),
|
Token::RightBracket.into(),
|
||||||
"for a matching [ in this index expression".into(),
|
"for a matching [ in this index expression".into(),
|
||||||
@ -1110,9 +1108,7 @@ fn parse_array_literal(
|
|||||||
)
|
)
|
||||||
.into_err(*pos))
|
.into_err(*pos))
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(*pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(*pos))
|
|
||||||
}
|
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
Token::Comma.into(),
|
Token::Comma.into(),
|
||||||
@ -1144,9 +1140,7 @@ fn parse_map_literal(
|
|||||||
let (name, pos) = match input.next().unwrap() {
|
let (name, pos) = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => (s, pos),
|
(Token::Identifier(s), pos) => (s, pos),
|
||||||
(Token::StringConst(s), pos) => (s, pos),
|
(Token::StringConst(s), pos) => (s, pos),
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(pos))
|
|
||||||
}
|
|
||||||
(_, pos) if map.is_empty() => {
|
(_, pos) if map.is_empty() => {
|
||||||
return Err(
|
return Err(
|
||||||
PERR::MissingToken(Token::RightBrace.into(), MISSING_RBRACE.into())
|
PERR::MissingToken(Token::RightBrace.into(), MISSING_RBRACE.into())
|
||||||
@ -1164,9 +1158,7 @@ fn parse_map_literal(
|
|||||||
|
|
||||||
match input.next().unwrap() {
|
match input.next().unwrap() {
|
||||||
(Token::Colon, _) => (),
|
(Token::Colon, _) => (),
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(pos))
|
|
||||||
}
|
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
Token::Colon.into(),
|
Token::Colon.into(),
|
||||||
@ -1205,9 +1197,7 @@ fn parse_map_literal(
|
|||||||
)
|
)
|
||||||
.into_err(*pos))
|
.into_err(*pos))
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(*pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(*pos))
|
|
||||||
}
|
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(
|
return Err(
|
||||||
PERR::MissingToken(Token::RightBrace.into(), MISSING_RBRACE.into())
|
PERR::MissingToken(Token::RightBrace.into(), MISSING_RBRACE.into())
|
||||||
@ -1269,7 +1259,7 @@ fn parse_primary(
|
|||||||
Token::MapStart => parse_map_literal(input, state, settings.level_up())?,
|
Token::MapStart => parse_map_literal(input, state, settings.level_up())?,
|
||||||
Token::True => Expr::True(settings.pos),
|
Token::True => Expr::True(settings.pos),
|
||||||
Token::False => Expr::False(settings.pos),
|
Token::False => Expr::False(settings.pos),
|
||||||
Token::LexError(err) => return Err(PERR::BadInput(err.to_string()).into_err(settings.pos)),
|
Token::LexError(err) => return Err(err.into_err(settings.pos)),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(
|
return Err(
|
||||||
PERR::BadInput(format!("Unexpected '{}'", token.syntax())).into_err(settings.pos)
|
PERR::BadInput(format!("Unexpected '{}'", token.syntax())).into_err(settings.pos)
|
||||||
@ -1380,12 +1370,7 @@ fn parse_unary(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| LexError::MalformedNumber(format!("-{}", x.0)).into_err(pos))
|
||||||
PERR::BadInput(
|
|
||||||
LexError::MalformedNumber(format!("-{}", x.0)).to_string(),
|
|
||||||
)
|
|
||||||
.into_err(pos)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative float
|
// Negative float
|
||||||
@ -1990,7 +1975,7 @@ fn parse_for(
|
|||||||
// Variable name
|
// Variable name
|
||||||
(Token::Identifier(s), _) => s,
|
(Token::Identifier(s), _) => s,
|
||||||
// Bad identifier
|
// Bad identifier
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
// EOF
|
// EOF
|
||||||
(Token::EOF, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(Token::EOF, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
// Not a variable name
|
// Not a variable name
|
||||||
@ -2000,7 +1985,7 @@ fn parse_for(
|
|||||||
// for name in ...
|
// for name in ...
|
||||||
match input.next().unwrap() {
|
match input.next().unwrap() {
|
||||||
(Token::In, _) => (),
|
(Token::In, _) => (),
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(
|
return Err(
|
||||||
PERR::MissingToken(Token::In.into(), "after the iteration variable".into())
|
PERR::MissingToken(Token::In.into(), "after the iteration variable".into())
|
||||||
@ -2038,7 +2023,7 @@ fn parse_let(
|
|||||||
// let name ...
|
// let name ...
|
||||||
let (name, pos) = match input.next().unwrap() {
|
let (name, pos) = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => (s, pos),
|
(Token::Identifier(s), pos) => (s, pos),
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2109,7 +2094,7 @@ fn parse_import(
|
|||||||
// import expr as name ...
|
// import expr as name ...
|
||||||
let (name, _) = match input.next().unwrap() {
|
let (name, _) = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => (s, pos),
|
(Token::Identifier(s), pos) => (s, pos),
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2132,9 +2117,7 @@ fn parse_export(
|
|||||||
loop {
|
loop {
|
||||||
let (id, id_pos) = match input.next().unwrap() {
|
let (id, id_pos) = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => (s.clone(), pos),
|
(Token::Identifier(s), pos) => (s.clone(), pos),
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(pos))
|
|
||||||
}
|
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2189,7 +2172,7 @@ fn parse_block(
|
|||||||
// Must start with {
|
// Must start with {
|
||||||
settings.pos = match input.next().unwrap() {
|
settings.pos = match input.next().unwrap() {
|
||||||
(Token::LeftBrace, pos) => pos,
|
(Token::LeftBrace, pos) => pos,
|
||||||
(Token::LexError(err), pos) => return Err(PERR::BadInput(err.to_string()).into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(
|
return Err(PERR::MissingToken(
|
||||||
Token::LeftBrace.into(),
|
Token::LeftBrace.into(),
|
||||||
@ -2229,9 +2212,7 @@ fn parse_block(
|
|||||||
// { ... { stmt } ???
|
// { ... { stmt } ???
|
||||||
(_, _) if !need_semicolon => (),
|
(_, _) if !need_semicolon => (),
|
||||||
// { ... stmt <error>
|
// { ... stmt <error>
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(*pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(*pos))
|
|
||||||
}
|
|
||||||
// { ... stmt ???
|
// { ... stmt ???
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
// Semicolons are not optional between statements
|
// Semicolons are not optional between statements
|
||||||
@ -2380,9 +2361,7 @@ fn parse_fn(
|
|||||||
state.push((s.clone(), ScopeEntryType::Normal));
|
state.push((s.clone(), ScopeEntryType::Normal));
|
||||||
params.push((s, pos))
|
params.push((s, pos))
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(pos))
|
|
||||||
}
|
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(Token::RightParen.into(), end_err).into_err(pos))
|
return Err(PERR::MissingToken(Token::RightParen.into(), end_err).into_err(pos))
|
||||||
}
|
}
|
||||||
@ -2394,9 +2373,7 @@ fn parse_fn(
|
|||||||
(Token::Identifier(_), pos) => {
|
(Token::Identifier(_), pos) => {
|
||||||
return Err(PERR::MissingToken(Token::Comma.into(), sep_err).into_err(pos))
|
return Err(PERR::MissingToken(Token::Comma.into(), sep_err).into_err(pos))
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(pos))
|
|
||||||
}
|
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
return Err(PERR::MissingToken(Token::Comma.into(), sep_err).into_err(pos))
|
return Err(PERR::MissingToken(Token::Comma.into(), sep_err).into_err(pos))
|
||||||
}
|
}
|
||||||
@ -2567,9 +2544,7 @@ impl Engine {
|
|||||||
// { stmt } ???
|
// { stmt } ???
|
||||||
(_, _) if !need_semicolon => (),
|
(_, _) if !need_semicolon => (),
|
||||||
// stmt <error>
|
// stmt <error>
|
||||||
(Token::LexError(err), pos) => {
|
(Token::LexError(err), pos) => return Err(err.into_err(*pos)),
|
||||||
return Err(PERR::BadInput(err.to_string()).into_err(*pos))
|
|
||||||
}
|
|
||||||
// stmt ???
|
// stmt ???
|
||||||
(_, pos) => {
|
(_, pos) => {
|
||||||
// Semicolons are not optional between statements
|
// Semicolons are not optional between statements
|
||||||
|
@ -14,12 +14,12 @@ fn test_max_string_size() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
engine.compile(r#"let x = "hello, world!";"#).expect_err("should error"),
|
engine.compile(r#"let x = "hello, world!";"#).expect_err("should error"),
|
||||||
ParseError(x, _) if *x == ParseErrorType::BadInput("Length of string literal exceeds the maximum limit (10)".to_string())
|
ParseError(x, _) if *x == ParseErrorType::LiteralTooLarge("Length of string literal".to_string(), 10)
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
engine.compile(r#"let x = "朝に紅顔、暮に白骨";"#).expect_err("should error"),
|
engine.compile(r#"let x = "朝に紅顔、暮に白骨";"#).expect_err("should error"),
|
||||||
ParseError(x, _) if *x == ParseErrorType::BadInput("Length of string literal exceeds the maximum limit (10)".to_string())
|
ParseError(x, _) if *x == ParseErrorType::LiteralTooLarge("Length of string literal".to_string(), 10)
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
|
Loading…
Reference in New Issue
Block a user