Refine position display in error messages.

This commit is contained in:
Stephen Chung
2020-06-12 18:04:16 +08:00
parent 6cc27eb9f4
commit 9d91349513
12 changed files with 256 additions and 238 deletions

View File

@@ -1,7 +1,7 @@
//! Module containing error definitions for the evaluation process.
use crate::any::Dynamic;
use crate::error::ParseError;
use crate::error::ParseErrorType;
use crate::parser::INT;
use crate::token::Position;
@@ -23,7 +23,7 @@ use crate::stdlib::path::PathBuf;
#[derive(Debug)]
pub enum EvalAltResult {
/// Syntax error.
ErrorParsing(ParseError),
ErrorParsing(ParseErrorType, Position),
/// Error reading from a script file. Wrapped value is the path of the script file.
///
@@ -101,7 +101,7 @@ impl EvalAltResult {
#[cfg(not(feature = "no_std"))]
Self::ErrorReadingScriptFile(_, _, _) => "Cannot read from script file",
Self::ErrorParsing(p) => p.desc(),
Self::ErrorParsing(p, _) => p.desc(),
Self::ErrorInFunctionCall(_, _, _) => "Error in called function",
Self::ErrorFunctionNotFound(_, _) => "Function not found",
Self::ErrorBooleanArgMismatch(_, _) => "Boolean operator expects boolean operands",
@@ -153,95 +153,89 @@ impl Error for EvalAltResult {}
impl fmt::Display for EvalAltResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let desc = self.desc();
let pos = self.position();
match self {
#[cfg(not(feature = "no_std"))]
Self::ErrorReadingScriptFile(path, pos, err) if pos.is_none() => {
write!(f, "{} '{}': {}", desc, path.display(), err)
}
#[cfg(not(feature = "no_std"))]
Self::ErrorReadingScriptFile(path, pos, err) => {
write!(f, "{} '{}': {} ({})", desc, path.display(), err, pos)
Self::ErrorReadingScriptFile(path, _, err) => {
write!(f, "{} '{}': {}", desc, path.display(), err)?
}
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
Self::ErrorParsing(p, _) => write!(f, "Syntax error: {}", p)?,
Self::ErrorInFunctionCall(s, err, pos) => {
write!(f, "Error in call to function '{}' ({}): {}", s, pos, err)
Self::ErrorInFunctionCall(s, err, _) => {
write!(f, "Error in call to function '{}' : {}", s, err)?
}
Self::ErrorFunctionNotFound(s, pos)
| Self::ErrorVariableNotFound(s, pos)
| Self::ErrorModuleNotFound(s, pos) => write!(f, "{}: '{}' ({})", desc, s, pos),
Self::ErrorFunctionNotFound(s, _)
| Self::ErrorVariableNotFound(s, _)
| Self::ErrorModuleNotFound(s, _) => write!(f, "{}: '{}'", desc, s)?,
Self::ErrorDotExpr(s, pos) if !s.is_empty() => write!(f, "{} {} ({})", desc, s, pos),
Self::ErrorDotExpr(s, _) if !s.is_empty() => write!(f, "{} {}", desc, s)?,
Self::ErrorIndexingType(_, pos)
| Self::ErrorNumericIndexExpr(pos)
| Self::ErrorStringIndexExpr(pos)
| Self::ErrorImportExpr(pos)
| Self::ErrorLogicGuard(pos)
| Self::ErrorFor(pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorInExpr(pos)
| Self::ErrorDotExpr(_, pos)
| Self::ErrorTooManyOperations(pos)
| Self::ErrorTooManyModules(pos)
| Self::ErrorStackOverflow(pos)
| Self::ErrorTerminated(pos) => write!(f, "{} ({})", desc, pos),
Self::ErrorIndexingType(_, _)
| Self::ErrorNumericIndexExpr(_)
| Self::ErrorStringIndexExpr(_)
| Self::ErrorImportExpr(_)
| Self::ErrorLogicGuard(_)
| Self::ErrorFor(_)
| Self::ErrorAssignmentToUnknownLHS(_)
| Self::ErrorInExpr(_)
| Self::ErrorDotExpr(_, _)
| Self::ErrorTooManyOperations(_)
| Self::ErrorTooManyModules(_)
| Self::ErrorStackOverflow(_)
| Self::ErrorTerminated(_) => write!(f, "{}", desc)?,
Self::ErrorRuntime(s, pos) => {
write!(f, "{} ({})", if s.is_empty() { desc } else { s }, pos)
Self::ErrorRuntime(s, _) => write!(f, "{}", if s.is_empty() { desc } else { s })?,
Self::ErrorAssignmentToConstant(s, _) => write!(f, "{}: '{}'", desc, s)?,
Self::ErrorMismatchOutputType(s, _) => write!(f, "{}: {}", desc, s)?,
Self::ErrorArithmetic(s, _) => write!(f, "{}", s)?,
Self::ErrorLoopBreak(_, _) => write!(f, "{}", desc)?,
Self::Return(_, _) => write!(f, "{}", desc)?,
Self::ErrorBooleanArgMismatch(op, _) => {
write!(f, "{} operator expects boolean operands", op)?
}
Self::ErrorAssignmentToConstant(s, pos) => write!(f, "{}: '{}' ({})", desc, s, pos),
Self::ErrorMismatchOutputType(s, pos) => write!(f, "{}: {} ({})", desc, s, pos),
Self::ErrorArithmetic(s, pos) => write!(f, "{} ({})", s, pos),
Self::ErrorLoopBreak(_, pos) => write!(f, "{} ({})", desc, pos),
Self::Return(_, pos) => write!(f, "{} ({})", desc, pos),
Self::ErrorBooleanArgMismatch(op, pos) => {
write!(f, "{} operator expects boolean operands ({})", op, pos)
Self::ErrorCharMismatch(_) => write!(f, "string indexing expects a character value")?,
Self::ErrorArrayBounds(_, index, _) if *index < 0 => {
write!(f, "{}: {} < 0", desc, index)?
}
Self::ErrorCharMismatch(pos) => {
write!(f, "string indexing expects a character value ({})", pos)
}
Self::ErrorArrayBounds(_, index, pos) if *index < 0 => {
write!(f, "{}: {} < 0 ({})", desc, index, pos)
}
Self::ErrorArrayBounds(0, _, pos) => write!(f, "{} ({})", desc, pos),
Self::ErrorArrayBounds(1, index, pos) => write!(
Self::ErrorArrayBounds(0, _, _) => write!(f, "{}", desc)?,
Self::ErrorArrayBounds(1, index, _) => write!(
f,
"Array index {} is out of bounds: only one element in the array ({})",
index, pos
),
Self::ErrorArrayBounds(max, index, pos) => write!(
"Array index {} is out of bounds: only one element in the array",
index
)?,
Self::ErrorArrayBounds(max, index, _) => write!(
f,
"Array index {} is out of bounds: only {} elements in the array ({})",
index, max, pos
),
Self::ErrorStringBounds(_, index, pos) if *index < 0 => {
write!(f, "{}: {} < 0 ({})", desc, index, pos)
"Array index {} is out of bounds: only {} elements in the array",
index, max
)?,
Self::ErrorStringBounds(_, index, _) if *index < 0 => {
write!(f, "{}: {} < 0", desc, index)?
}
Self::ErrorStringBounds(0, _, pos) => write!(f, "{} ({})", desc, pos),
Self::ErrorStringBounds(1, index, pos) => write!(
Self::ErrorStringBounds(0, _, _) => write!(f, "{}", desc)?,
Self::ErrorStringBounds(1, index, _) => write!(
f,
"String index {} is out of bounds: only one character in the string ({})",
index, pos
),
Self::ErrorStringBounds(max, index, pos) => write!(
"String index {} is out of bounds: only one character in the string",
index
)?,
Self::ErrorStringBounds(max, index, _) => write!(
f,
"String index {} is out of bounds: only {} characters in the string ({})",
index, max, pos
),
"String index {} is out of bounds: only {} characters in the string",
index, max
)?,
}
}
}
impl From<ParseError> for Box<EvalAltResult> {
fn from(err: ParseError) -> Self {
Box::new(EvalAltResult::ErrorParsing(err))
// Do not write any position if None
if !pos.is_none() {
write!(f, " ({})", pos)?;
}
Ok(())
}
}
@@ -261,9 +255,8 @@ impl EvalAltResult {
#[cfg(not(feature = "no_std"))]
Self::ErrorReadingScriptFile(_, pos, _) => *pos,
Self::ErrorParsing(err) => err.position(),
Self::ErrorFunctionNotFound(_, pos)
Self::ErrorParsing(_, pos)
| Self::ErrorFunctionNotFound(_, pos)
| Self::ErrorInFunctionCall(_, _, pos)
| Self::ErrorBooleanArgMismatch(_, pos)
| Self::ErrorCharMismatch(pos)
@@ -299,9 +292,8 @@ impl EvalAltResult {
#[cfg(not(feature = "no_std"))]
Self::ErrorReadingScriptFile(_, pos, _) => *pos = new_position,
Self::ErrorParsing(err) => err.1 = new_position,
Self::ErrorFunctionNotFound(_, pos)
Self::ErrorParsing(_, pos)
| Self::ErrorFunctionNotFound(_, pos)
| Self::ErrorInFunctionCall(_, _, pos)
| Self::ErrorBooleanArgMismatch(_, pos)
| Self::ErrorCharMismatch(pos)