1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use ress::{tokens::Keyword, Position};
use std::fmt::{Display, Formatter, Result};
#[derive(Debug)]
pub enum Error {
    UnexpectedEoF,
    ParseAfterEoF,
    RestrictedIdent(Position),
    UnexpectedToken(Position, String),
    UnableToReinterpret(Position, String, String),
    Redecl(Position, String),
    OperationError(Position, String),
    InvalidGetterParams(Position),
    InvalidSetterParams(Position),
    NonStrictFeatureInStrictContext(Position, String),
    InvalidImportError(Position),
    InvalidExportError(Position),
    InvalidYield(Position),
    InvalidUseOfContextualKeyword(Position, String),
    TryWithNoCatchOrFinally(Position),
    InvalidCatchArg(Position),
    ThrowWithNoArg(Position),
    UnknownOptionalLabel(Position, Keyword<()>, String),
    InvalidOptionalLabel(Position),
    UseOfModuleFeatureOutsideOfModule(Position, String),
    NewLineAfterFatArrow(Position),
    StrictModeArgumentsOrEval(Position),
    InvalidSuper(Position),
    InvalidFuncPosition(Position, String),
    InvalidClassPosition(Position, String),
    ForOfInAssign(Position, String),
    ContinueOutsideOfIteration(Position),
    InvalidParameter(Position, String),
    OctalLiteral(Position),
    HtmlCommentInModule(Position),
    InvalidRegEx(Position, String),
    InvalidTrailingComma(Position),
    InvalidEscape(Position, String),
    LexicalRedecl(Position, Position, String),
    InvalidLHS(Position),
    ForOfNotSimple(Position),
    InvalidStartOfExpressionStmt(Position, String),
    DuplicateExport(Position, String),
    UndefinedExports(Vec<String>),
    ContinueOfNotIterationLabel(Position, String),
    Scanner(ress::error::Error),
    Other(Box<dyn ::std::error::Error>),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match self {
            Error::UnexpectedToken(ref pos, ref msg) => write!(f, "Unexpected Token at {}: {}", pos, msg),
            Error::UnexpectedEoF => write!(f, "Unexpectedly found the end of the file"),
            Error::ParseAfterEoF => write!(f, "Parser attempted to get the next token after finding the end of the file"),
            Error::RestrictedIdent(pos) => write!(f, "Restricted word used as identifier at {}", pos),
            Error::UnableToReinterpret(ref pos, ref from, ref to) => write!(f, "Unable to re-interpret from {} to {} at {}", from, to, pos),
            Error::Redecl(ref pos, ref ident) => write!(f, "Nested label at {} shadows parent: {}", pos, ident),
            Error::OperationError(ref pos, ref msg) => write!(f, "Invalid operation, {}: {}", pos, msg),
            Error::InvalidGetterParams(ref pos) => write!(f, "Found a getter method that takes arguments at {}, getter methods cannot take arguments", pos),
            Error::InvalidSetterParams(ref pos) => write!(f, "Found a setter method that takes more or less than 1 argument at {}, setter methods must take only one argument", pos),
            Error::InvalidYield(ref pos) => write!(f, "Yield cannot be used as an identifier at {}", pos),
            Error::NonStrictFeatureInStrictContext(ref pos, ref name) => write!(f, "Attempting to use non-strict feature {} in a strict context at {}", name, pos),
            Error::InvalidImportError(ref pos) => write!(f, "Inavlid use of es6 import syntax at {}", pos),
            Error::InvalidExportError(ref pos) => write!(f, "Inavlid use of es6 export syntax at {}", pos),
            Error::InvalidUseOfContextualKeyword(ref pos, ref ident) => write!(f, "Inavlid use of contextual keyword {} at {}", pos, ident),
            Error::TryWithNoCatchOrFinally(ref pos) => write!(f, "Try catch block must have catch or finally clause at {}", pos),
            Error::InvalidCatchArg(ref pos) => write!(f, "Inavlid parameter in catch block at {}", pos),
            Error::ThrowWithNoArg(ref pos) => write!(f, "Throw statements without an argument {}", pos),
            Error::UnknownOptionalLabel(ref pos, ref key, ref label) => write!(f, "Attempt to {0} {1} but {1} is unknown in this scope at {2}", key.to_string(), label, pos),
            Error::InvalidOptionalLabel(ref pos) => write!(f, "Attempt to break with no label is not allowed unless in an iteration or switch: {}", pos),
            Error::UseOfModuleFeatureOutsideOfModule(ref pos, ref feature) => write!(f, "Used {} at {} which is only available inside of an es6 module", feature, pos),
            Error::NewLineAfterFatArrow(ref pos) => write!(f, "New line after fat arrow at {}", pos),
            Error::StrictModeArgumentsOrEval(ref pos) => write!(f, "arguments or eval used as an identifier in strict mode near {}", pos),
            Error::InvalidFuncPosition(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
            Error::InvalidClassPosition(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
            Error::ForOfInAssign(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
            Error::InvalidSuper(ref pos) => write!(f, "Invalid use of super at {}", pos),
            Error::ContinueOutsideOfIteration(ref pos) => write!(f, "Invalid use of continue at {}", pos),
            Error::InvalidParameter(ref pos, ref msg) => write!(f, "Invalid paramter at {} -- {}", pos, msg),
            Error::OctalLiteral(ref pos) => write!(f, "Invalid use of octal literal at {}", pos),
            Error::HtmlCommentInModule(ref pos) => write!(f, "HTML Comments are not available in module code: {}", pos),
            Error::InvalidRegEx(ref pos, ref msg) => write!(f, "Invalid regular expression literal at {} -- {}", pos, msg),
            Error::InvalidTrailingComma(ref pos) => write!(f, "Invalid trailing comma at {}", pos),
            Error::InvalidEscape(ref pos, ref msg) => write!(f, "{} at {}", msg, pos),
            Error::LexicalRedecl(ref orig, ref redecl, ref id) => write!(f, "identifier {} was previously declared at {} and again at {}", id, orig, redecl),
            Error::InvalidLHS(ref pos) => write!(f, "invalid left hand side at {}", pos),
            Error::ForOfNotSimple(ref pos) => write!(f, "initializer of a for-of loop must be a simple assignment target {}", pos),
            Error::InvalidStartOfExpressionStmt(ref pos, ref token) => write!(f, "Expression statement cannot start with {} at {}", token, pos),
            Error::DuplicateExport(ref pos, ref token) => write!(f, "Found duplicate export with name {} at {}", token, pos),
            Error::UndefinedExports(ref names) => write!(f, "Undefined exports in module: {}", names.join(", ")),
            Error::ContinueOfNotIterationLabel(ref pos, ref token) => write!(f, "Label `{}` is does not label a loop, continue is invalid at {}", token, pos),
            Error::Scanner(ref e) => write!(f, "Error when tokenizing {}", e),
            Error::Other(ref e) => write!(f, "{}", e),
        }
    }
}

impl Error {
    pub fn unable_to_reinterpret(pos: Position, from: &str, to: &str) -> Self {
        Error::UnableToReinterpret(pos, from.to_owned(), to.to_owned())
    }
}

impl From<::std::io::Error> for Error {
    fn from(other: ::std::io::Error) -> Self {
        Error::Other(Box::new(other))
    }
}
impl ::std::error::Error for Error {}

impl From<ress::error::Error> for Error {
    fn from(other: ress::error::Error) -> Self {
        Error::Scanner(other)
    }
}