use std::fmt;
use std::error::Error as StdError;
use std::any::Any;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct SourcePosition {
pub line: i32,
pub column: i32
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct BytePosition {
pub position: usize
}
impl fmt::Display for BytePosition {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "position: {}", self.position)
}
}
#[derive(Clone, Debug)]
pub enum Info<T> {
Token(T),
Owned(String),
Borrowed(&'static str)
}
impl <T: PartialEq> PartialEq for Info<T> {
fn eq(&self, other: &Info<T>) -> bool {
match (self, other) {
(&Info::Token(ref l), &Info::Token(ref r)) => l == r,
(&Info::Owned(ref l), &Info::Owned(ref r)) => l == r,
(&Info::Borrowed(ref l), &Info::Owned(ref r)) => l == r,
(&Info::Owned(ref l), &Info::Borrowed(ref r)) => l == r,
(&Info::Borrowed(ref l), &Info::Borrowed(ref r)) => l == r,
_ => false
}
}
}
impl <T: fmt::Display> fmt::Display for Info<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Info::Token(ref c) => write!(f, "{}", c),
Info::Owned(ref s) => write!(f, "{}", s),
Info::Borrowed(s) => write!(f, "{}", s),
}
}
}
impl <T: Positioner> From<T> for Info<T> {
fn from(s: T) -> Info<T> {
Info::Token(s)
}
}
impl <T> From<String> for Info<T> {
fn from(s: String) -> Info<T> {
Info::Owned(s)
}
}
impl <T> From<&'static str> for Info<T> {
fn from(s: &'static str) -> Info<T> {
Info::Borrowed(s)
}
}
#[derive(Debug)]
pub enum Error<T> {
Unexpected(T),
Expected(Info<T>),
Message(Info<T>),
Other(Box<StdError+Send>)
}
impl <T: PartialEq> PartialEq for Error<T> {
fn eq(&self, other: &Error<T>) -> bool {
match (self, other) {
(&Error::Unexpected(ref l), &Error::Unexpected(ref r)) => l == r,
(&Error::Expected(ref l), &Error::Expected(ref r)) => l == r,
(&Error::Message(ref l), &Error::Message(ref r)) => l == r,
_ => false
}
}
}
impl <E, T> From<E> for Error<T> where E: StdError + 'static + Send {
fn from(e: E) -> Error<T> {
Error::Other(Box::new(e))
}
}
#[derive(Clone, PartialEq, Debug, Copy)]
pub enum Consumed<T> {
Consumed(T),
Empty(T)
}
impl <T> Consumed<T> {
pub fn is_empty(&self) -> bool {
match *self {
Consumed::Empty(_) => true,
Consumed::Consumed(_) => false
}
}
pub fn into_inner(self) -> T {
match self {
Consumed::Empty(x) => x,
Consumed::Consumed(x) => x
}
}
pub fn as_consumed(self) -> Consumed<T> {
Consumed::Consumed(self.into_inner())
}
pub fn as_empty(self) -> Consumed<T> {
Consumed::Empty(self.into_inner())
}
pub fn map<F, U>(self, f: F) -> Consumed<U>
where F: FnOnce(T) -> U {
match self {
Consumed::Empty(x) => Consumed::Empty(f(x)),
Consumed::Consumed(x) => Consumed::Consumed(f(x))
}
}
pub fn combine<F, U, I>(self, f: F) -> ParseResult<U, I, I::Item>
where F: FnOnce(T) -> ParseResult<U, I, I::Item>
, I: Stream {
match self {
Consumed::Consumed(x) => {
match f(x) {
Ok((v, Consumed::Empty(rest))) => Ok((v, Consumed::Consumed(rest))),
Err(Consumed::Empty(err)) => Err(Consumed::Consumed(err)),
y => y
}
}
Consumed::Empty(x) => f(x)
}
}
}
#[derive(Debug, PartialEq)]
pub struct ParseError<P: Positioner> {
pub position: P::Position,
pub errors: Vec<Error<P>>
}
impl <P: Positioner> ParseError<P> {
pub fn new(position: P::Position, error: Error<P>) -> ParseError<P> {
ParseError::from_errors(position, vec![error])
}
pub fn empty(position: P::Position) -> ParseError<P> {
ParseError::from_errors(position, vec![])
}
pub fn from_errors(position: P::Position, errors: Vec<Error<P>>) -> ParseError<P> {
ParseError { position: position, errors: errors }
}
pub fn add_message<S>(&mut self, message: S)
where S: Into<Info<P>> {
self.add_error(Error::Message(message.into()));
}
pub fn add_error(&mut self, message: Error<P>) {
if self.errors.iter().find(|msg| **msg == message).is_none() {
self.errors.push(message);
}
}
pub fn set_expected(&mut self, message: Info<P>) {
self.errors.retain(|e| match *e { Error::Expected(_) => false, _ => true });
self.errors.push(Error::Expected(message));
}
pub fn merge(mut self, other: ParseError<P>) -> ParseError<P> {
use std::cmp::Ordering;
match self.position.cmp(&other.position) {
Ordering::Less => other,
Ordering::Greater => self,
Ordering::Equal => {
for message in other.errors.into_iter() {
self.add_error(message);
}
self
}
}
}
}
impl <P> StdError for ParseError<P>
where P: Positioner + fmt::Display + fmt::Debug + Any
, P::Position: fmt::Display + fmt::Debug + Any {
fn description(&self) -> &str { "parse error" }
}
impl <P: Positioner + fmt::Display> fmt::Display for ParseError<P>
where P::Position: fmt::Display {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "Parse error at {}", self.position));
let unexpected = self.errors.iter()
.filter(|e| match **e { Error::Unexpected(_) => true, _ => false } );
for error in unexpected {
try!(writeln!(f, "{}", error));
}
let expected_count = self.errors.iter()
.filter(|e| match **e { Error::Expected(_) => true, _ => false } )
.count();
let mut i = 0;
for error in self.errors.iter() {
match *error {
Error::Expected(ref message) => {
i += 1;
if i == 1 {
try!(write!(f, "Expected"));
}
else if i == expected_count { try!(write!(f, " or"));
}
else {
try!(write!(f, ","));
}
try!(write!(f, " '{}'", message));
}
_ => ()
}
}
if expected_count != 0 {
try!(writeln!(f, ""));
}
let messages = self.errors.iter()
.filter(|e| match **e { Error::Message(_) | Error::Other(_) => true, _ => false } );
for error in messages {
try!(writeln!(f, "{}", error));
}
Ok(())
}
}
impl fmt::Display for SourcePosition {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "line: {}, column: {}", self.line, self.column)
}
}
impl <T: fmt::Display> fmt::Display for Error<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Unexpected(ref c) => write!(f, "Unexpected token '{}'", c),
Error::Expected(ref s) => write!(f, "Expected {}", s),
Error::Message(ref msg) => write!(f, "{}", msg),
Error::Other(ref err) => err.fmt(f)
}
}
}
#[derive(Clone, PartialEq)]
pub struct State<I>
where I: Stream {
pub position: <I::Item as Positioner>::Position,
pub input: I
}
impl <I> fmt::Debug for State<I>
where I: Stream + fmt::Debug
, <I::Item as Positioner>::Position: fmt::Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "State {{ position: {:?}, input: {:?} }}", self.position, self.input)
}
}
impl <I: Stream> State<I> {
pub fn new(input: I) -> State<I> {
State { position: <I::Item as Positioner>::start(), input: input }
}
pub fn as_empty(&self) -> State<I> {
State { position: self.position.clone(), input: self.input.clone() }
}
pub fn uncons(self) -> ParseResult<I::Item, I, I::Item> {
let State { mut position, input, .. } = self;
match input.uncons() {
Ok((c, input)) => {
c.update(&mut position);
Ok((c, Consumed::Consumed(State { position: position, input: input })))
}
Err(()) => Err(Consumed::Empty(ParseError::new(position, Error::Message("End of input".into()))))
}
}
pub fn update(mut self, i: I::Item, rest: I) -> ParseResult<I::Item, I, I::Item> {
i.update(&mut self.position);
self.input = rest;
Ok((i, Consumed::Consumed(self)))
}
pub fn end_of_input(self) -> ParseResult<I::Item, I, I::Item> {
Err(Consumed::Empty(ParseError::new(self.position, Error::Message("End of input".into()))))
}
}
pub type ParseResult<O, I, T> = Result<(O, Consumed<State<I>>), Consumed<ParseError<T>>>;
pub trait Stream : Clone {
type Item: Positioner;
fn uncons(self) -> Result<(Self::Item, Self), ()>;
}
impl <'a> Stream for &'a str {
type Item = char;
fn uncons(self) -> Result<(char, &'a str), ()> {
match self.chars().next() {
Some(c) => Ok((c, &self[c.len_utf8()..])),
None => Err(())
}
}
}
impl <'a, T> Stream for &'a [T]
where T: Positioner {
type Item = &'a T;
fn uncons(self) -> Result<(&'a T, &'a [T]), ()> {
if self.len() > 0 {
Ok((&self[0], &self[1..]))
}
else {
Err(())
}
}
}
#[derive(Clone, Debug)]
pub struct IteratorStream<I>(I)
where I: Iterator + Clone;
pub fn from_iter<I>(iter: I) -> IteratorStream<I>
where I: Iterator + Clone {
IteratorStream(iter)
}
impl <I: Iterator + Clone> Stream for IteratorStream<I>
where I::Item: Positioner {
type Item = <I as Iterator>::Item;
fn uncons(mut self) -> Result<(I::Item, Self), ()> {
match self.0.next() {
Some(x) => Ok((x, self)),
None => Err(())
}
}
}
pub trait Positioner: Clone + PartialEq {
type Position: Clone + Ord;
fn start() -> Self::Position;
fn update(&self, position: &mut Self::Position);
}
impl <'a, T> Positioner for &'a T
where T: Positioner {
type Position = <T as Positioner>::Position;
fn start() -> <T as Positioner>::Position {
<T as Positioner>::start()
}
fn update(&self, position: &mut <T as Positioner>::Position) {
(*self).update(position)
}
}
impl Positioner for char {
type Position = SourcePosition;
fn start() -> SourcePosition {
SourcePosition { line: 1, column: 1 }
}
fn update(&self, position: &mut SourcePosition) {
position.column += 1;
if *self == '\n' {
position.column = 1;
position.line += 1;
}
}
}
impl Positioner for u8 {
type Position = BytePosition;
fn start() -> BytePosition {
BytePosition { position: 0 }
}
fn update(&self, b: &mut BytePosition) {
b.position += 1;
}
}
pub trait Parser {
type Input: Stream;
type Output;
fn parse(&mut self, input: Self::Input) -> Result<(Self::Output, Self::Input), ParseError<<Self::Input as Stream>::Item>> {
match self.parse_state(State::new(input)) {
Ok((v, state)) => Ok((v, state.into_inner().input)),
Err(error) => Err(error.into_inner())
}
}
fn parse_state(&mut self, input: State<Self::Input>) -> ParseResult<Self::Output, Self::Input, <Self::Input as Stream>::Item> {
let mut result = self.parse_lazy(input.clone());
if let Err(Consumed::Empty(ref mut error)) = result {
if let Ok((t, _)) = input.input.uncons() {
error.add_error(Error::Unexpected(t.into()));
}
self.add_error(error);
}
result
}
fn parse_lazy(&mut self, input: State<Self::Input>) -> ParseResult<Self::Output, Self::Input, <Self::Input as Stream>::Item> {
self.parse_state(input)
}
fn add_error(&mut self, _error: &mut ParseError<<Self::Input as Stream>::Item>) {
}
}
impl <'a, I, O, P: ?Sized> Parser for &'a mut P
where I: Stream, P: Parser<Input=I, Output=O> {
type Input = I;
type Output = O;
fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I, I::Item> {
(**self).parse_state(input)
}
fn parse_lazy(&mut self, input: State<I>) -> ParseResult<O, I, I::Item> {
(**self).parse_lazy(input)
}
fn add_error(&mut self, error: &mut ParseError<<Self::Input as Stream>::Item>) {
(**self).add_error(error)
}
}
impl <I, O, P: ?Sized> Parser for Box<P>
where I: Stream, P: Parser<Input=I, Output=O> {
type Input = I;
type Output = O;
fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I, I::Item> {
(**self).parse_state(input)
}
fn parse_lazy(&mut self, input: State<I>) -> ParseResult<O, I, I::Item> {
(**self).parse_lazy(input)
}
fn add_error(&mut self, error: &mut ParseError<<Self::Input as Stream>::Item>) {
(**self).add_error(error)
}
}