#[macro_use]
use corollary_support::*;
use std::iter;
use std::fmt::Write;
use data::position::*;
use data::node::*;
use data::position::Pos;
#[derive(Eq, Ord, PartialEq, PartialOrd, Debug)]
pub enum ErrorLevel {
LevelWarn,
LevelError,
LevelFatal,
}
pub use self::ErrorLevel::*;
impl ::std::fmt::Display for ErrorLevel {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub fn isHardError<E: Error>(e: E) -> bool {
errorLevel(e) > LevelWarn
}
#[derive(Debug)]
pub struct ErrorInfo(pub ErrorLevel, pub Position, pub Vec<String>);
pub fn mkErrorInfo(lvl: ErrorLevel, msg: String, node: NodeInfo) -> ErrorInfo {
ErrorInfo(lvl, node.into_pos(), lines(msg))
}
#[derive(Debug)]
pub struct CError(pub Box<Error>);
use std::fmt::Debug;
pub trait Error
where Self: Debug
{
fn errorInfo(self) -> ErrorInfo;
fn toError(self) -> CError;
fn fromError(c: CError) -> Option<Box<Self>> where Self: Sized;
fn changeErrorLevel(self, lvl: ErrorLevel) -> Self
where Self: Sized + Clone
{
if errorLevel(self.clone()) == lvl {
self
} else {
panic!("changeErrorLevel: not possible for {:?}", self);
}
}
}
impl Error for CError {
fn errorInfo(self) -> ErrorInfo {
unreachable!()
}
fn toError(self) -> CError {
self
}
fn fromError(c: CError) -> Option<Box<Self>> {
Some(box c)
}
fn changeErrorLevel(self, lvl: ErrorLevel) -> Self {
unreachable!()
}
}
pub fn errorPos<E: Error>(e: E) -> Position {
let ErrorInfo(_, pos, _) = e.errorInfo();
pos
}
pub fn errorLevel<E: Error>(e: E) -> ErrorLevel {
let ErrorInfo(lvl, _, _) = e.errorInfo();
lvl
}
pub fn errorMsg<E: Error>(e: E) -> Vec<String> {
let ErrorInfo(_, _, msgs) = e.errorInfo();
msgs
}
#[derive(Debug)]
pub struct UnsupportedFeature(pub String, pub Position);
pub fn unsupportedFeature<P: Pos>(msg: String, a: P) -> UnsupportedFeature {
UnsupportedFeature(msg, a.into_pos())
}
pub fn unsupportedFeature_(msg: String) -> UnsupportedFeature {
UnsupportedFeature(msg, Position::internal())
}
#[derive(Debug)]
pub struct UserError(pub ErrorInfo);
pub fn userErr(msg: String) -> UserError {
UserError(ErrorInfo(LevelError, Position::internal(), lines(msg)))
}
pub fn showError<E: Error>(short_msg: String, e: E) -> String {
showErrorInfo(short_msg, e.errorInfo())
}
pub const INDENT: &str = " ";
pub const INTERNAL_ERR_PREFIX: &str = "parser-c : Internal Error\n\
This is propably a bug, and should be reported at \
https://github.com/tcr/parser-c";
pub fn showErrorInfo(short_msg: String, ErrorInfo(level, pos, mut msgs): ErrorInfo) -> String {
let mut res = String::new();
if pos.isSource() {
write!(res, "{}:{}: (column {}) ", pos.file(), pos.row(), pos.column()).unwrap();
} else {
write!(res, "{}:: ", pos).unwrap();
}
write!(res, "[{}]", level).unwrap();
if !short_msg.is_empty() {
msgs.insert(0, short_msg);
}
if msgs.is_empty() {
internalErr("No short message or error message provided.");
}
for msg in msgs {
write!(res, "{}>>> {}\n", INDENT, msg).unwrap();
}
res
}
pub fn internalErr(msg: &str) -> ! {
let mut res = String::new();
for line in msg.split('\n') {
write!(res, "{}{}\n", INDENT, line).unwrap();
}
panic!("{}\n{}", INTERNAL_ERR_PREFIX, res);
}