Catch illegal variable names.
This commit is contained in:
parent
372321dfe3
commit
2c90fea764
46
src/error.rs
46
src/error.rs
@ -18,6 +18,8 @@ pub enum LexError {
|
||||
MalformedChar(String),
|
||||
/// Error in the script text.
|
||||
InputError(String),
|
||||
/// An identifier is in an invalid format.
|
||||
MalformedIdentifier(String),
|
||||
}
|
||||
|
||||
impl Error for LexError {}
|
||||
@ -29,6 +31,9 @@ impl fmt::Display for LexError {
|
||||
Self::MalformedEscapeSequence(s) => write!(f, "Invalid escape sequence: '{}'", s),
|
||||
Self::MalformedNumber(s) => write!(f, "Invalid number: '{}'", s),
|
||||
Self::MalformedChar(s) => write!(f, "Invalid character: '{}'", s),
|
||||
Self::MalformedIdentifier(s) => {
|
||||
write!(f, "Variable name is not in a legal format: '{}'", s)
|
||||
}
|
||||
Self::InputError(s) => write!(f, "{}", s),
|
||||
Self::UnterminatedString => write!(f, "Open string is not terminated"),
|
||||
}
|
||||
@ -51,20 +56,27 @@ pub enum ParseErrorType {
|
||||
/// An open `{` is missing the corresponding closing `}`.
|
||||
MissingRightBrace(String),
|
||||
/// An open `[` is missing the corresponding closing `]`.
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
MissingRightBracket(String),
|
||||
/// An expression in function call arguments `()` has syntax error.
|
||||
MalformedCallExpr(String),
|
||||
/// An expression in indexing brackets `[]` has syntax error.
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
MalformedIndexExpr(String),
|
||||
/// Invalid expression assigned to constant.
|
||||
ForbiddenConstantExpr(String),
|
||||
/// Missing a variable name after the `let` keyword.
|
||||
VarExpectsIdentifier,
|
||||
/// Missing a variable name after the `let`, `const` or `for` keywords.
|
||||
VariableExpected,
|
||||
/// A `for` statement is missing the `in` keyword.
|
||||
MissingIn,
|
||||
/// Defining a function `fn` in an appropriate place (e.g. inside another function).
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
WrongFnDefinition,
|
||||
/// Missing a function name after the `fn` keyword.
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
FnMissingName,
|
||||
/// A function definition is missing the parameters list. Wrapped value is the function name.
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
FnMissingParams(String),
|
||||
/// Assignment to an inappropriate LHS (left-hand-side) expression.
|
||||
AssignmentToInvalidLHS,
|
||||
@ -102,13 +114,19 @@ impl ParseError {
|
||||
ParseErrorType::MissingRightParen(_) => "Expecting ')'",
|
||||
ParseErrorType::MissingLeftBrace => "Expecting '{'",
|
||||
ParseErrorType::MissingRightBrace(_) => "Expecting '}'",
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
ParseErrorType::MissingRightBracket(_) => "Expecting ']'",
|
||||
ParseErrorType::MalformedCallExpr(_) => "Invalid expression in function call arguments",
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
ParseErrorType::MalformedIndexExpr(_) => "Invalid index in indexing expression",
|
||||
ParseErrorType::ForbiddenConstantExpr(_) => "Expecting a constant",
|
||||
ParseErrorType::VarExpectsIdentifier => "Expecting name of a variable",
|
||||
ParseErrorType::MissingIn => "Expecting 'in'",
|
||||
ParseErrorType::VariableExpected => "Expecting name of a variable",
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
ParseErrorType::FnMissingName => "Expecting name in function declaration",
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
ParseErrorType::FnMissingParams(_) => "Expecting parameters in function declaration",
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
ParseErrorType::WrongFnDefinition => "Function definitions must be at top level and cannot be inside a block or another function",
|
||||
ParseErrorType::AssignmentToInvalidLHS => "Cannot assign to this expression",
|
||||
ParseErrorType::AssignmentToCopy => "Cannot assign to this expression because it will only be changing a copy of the value",
|
||||
@ -122,21 +140,31 @@ impl Error for ParseError {}
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {
|
||||
ParseErrorType::BadInput(ref s)
|
||||
| ParseErrorType::MalformedIndexExpr(ref s)
|
||||
| ParseErrorType::MalformedCallExpr(ref s) => {
|
||||
ParseErrorType::BadInput(ref s) | ParseErrorType::MalformedCallExpr(ref s) => {
|
||||
write!(f, "{}", if s.is_empty() { self.desc() } else { s })?
|
||||
}
|
||||
ParseErrorType::ForbiddenConstantExpr(ref s) => {
|
||||
write!(f, "Expecting a constant to assign to '{}'", s)?
|
||||
}
|
||||
ParseErrorType::UnknownOperator(ref s) => write!(f, "{}: '{}'", self.desc(), s)?,
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
ParseErrorType::MalformedIndexExpr(ref s) => {
|
||||
write!(f, "{}", if s.is_empty() { self.desc() } else { s })?
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
ParseErrorType::FnMissingParams(ref s) => {
|
||||
write!(f, "Expecting parameters for function '{}'", s)?
|
||||
}
|
||||
ParseErrorType::MissingRightParen(ref s)
|
||||
| ParseErrorType::MissingRightBrace(ref s)
|
||||
| ParseErrorType::MissingRightBracket(ref s) => write!(f, "{} for {}", self.desc(), s)?,
|
||||
|
||||
ParseErrorType::MissingRightParen(ref s) | ParseErrorType::MissingRightBrace(ref s) => {
|
||||
write!(f, "{} for {}", self.desc(), s)?
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
ParseErrorType::MissingRightBracket(ref s) => write!(f, "{} for {}", self.desc(), s)?,
|
||||
|
||||
ParseErrorType::AssignmentToConstant(ref s) if s.is_empty() => {
|
||||
write!(f, "{}", self.desc())?
|
||||
}
|
||||
|
@ -882,10 +882,11 @@ impl<'a> TokenIterator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let out: String = result.iter().collect();
|
||||
let has_letter = result.iter().any(char::is_ascii_alphabetic);
|
||||
let identifier: String = result.iter().collect();
|
||||
|
||||
return Some((
|
||||
match out.as_str() {
|
||||
match identifier.as_str() {
|
||||
"true" => Token::True,
|
||||
"false" => Token::False,
|
||||
"let" => Token::Let,
|
||||
@ -903,7 +904,9 @@ impl<'a> TokenIterator<'a> {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
"fn" => Token::Fn,
|
||||
|
||||
_ => Token::Identifier(out),
|
||||
_ if has_letter => Token::Identifier(identifier),
|
||||
|
||||
_ => Token::LexError(LERR::MalformedIdentifier(identifier)),
|
||||
},
|
||||
pos,
|
||||
));
|
||||
@ -1904,14 +1907,17 @@ fn parse_for<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, ParseE
|
||||
|
||||
let name = match input.next() {
|
||||
Some((Token::Identifier(s), _)) => s,
|
||||
Some((_, pos)) => return Err(ParseError::new(PERR::VarExpectsIdentifier, pos)),
|
||||
None => return Err(ParseError::new(PERR::VarExpectsIdentifier, Position::eof())),
|
||||
Some((Token::LexError(s), pos)) => {
|
||||
return Err(ParseError::new(PERR::BadInput(s.to_string()), pos))
|
||||
}
|
||||
Some((_, pos)) => return Err(ParseError::new(PERR::VariableExpected, pos)),
|
||||
None => return Err(ParseError::new(PERR::VariableExpected, Position::eof())),
|
||||
};
|
||||
|
||||
match input.next() {
|
||||
Some((Token::In, _)) => {}
|
||||
Some((_, pos)) => return Err(ParseError::new(PERR::VarExpectsIdentifier, pos)),
|
||||
None => return Err(ParseError::new(PERR::VarExpectsIdentifier, Position::eof())),
|
||||
Some((Token::In, _)) => (),
|
||||
Some((_, pos)) => return Err(ParseError::new(PERR::MissingIn, pos)),
|
||||
None => return Err(ParseError::new(PERR::MissingIn, Position::eof())),
|
||||
}
|
||||
|
||||
let expr = parse_expr(input)?;
|
||||
@ -1932,8 +1938,11 @@ fn parse_var<'a>(
|
||||
|
||||
let name = match input.next() {
|
||||
Some((Token::Identifier(s), _)) => s,
|
||||
Some((_, pos)) => return Err(ParseError::new(PERR::VarExpectsIdentifier, pos)),
|
||||
None => return Err(ParseError::new(PERR::VarExpectsIdentifier, Position::eof())),
|
||||
Some((Token::LexError(s), pos)) => {
|
||||
return Err(ParseError::new(PERR::BadInput(s.to_string()), pos))
|
||||
}
|
||||
Some((_, pos)) => return Err(ParseError::new(PERR::VariableExpected, pos)),
|
||||
None => return Err(ParseError::new(PERR::VariableExpected, Position::eof())),
|
||||
};
|
||||
|
||||
if matches!(input.peek(), Some(&(Token::Equals, _))) {
|
||||
|
Loading…
Reference in New Issue
Block a user