2018-11-04 09:45:22 -06:00
|
|
|
use std::fmt;
|
|
|
|
|
2018-11-05 11:38:34 -06:00
|
|
|
use crate::{TextRange, TextUnit};
|
2018-11-04 09:45:22 -06:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct SyntaxError {
|
2018-11-05 11:38:34 -06:00
|
|
|
kind: SyntaxErrorKind,
|
|
|
|
location: Location,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub enum Location {
|
|
|
|
Offset(TextUnit),
|
|
|
|
Range(TextRange),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<Location> for TextUnit {
|
|
|
|
fn into(self) -> Location {
|
|
|
|
Location::Offset(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<Location> for TextRange {
|
|
|
|
fn into(self) -> Location {
|
|
|
|
Location::Range(self)
|
|
|
|
}
|
2018-11-04 09:45:22 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SyntaxError {
|
2018-11-05 11:38:34 -06:00
|
|
|
pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError {
|
2018-11-05 15:29:33 -06:00
|
|
|
SyntaxError {
|
|
|
|
kind,
|
|
|
|
location: loc.into(),
|
|
|
|
}
|
2018-11-05 11:38:34 -06:00
|
|
|
}
|
|
|
|
|
2018-11-07 04:35:33 -06:00
|
|
|
pub fn kind(&self) -> SyntaxErrorKind {
|
|
|
|
self.kind.clone()
|
|
|
|
}
|
|
|
|
|
2018-11-05 11:38:34 -06:00
|
|
|
pub fn location(&self) -> Location {
|
|
|
|
self.location.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn offset(&self) -> TextUnit {
|
|
|
|
match self.location {
|
|
|
|
Location::Offset(offset) => offset,
|
|
|
|
Location::Range(range) => range.start(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_offset(mut self, plus_offset: TextUnit) -> SyntaxError {
|
|
|
|
self.location = match self.location {
|
|
|
|
Location::Range(range) => Location::Range(range + plus_offset),
|
2018-11-05 15:29:33 -06:00
|
|
|
Location::Offset(offset) => Location::Offset(offset + plus_offset),
|
2018-11-05 11:38:34 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SyntaxError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
self.kind.fmt(f)
|
2018-11-04 09:45:22 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub enum SyntaxErrorKind {
|
|
|
|
ParseError(ParseError),
|
2018-11-07 04:35:33 -06:00
|
|
|
UnescapedCodepoint,
|
2018-11-04 09:45:22 -06:00
|
|
|
EmptyChar,
|
|
|
|
UnclosedChar,
|
2018-11-08 08:42:00 -06:00
|
|
|
OverlongChar,
|
2018-11-11 13:27:00 -06:00
|
|
|
EmptyByte,
|
|
|
|
UnclosedByte,
|
|
|
|
OverlongByte,
|
|
|
|
ByteOutOfRange,
|
|
|
|
UnescapedByte,
|
|
|
|
EmptyByteEscape,
|
|
|
|
InvalidByteEscape,
|
|
|
|
TooShortByteCodeEscape,
|
|
|
|
MalformedByteCodeEscape,
|
|
|
|
UnicodeEscapeForbidden,
|
2018-11-04 09:45:22 -06:00
|
|
|
EmptyAsciiEscape,
|
|
|
|
InvalidAsciiEscape,
|
2018-11-06 10:05:06 -06:00
|
|
|
TooShortAsciiCodeEscape,
|
|
|
|
AsciiCodeEscapeOutOfRange,
|
|
|
|
MalformedAsciiCodeEscape,
|
|
|
|
UnclosedUnicodeEscape,
|
|
|
|
MalformedUnicodeEscape,
|
|
|
|
EmptyUnicodeEcape,
|
|
|
|
OverlongUnicodeEscape,
|
|
|
|
UnicodeEscapeOutOfRange,
|
2018-11-08 08:42:00 -06:00
|
|
|
UnclosedString,
|
2018-12-27 06:03:18 -06:00
|
|
|
InvalidSuffix,
|
2018-11-04 09:45:22 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct ParseError(pub String);
|
|
|
|
|
|
|
|
impl fmt::Display for SyntaxErrorKind {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
use self::SyntaxErrorKind::*;
|
|
|
|
match self {
|
2018-11-07 04:35:33 -06:00
|
|
|
UnescapedCodepoint => write!(f, "This codepoint should always be escaped"),
|
2018-11-04 09:45:22 -06:00
|
|
|
EmptyAsciiEscape => write!(f, "Empty escape sequence"),
|
|
|
|
InvalidAsciiEscape => write!(f, "Invalid escape sequence"),
|
|
|
|
EmptyChar => write!(f, "Empty char literal"),
|
|
|
|
UnclosedChar => write!(f, "Unclosed char literal"),
|
2018-11-08 08:42:00 -06:00
|
|
|
OverlongChar => write!(f, "Char literal should be one character long"),
|
2018-11-11 13:27:00 -06:00
|
|
|
EmptyByte => write!(f, "Empty byte literal"),
|
|
|
|
UnclosedByte => write!(f, "Unclosed byte literal"),
|
|
|
|
OverlongByte => write!(f, "Byte literal should be one character long"),
|
|
|
|
ByteOutOfRange => write!(f, "Byte should be a valid ASCII character"),
|
|
|
|
UnescapedByte => write!(f, "This byte should always be escaped"),
|
|
|
|
EmptyByteEscape => write!(f, "Empty escape sequence"),
|
|
|
|
InvalidByteEscape => write!(f, "Invalid escape sequence"),
|
|
|
|
TooShortByteCodeEscape => write!(f, "Escape sequence should have two digits"),
|
|
|
|
MalformedByteCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"),
|
2018-11-11 14:00:31 -06:00
|
|
|
UnicodeEscapeForbidden => write!(
|
|
|
|
f,
|
|
|
|
"Unicode escapes are not allowed in byte literals or byte strings"
|
|
|
|
),
|
2018-11-06 10:05:06 -06:00
|
|
|
TooShortAsciiCodeEscape => write!(f, "Escape sequence should have two digits"),
|
2018-11-07 04:41:42 -06:00
|
|
|
AsciiCodeEscapeOutOfRange => {
|
|
|
|
write!(f, "Escape sequence should be between \\x00 and \\x7F")
|
|
|
|
}
|
2018-11-06 10:05:06 -06:00
|
|
|
MalformedAsciiCodeEscape => write!(f, "Escape sequence should be a hexadecimal number"),
|
|
|
|
UnclosedUnicodeEscape => write!(f, "Missing `}}`"),
|
|
|
|
MalformedUnicodeEscape => write!(f, "Malformed unicode escape sequence"),
|
|
|
|
EmptyUnicodeEcape => write!(f, "Empty unicode escape sequence"),
|
2018-11-07 04:41:42 -06:00
|
|
|
OverlongUnicodeEscape => {
|
|
|
|
write!(f, "Unicode escape sequence should have at most 6 digits")
|
|
|
|
}
|
2018-11-06 10:05:06 -06:00
|
|
|
UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"),
|
2018-11-08 08:42:00 -06:00
|
|
|
UnclosedString => write!(f, "Unclosed string literal"),
|
2018-12-27 06:03:18 -06:00
|
|
|
InvalidSuffix => write!(f, "Invalid literal suffix"),
|
2018-11-04 09:45:22 -06:00
|
|
|
ParseError(msg) => write!(f, "{}", msg.0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|