use std::fmt::Display;
use std::fmt::Error;
use std::fmt::Formatter;
use std::ops::Index;
use symbols::Symbol;
use text::TextPosition;
use text::Utf16C;
use utils::iterable::Iterable;
pub trait ParseErrorDataTrait {
fn get_position(&self) -> TextPosition;
fn get_length(&self) -> usize;
fn get_message(&self) -> String;
}
#[derive(Copy, Clone)]
pub struct ParseErrorEndOfInput {
position: TextPosition
}
impl ParseErrorDataTrait for ParseErrorEndOfInput {
fn get_position(&self) -> TextPosition {
*(&self.position)
}
fn get_length(&self) -> usize {
0
}
fn get_message(&self) -> String {
String::from("Unexpected end of input")
}
}
impl ParseErrorEndOfInput {
pub fn new(position: TextPosition) -> ParseErrorEndOfInput {
ParseErrorEndOfInput { position }
}
}
#[derive(Copy, Clone)]
pub struct ParseErrorUnexpectedChar {
position: TextPosition,
unexpected: [Utf16C; 2]
}
impl ParseErrorDataTrait for ParseErrorUnexpectedChar {
fn get_position(&self) -> TextPosition {
*(&self.position)
}
fn get_length(&self) -> usize {
if self.unexpected[1] == 0x00 {
1
} else {
2
}
}
fn get_message(&self) -> String {
let mut result = String::new();
result.push_str("Unexpected character '");
if self.unexpected[1] == 0x00 {
result.push_str(&String::from_utf16(&self.unexpected[0..1]).unwrap());
result.push_str("' (U+");
result.push_str(&format!("{:X}", self.unexpected[0]));
} else {
let lead = self.unexpected[0] as u32;
let trail = self.unexpected[1] as u32;
let cp = ((trail - 0xDC00) | ((lead - 0xD800) << 10)) + 0x10000;
result.push_str(&String::from_utf16(&self.unexpected).unwrap());
result.push_str("' (U+");
result.push_str(&format!("{:X}", cp));
}
result.push_str(")");
result
}
}
impl ParseErrorUnexpectedChar {
pub fn new(position: TextPosition, unexpected: [Utf16C; 2]) -> ParseErrorUnexpectedChar {
ParseErrorUnexpectedChar {
position,
unexpected
}
}
}
#[derive(Copy, Clone)]
pub struct ParseErrorIncorrectEncodingSequence {
position: TextPosition,
missing_high: bool,
sequence: Utf16C
}
impl ParseErrorDataTrait for ParseErrorIncorrectEncodingSequence {
fn get_position(&self) -> TextPosition {
*(&self.position)
}
fn get_length(&self) -> usize {
1
}
fn get_message(&self) -> String {
let mut result = String::new();
result.push_str("Incorrect encoding sequence: [");
if self.missing_high {
result.push_str("<missing> ");
result.push_str("0x");
result.push_str(&format!("{:X}", self.sequence));
} else {
result.push_str("0x");
result.push_str(&format!("{:X}", self.sequence));
result.push_str(" <missing>");
}
result.push_str("]");
result
}
}
impl ParseErrorIncorrectEncodingSequence {
pub fn new(
position: TextPosition,
missing_high: bool,
sequence: Utf16C
) -> ParseErrorIncorrectEncodingSequence {
ParseErrorIncorrectEncodingSequence {
position,
missing_high,
sequence
}
}
}
#[derive(Clone)]
pub struct ParseErrorUnexpectedToken {
position: TextPosition,
length: usize,
value: String,
terminal: Symbol,
expected: Vec<Symbol>
}
impl ParseErrorDataTrait for ParseErrorUnexpectedToken {
fn get_position(&self) -> TextPosition {
*(&self.position)
}
fn get_length(&self) -> usize {
self.length
}
fn get_message(&self) -> String {
let mut result = String::new();
result.push_str("Unexpected token \"");
result.push_str(&self.value);
result.push_str("\"");
if self.expected.len() > 0 {
result.push_str("; expected: ");
for (i, x) in self.expected.iter().enumerate() {
if i != 0 {
result.push_str(", ");
}
result.push_str(x.name);
}
}
result
}
}
impl ParseErrorUnexpectedToken {
pub fn new(
position: TextPosition,
length: usize,
value: String,
terminal: Symbol,
expected: Vec<Symbol>
) -> ParseErrorUnexpectedToken {
ParseErrorUnexpectedToken {
position,
length,
value,
terminal,
expected
}
}
}
#[derive(Clone)]
pub enum ParseError {
UnexpectedEndOfInput(ParseErrorEndOfInput),
UnexpectedChar(ParseErrorUnexpectedChar),
UnexpectedToken(ParseErrorUnexpectedToken),
IncorrectUTF16NoLowSurrogate(ParseErrorIncorrectEncodingSequence),
IncorrectUTF16NoHighSurrogate(ParseErrorIncorrectEncodingSequence)
}
impl ParseErrorDataTrait for ParseError {
fn get_position(&self) -> TextPosition {
match self {
&ParseError::UnexpectedEndOfInput(ref x) => x.get_position(),
&ParseError::UnexpectedChar(ref x) => x.get_position(),
&ParseError::UnexpectedToken(ref x) => x.get_position(),
&ParseError::IncorrectUTF16NoLowSurrogate(ref x) => x.get_position(),
&ParseError::IncorrectUTF16NoHighSurrogate(ref x) => x.get_position()
}
}
fn get_length(&self) -> usize {
match self {
&ParseError::UnexpectedEndOfInput(ref x) => x.get_length(),
&ParseError::UnexpectedChar(ref x) => x.get_length(),
&ParseError::UnexpectedToken(ref x) => x.get_length(),
&ParseError::IncorrectUTF16NoLowSurrogate(ref x) => x.get_length(),
&ParseError::IncorrectUTF16NoHighSurrogate(ref x) => x.get_length()
}
}
fn get_message(&self) -> String {
match self {
&ParseError::UnexpectedEndOfInput(ref x) => x.get_message(),
&ParseError::UnexpectedChar(ref x) => x.get_message(),
&ParseError::UnexpectedToken(ref x) => x.get_message(),
&ParseError::IncorrectUTF16NoLowSurrogate(ref x) => x.get_message(),
&ParseError::IncorrectUTF16NoHighSurrogate(ref x) => x.get_message()
}
}
}
impl Display for ParseError {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "@{} {}", self.get_position(), self.get_message())
}
}
pub struct ParseErrors {
errors: Vec<ParseError>
}
impl ParseErrors {
pub fn new() -> ParseErrors {
ParseErrors {
errors: Vec::<ParseError>::new()
}
}
pub fn push_error_eoi(&mut self, error: ParseErrorEndOfInput) {
self.errors.push(ParseError::UnexpectedEndOfInput((error)));
}
pub fn push_error_unexpected_char(&mut self, error: ParseErrorUnexpectedChar) {
self.errors.push(ParseError::UnexpectedChar((error)));
}
pub fn push_error_unexpected_token(&mut self, error: ParseErrorUnexpectedToken) {
self.errors.push(ParseError::UnexpectedToken((error)));
}
pub fn push_error_no_low_utf16_surrogate(
&mut self,
error: ParseErrorIncorrectEncodingSequence
) {
self.errors
.push(ParseError::IncorrectUTF16NoLowSurrogate((error)));
}
pub fn push_error_no_high_utf16_surrogate(
&mut self,
error: ParseErrorIncorrectEncodingSequence
) {
self.errors
.push(ParseError::IncorrectUTF16NoHighSurrogate((error)));
}
pub fn get_count(&self) -> usize {
self.errors.len()
}
}
impl<'a> Index<usize> for ParseErrors {
type Output = ParseError;
fn index(&self, index: usize) -> &Self::Output {
&self.errors[index]
}
}
pub struct ParseErrorsIterator<'a> {
parent: &'a ParseErrors,
index: usize
}
impl<'a> Iterator for ParseErrorsIterator<'a> {
type Item = &'a ParseError;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.parent.errors.len() {
None
} else {
let result = &self.parent[self.index];
self.index = self.index + 1;
Some(result)
}
}
}
impl<'a> Iterable<'a> for ParseErrors {
type Item = &'a ParseError;
type IteratorType = ParseErrorsIterator<'a>;
fn iter(&'a self) -> Self::IteratorType {
ParseErrorsIterator {
parent: &self,
index: 0
}
}
}