use std::fmt::{Display, Error, Formatter};
use serde_derive::Serialize;
use crate::symbols::Symbol;
use crate::text::{TextPosition, Utf16C};
pub trait ParseErrorDataTrait {
fn get_position(&self) -> TextPosition;
fn get_length(&self) -> usize;
fn get_message(&self) -> String;
}
#[derive(Debug, Clone, Serialize)]
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(Debug, Clone, Serialize)]
pub struct ParseErrorUnexpectedChar {
position: TextPosition,
unexpected: char
}
impl ParseErrorDataTrait for ParseErrorUnexpectedChar {
fn get_position(&self) -> TextPosition {
self.position
}
fn get_length(&self) -> usize {
self.unexpected.len_utf8()
}
fn get_message(&self) -> String {
let mut result = String::new();
result.push_str("Unexpected character '");
result.push(self.unexpected);
result.push_str("' (U+");
result.push_str(&format!("{:X}", self.unexpected as u32));
result.push(')');
result
}
}
impl ParseErrorUnexpectedChar {
pub fn new(position: TextPosition, unexpected: char) -> ParseErrorUnexpectedChar {
ParseErrorUnexpectedChar {
position,
unexpected
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct ParseErrorIncorrectEncodingSequence {
position: TextPosition,
#[serde(rename = "missingHigh")]
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(']');
result
}
}
impl ParseErrorIncorrectEncodingSequence {
pub fn new(
position: TextPosition,
missing_high: bool,
sequence: Utf16C
) -> ParseErrorIncorrectEncodingSequence {
ParseErrorIncorrectEncodingSequence {
position,
missing_high,
sequence
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct ParseErrorUnexpectedToken<'s> {
position: TextPosition,
length: usize,
value: String,
terminal: Symbol<'s>,
expected: Vec<Symbol<'s>>
}
impl<'s> ParseErrorDataTrait for ParseErrorUnexpectedToken<'s> {
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('"');
if !self.expected.is_empty() {
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<'s> ParseErrorUnexpectedToken<'s> {
pub fn new(
position: TextPosition,
length: usize,
value: String,
terminal: Symbol<'s>,
expected: Vec<Symbol<'s>>
) -> ParseErrorUnexpectedToken<'s> {
ParseErrorUnexpectedToken {
position,
length,
value,
terminal,
expected
}
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type")]
pub enum ParseError<'s> {
UnexpectedEndOfInput(ParseErrorEndOfInput),
UnexpectedChar(ParseErrorUnexpectedChar),
UnexpectedToken(ParseErrorUnexpectedToken<'s>),
IncorrectUTF16NoLowSurrogate(ParseErrorIncorrectEncodingSequence),
IncorrectUTF16NoHighSurrogate(ParseErrorIncorrectEncodingSequence)
}
impl<'s> ParseErrorDataTrait for ParseError<'s> {
fn get_position(&self) -> TextPosition {
match self {
ParseError::UnexpectedEndOfInput(x) => x.get_position(),
ParseError::UnexpectedChar(x) => x.get_position(),
ParseError::UnexpectedToken(x) => x.get_position(),
ParseError::IncorrectUTF16NoLowSurrogate(x) => x.get_position(),
ParseError::IncorrectUTF16NoHighSurrogate(x) => x.get_position()
}
}
fn get_length(&self) -> usize {
match self {
ParseError::UnexpectedEndOfInput(x) => x.get_length(),
ParseError::UnexpectedChar(x) => x.get_length(),
ParseError::UnexpectedToken(x) => x.get_length(),
ParseError::IncorrectUTF16NoLowSurrogate(x) => x.get_length(),
ParseError::IncorrectUTF16NoHighSurrogate(x) => x.get_length()
}
}
fn get_message(&self) -> String {
match self {
ParseError::UnexpectedEndOfInput(x) => x.get_message(),
ParseError::UnexpectedChar(x) => x.get_message(),
ParseError::UnexpectedToken(x) => x.get_message(),
ParseError::IncorrectUTF16NoLowSurrogate(x) => x.get_message(),
ParseError::IncorrectUTF16NoHighSurrogate(x) => x.get_message()
}
}
}
impl<'s> Display for ParseError<'s> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "@{} {}", self.get_position(), self.get_message())
}
}
impl<'s> std::error::Error for ParseError<'s> {}
#[derive(Default, Clone)]
pub struct ParseErrors<'s> {
pub errors: Vec<ParseError<'s>>
}
impl<'s> ParseErrors<'s> {
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<'s>) {
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));
}
}