use std::fmt;
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, Debug)]
pub enum Info {
Token(char),
Owned(String),
Borrowed(&'static str)
}
impl PartialEq for Info {
fn eq(&self, other: &Info) -> bool {
match (self, other) {
(&Info::Token(l), &Info::Token(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 fmt::Display for Info {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Info::Token(c) => write!(f, "{}", c),
Info::Owned(ref s) => write!(f, "{}", s),
Info::Borrowed(s) => write!(f, "{}", s),
}
}
}
impl From<char> for Info {
fn from(s: char) -> Info {
Info::Token(s)
}
}
impl From<String> for Info {
fn from(s: String) -> Info {
Info::Owned(s)
}
}
impl From<&'static str> for Info {
fn from(s: &'static str) -> Info {
Info::Borrowed(s)
}
}
#[derive(Debug)]
pub enum Error {
Unexpected(char),
Expected(Info),
Message(Info),
Other(Box<StdError+Send>)
}
impl PartialEq for Error {
fn eq(&self, other: &Error) -> bool {
match (self, other) {
(&Error::Unexpected(l), &Error::Unexpected(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> From<E> for Error where E: StdError + 'static + Send {
fn from(e: E) -> Error {
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>
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(Debug, PartialEq)]
pub struct ParseError {
pub position: SourcePosition,
pub errors: Vec<Error>
}
impl ParseError {
pub fn new(position: SourcePosition, error: Error) -> ParseError {
ParseError::from_errors(position, vec![error])
}
pub fn from_errors(position: SourcePosition, errors: Vec<Error>) -> ParseError {
ParseError { position: position, errors: errors }
}
pub fn add_message<S>(&mut self, message: S)
where S: Into<Info> {
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: Info) {
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(_) | 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 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),
Error::Other(ref err) => err.fmt(f)
}
}
}
#[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)
}
}