mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
REFACTOR: Error handling to use BuildError throughout.
Also removed more extraneous error output. Contributes toward issue #45
This commit is contained in:
parent
e5f406d4e9
commit
85f239a566
@ -159,8 +159,7 @@ fn test_assert_just_keyword_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert ",
|
||||
vec![
|
||||
Regex::new(r"line: 1, column: 1").unwrap(),
|
||||
Regex::new(r"Expected Tuple \{ok=<bool>, desc=<str>\}: at <eval> line: 1, column: 8")
|
||||
Regex::new(r"Expected Tuple \{ok=<bool>, desc=<str>\} at <eval> line: 1, column: 8")
|
||||
.unwrap(),
|
||||
],
|
||||
);
|
||||
@ -171,10 +170,9 @@ fn test_assert_partial_tuple_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert {",
|
||||
vec![
|
||||
Regex::new(r"line: 1, column: 1").unwrap(),
|
||||
Regex::new(r"Expected Tuple \{ok=<bool>, desc=<str>\}: at <eval> line: 1, column: 8")
|
||||
Regex::new(r"Expected Tuple \{ok=<bool>, desc=<str>\} at <eval> line: 1, column: 8")
|
||||
.unwrap(),
|
||||
Regex::new(r"Expected \(\}\) but got \(\): at <eval> line: 1, column: 9").unwrap(),
|
||||
Regex::new(r"Expected \(\}\) but got \(\) at <eval> line: 1, column: 9").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -227,10 +225,7 @@ fn test_assert_partial_tuple_bad_desc_compile_failures() {
|
||||
fn test_import_missing_path_compile_failure() {
|
||||
assert_build_failure(
|
||||
"import ;",
|
||||
vec![
|
||||
Regex::new(r"Expected import path: at <eval> line: 1, column: 8").unwrap(),
|
||||
Regex::new(r"Not a String: at <eval> line: 1, column: 8").unwrap(),
|
||||
],
|
||||
vec![Regex::new(r"Expected import path at <eval> line: 1, column: 8").unwrap()],
|
||||
)
|
||||
}
|
||||
|
||||
@ -238,10 +233,7 @@ fn test_import_missing_path_compile_failure() {
|
||||
fn test_import_path_not_a_string_compile_failure() {
|
||||
assert_build_failure(
|
||||
"import 1;",
|
||||
vec![
|
||||
Regex::new(r"Expected import path: at <eval> line: 1, column: 8").unwrap(),
|
||||
Regex::new(r"Not a String: at <eval> line: 1, column: 8").unwrap(),
|
||||
],
|
||||
vec![Regex::new(r"Expected import path at <eval> line: 1, column: 8").unwrap()],
|
||||
)
|
||||
}
|
||||
|
||||
@ -250,7 +242,7 @@ fn test_binary_operator_missing_operand_compile_failure() {
|
||||
assert_build_failure(
|
||||
"1 +",
|
||||
vec![
|
||||
Regex::new(r"Missing operand for binary expression: at <eval> line: 1, column: 4")
|
||||
Regex::new(r"Missing operand for binary expression at <eval> line: 1, column: 4")
|
||||
.unwrap(),
|
||||
],
|
||||
)
|
||||
@ -427,7 +419,6 @@ fn test_out_missing_type_compile_failure() {
|
||||
"out",
|
||||
vec![
|
||||
Regex::new(r"Expected converter name").unwrap(),
|
||||
Regex::new(r"Not a Bareword").unwrap(),
|
||||
Regex::new(r"at <eval> line: 1, column: 4").unwrap(),
|
||||
],
|
||||
)
|
||||
|
@ -328,16 +328,7 @@ where
|
||||
Some(val) => Ok(val),
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let cause = Box::new(simple_error::SimpleError::new(err));
|
||||
Err(error::BuildError::with_pos(
|
||||
"Unable to parse input",
|
||||
error::ErrorType::ParseError,
|
||||
(&input).into(),
|
||||
)
|
||||
.wrap_cause(cause)
|
||||
.to_boxed())
|
||||
}
|
||||
Err(err) => Err(Box::new(err)),
|
||||
}
|
||||
}
|
||||
|
||||
|
60
src/error.rs
60
src/error.rs
@ -145,48 +145,28 @@ impl error::Error for BuildError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StackPrinter<C: FilePositioned> {
|
||||
pub err: abortable_parser::Error<C>,
|
||||
impl<'a, C> std::convert::From<abortable_parser::Error<C>> for BuildError
|
||||
where
|
||||
C: FilePositioned + 'a,
|
||||
C: abortable_parser::Offsetable + Debug,
|
||||
{
|
||||
fn from(e: abortable_parser::Error<C>) -> BuildError {
|
||||
BuildError::from(&e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: FilePositioned> StackPrinter<C> {
|
||||
pub fn render(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut curr_err = Some(&self.err);
|
||||
let mut tabstop = "";
|
||||
loop {
|
||||
match curr_err {
|
||||
// our exit condition;
|
||||
None => break,
|
||||
Some(err) => {
|
||||
let context = err.get_context();
|
||||
let file = match context.file() {
|
||||
Some(ref pb) => pb.to_string_lossy().to_string(),
|
||||
None => "<eval>".to_string(),
|
||||
};
|
||||
writeln!(
|
||||
w,
|
||||
"{}{}: at {} line: {}, column: {}",
|
||||
tabstop,
|
||||
err.get_msg(),
|
||||
file,
|
||||
context.line(),
|
||||
context.column(),
|
||||
)?;
|
||||
tabstop = "\t";
|
||||
curr_err = err.get_cause();
|
||||
if curr_err.is_some() {
|
||||
writeln!(w, "Caused by:")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, C> std::convert::From<&'a abortable_parser::Error<C>> for BuildError
|
||||
where
|
||||
C: FilePositioned + 'a,
|
||||
C: abortable_parser::Offsetable + Debug,
|
||||
{
|
||||
fn from(e: &'a abortable_parser::Error<C>) -> BuildError {
|
||||
let ctx = e.get_context();
|
||||
let position = Position::new(ctx.line(), ctx.column(), ctx.get_offset());
|
||||
let err = BuildError::with_pos(e.get_msg(), ErrorType::ParseError, position);
|
||||
match e.get_cause() {
|
||||
None => err,
|
||||
Some(cause) => err.wrap_cause(Box::new(BuildError::from(cause))),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: FilePositioned> fmt::Display for StackPrinter<C> {
|
||||
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.render(w)
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use abortable_parser::{Error, Peekable, Result};
|
||||
|
||||
use self::precedence::op_expression;
|
||||
use crate::ast::*;
|
||||
use crate::error::StackPrinter;
|
||||
use crate::error::BuildError;
|
||||
use crate::iter::OffsetStrIter;
|
||||
use crate::tokenizer::*;
|
||||
|
||||
@ -857,7 +857,7 @@ fn statement(i: SliceIter<Token>) -> Result<SliceIter<Token>, Statement> {
|
||||
pub fn parse<'a>(
|
||||
input: OffsetStrIter<'a>,
|
||||
comment_map: Option<&mut CommentMap>,
|
||||
) -> std::result::Result<Vec<Statement>, String> {
|
||||
) -> std::result::Result<Vec<Statement>, BuildError> {
|
||||
match tokenize(input.clone(), comment_map) {
|
||||
Ok(tokenized) => {
|
||||
let mut out = Vec::new();
|
||||
@ -871,20 +871,17 @@ pub fn parse<'a>(
|
||||
}
|
||||
match statement(i.clone()) {
|
||||
Result::Abort(e) => {
|
||||
let ctx_err = StackPrinter { err: e };
|
||||
return Err(format!("{}", ctx_err));
|
||||
return Err(BuildError::from(e));
|
||||
}
|
||||
Result::Fail(e) => {
|
||||
let ctx_err = StackPrinter { err: e };
|
||||
return Err(format!("{}", ctx_err));
|
||||
return Err(BuildError::from(e));
|
||||
}
|
||||
Result::Incomplete(_ei) => {
|
||||
let err = abortable_parser::Error::new(
|
||||
"Unexpected end of parse input",
|
||||
Box::new(i.clone()),
|
||||
);
|
||||
let ctx_err = StackPrinter { err: err };
|
||||
return Err(format!("{}", ctx_err));
|
||||
return Err(BuildError::from(err));
|
||||
}
|
||||
Result::Complete(rest, stmt) => {
|
||||
out.push(stmt);
|
||||
|
@ -260,11 +260,7 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec<Elemen
|
||||
// if we have successfully parsed an element and an operator then
|
||||
// failing to parse a second expression is an abort since we know
|
||||
// for sure now that the next expression is supposed to be there.
|
||||
let err = Error::caused_by(
|
||||
"Missing operand for binary expression",
|
||||
Box::new(e),
|
||||
Box::new(_i),
|
||||
);
|
||||
let err = Error::new("Missing operand for binary expression", Box::new(_i));
|
||||
return Result::Abort(err);
|
||||
}
|
||||
return Result::Fail(e);
|
||||
|
@ -20,7 +20,7 @@ use abortable_parser::iter::SliceIter;
|
||||
use abortable_parser::{Error, Result};
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::error::StackPrinter;
|
||||
use crate::error::BuildError;
|
||||
use crate::iter::OffsetStrIter;
|
||||
|
||||
pub type CommentGroup = Vec<Token>;
|
||||
@ -466,7 +466,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
||||
pub fn tokenize<'a>(
|
||||
input: OffsetStrIter<'a>,
|
||||
mut comment_map: Option<&mut CommentMap>,
|
||||
) -> std::result::Result<Vec<Token>, String> {
|
||||
) -> std::result::Result<Vec<Token>, BuildError> {
|
||||
let mut out = Vec::new();
|
||||
let mut i = input.clone();
|
||||
let mut comment_group = Vec::new();
|
||||
@ -477,28 +477,15 @@ pub fn tokenize<'a>(
|
||||
}
|
||||
match token(i.clone()) {
|
||||
Result::Abort(e) => {
|
||||
let err = abortable_parser::Error::caused_by(
|
||||
"Invalid Token encountered",
|
||||
Box::new(e),
|
||||
Box::new(i.clone()),
|
||||
);
|
||||
let ctx_err = StackPrinter { err: err };
|
||||
return Err(format!("{}", ctx_err));
|
||||
return Err(BuildError::from(e));
|
||||
}
|
||||
Result::Fail(e) => {
|
||||
let err = abortable_parser::Error::caused_by(
|
||||
"Invalid Token encountered",
|
||||
Box::new(e),
|
||||
Box::new(i.clone()),
|
||||
);
|
||||
let ctx_err = StackPrinter { err: err };
|
||||
return Err(format!("{}", ctx_err));
|
||||
return Err(BuildError::from(e));
|
||||
}
|
||||
Result::Incomplete(_offset) => {
|
||||
let err =
|
||||
abortable_parser::Error::new("Invalid Token encountered", Box::new(i.clone()));
|
||||
let ctx_err = StackPrinter { err: err };
|
||||
return Err(format!("{}", ctx_err));
|
||||
return Err(BuildError::from(err));
|
||||
}
|
||||
Result::Complete(rest, tok) => {
|
||||
i = rest;
|
||||
|
Loading…
x
Reference in New Issue
Block a user