use std::fmt;
use std::borrow::Cow;
use std::error::Error as StdError;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct SourcePosition {
pub line: i32,
pub column: i32
}
impl SourcePosition {
fn start() -> SourcePosition {
SourcePosition { line: 1, column: 1 }
}
fn update(&mut self, c: &char) {
self.column += 1;
if *c == '\n' {
self.column = 1;
self.line += 1;
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
Unexpected(char),
Expected(Cow<'static, str>),
Message(Cow<'static, str>)
}
#[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>
where F: FnOnce(T) -> ParseResult<U, I> {
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(Clone, Debug, PartialEq)]
pub struct ParseError {
pub position: SourcePosition,
pub errors: Vec<Error>
}
impl ParseError {
pub fn new(position: SourcePosition, error: Error) -> ParseError {
ParseError { position: position, errors: vec![error] }
}
pub fn add_message<S>(&mut self, message: S)
where S: Into<Cow<'static, str>> {
self.add_error(Error::Message(message.into()));
}
pub fn add_error(&mut self, message: Error) {
if self.errors.iter().find(|msg| **msg == message).is_none() {
self.errors.push(message);
}
}
pub fn set_expected(&mut self, message: Cow<'static, str>) {
self.errors.retain(|e| match *e { Error::Expected(_) => false, _ => true });
self.errors.push(Error::Expected(message));
}
pub fn merge(mut self, other: ParseError) -> ParseError {
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 StdError for ParseError {
fn description(&self) -> &str { "parse error" }
}
impl fmt::Display for ParseError {
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(_) => 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 fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Unexpected(c) => write!(f, "Unexpected character '{}'", c),
Error::Expected(ref s) => write!(f, "Expected {}", s),
Error::Message(ref msg) => write!(f, "{}", msg),
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct State<I> {
pub position: SourcePosition,
pub input: I
}
impl <I: Stream> State<I> {
pub fn new(input: I) -> State<I> {
State { position: SourcePosition::start(), input: input }
}
pub fn as_empty(&self) -> State<I> {
State { position: self.position, input: self.input.clone() }
}
pub fn uncons<F>(self, f: F) -> ParseResult<<I as Stream>::Item, I>
where F: FnOnce(&mut SourcePosition, &<I as Stream>::Item) {
let State { mut position, input, .. } = self;
match input.uncons() {
Ok((c, input)) => {
f(&mut position, &c);
Ok((c, Consumed::Consumed(State { position: position, input: input })))
}
Err(()) => Err(Consumed::Empty(ParseError::new(position, Error::Message("End of input".into()))))
}
}
}
impl <I: Stream<Item=char>> State<I> {
pub fn uncons_char(self) -> ParseResult<<I as Stream>::Item, I> {
self.uncons(SourcePosition::update)
}
}
pub type ParseResult<O, I> = Result<(O, Consumed<State<I>>), Consumed<ParseError>>;
pub trait Stream : Clone {
type Item;
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] {
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> {
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 Parser {
type Input: Stream;
type Output;
fn parse(&mut self, input: Self::Input) -> Result<(Self::Output, Self::Input), ParseError> {
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>;
}
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> {
(*self).parse_state(input)
}
}
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> {
(**self).parse_state(input)
}
}