|
|
@ -13,7 +13,8 @@ use std::fmt; |
|
|
|
use std::str::{self, FromStr}; |
|
|
|
use std::str::{self, FromStr}; |
|
|
|
|
|
|
|
|
|
|
|
pub use error::Error; |
|
|
|
pub use error::Error; |
|
|
|
use error::{ERes, err}; |
|
|
|
pub use error::SourcePosition; |
|
|
|
|
|
|
|
use error::{ERes, err, spos}; |
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
#[cfg(test)] |
|
|
|
mod test; |
|
|
|
mod test; |
|
|
@ -34,11 +35,26 @@ pub enum Atom { |
|
|
|
|
|
|
|
|
|
|
|
/// An s-expression is either an atom or a list of s-expressions. This is
|
|
|
|
/// An s-expression is either an atom or a list of s-expressions. This is
|
|
|
|
/// similar to the data format used by lisp.
|
|
|
|
/// similar to the data format used by lisp.
|
|
|
|
#[derive(PartialEq, Clone, PartialOrd)] |
|
|
|
#[derive(Clone)] |
|
|
|
#[allow(missing_docs)] |
|
|
|
|
|
|
|
pub enum Sexp { |
|
|
|
pub enum Sexp { |
|
|
|
Atom(Atom), |
|
|
|
/// Atom
|
|
|
|
List(Vec<Sexp>), |
|
|
|
Atom(Atom, Option<Box<SourcePosition>>), |
|
|
|
|
|
|
|
/// List of expressions
|
|
|
|
|
|
|
|
List(Vec<Sexp>, Option<Box<SourcePosition>>), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl PartialEq for Sexp { |
|
|
|
|
|
|
|
fn eq(&self, other: &Self) -> bool { |
|
|
|
|
|
|
|
match (self, other) { |
|
|
|
|
|
|
|
(Sexp::Atom(a, _), Sexp::Atom(b, _)) => { |
|
|
|
|
|
|
|
a == b |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
(Sexp::List(a, _), Sexp::List(b, _)) => { |
|
|
|
|
|
|
|
a == b |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
_ => false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -180,30 +196,33 @@ fn parse_sexp(s: &str, pos: &mut usize) -> ERes<Sexp> { |
|
|
|
trace!("parse_sexp {}", pos); |
|
|
|
trace!("parse_sexp {}", pos); |
|
|
|
zspace(s, pos)?; |
|
|
|
zspace(s, pos)?; |
|
|
|
let (c, _) = peek(s, pos)?; |
|
|
|
let (c, _) = peek(s, pos)?; |
|
|
|
let r = |
|
|
|
let r = if c == '(' { |
|
|
|
if c == '(' { Ok(Sexp::List(parse_list(s, pos)?)) } else { Ok(Sexp::Atom(parse_atom(s, pos)?)) }; |
|
|
|
Ok(Sexp::List(parse_list(s, pos)?, spos(s, pos))) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
Ok(Sexp::Atom(parse_atom(s, pos)?, spos(s, pos))) |
|
|
|
|
|
|
|
}; |
|
|
|
zspace(s, pos)?; |
|
|
|
zspace(s, pos)?; |
|
|
|
r |
|
|
|
r |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Constructs an atomic s-expression from a string.
|
|
|
|
/// Constructs an atomic s-expression from a string.
|
|
|
|
pub fn atom_s(s: &str) -> Sexp { |
|
|
|
pub fn atom_s(s: &str) -> Sexp { |
|
|
|
Sexp::Atom(Atom::S(s.to_owned())) |
|
|
|
Sexp::Atom(Atom::S(s.to_owned()), None) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Constructs an atomic s-expression from an int.
|
|
|
|
/// Constructs an atomic s-expression from an int.
|
|
|
|
pub fn atom_i(i: i64) -> Sexp { |
|
|
|
pub fn atom_i(i: i64) -> Sexp { |
|
|
|
Sexp::Atom(Atom::I(i)) |
|
|
|
Sexp::Atom(Atom::I(i), None) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Constructs an atomic s-expression from a float.
|
|
|
|
/// Constructs an atomic s-expression from a float.
|
|
|
|
pub fn atom_f(f: f64) -> Sexp { |
|
|
|
pub fn atom_f(f: f64) -> Sexp { |
|
|
|
Sexp::Atom(Atom::F(f)) |
|
|
|
Sexp::Atom(Atom::F(f), None) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Constructs a list s-expression given a slice of s-expressions.
|
|
|
|
/// Constructs a list s-expression given a slice of s-expressions.
|
|
|
|
pub fn list(xs: &[Sexp]) -> Sexp { |
|
|
|
pub fn list(xs: &[Sexp]) -> Sexp { |
|
|
|
Sexp::List(xs.to_owned()) |
|
|
|
Sexp::List(xs.to_owned(), None) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Reads an s-expression out of a `&str`.
|
|
|
|
/// Reads an s-expression out of a `&str`.
|
|
|
@ -256,8 +275,8 @@ impl fmt::Display for Atom { |
|
|
|
impl fmt::Display for Sexp { |
|
|
|
impl fmt::Display for Sexp { |
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
|
|
|
match *self { |
|
|
|
match *self { |
|
|
|
Sexp::Atom(ref a) => write!(f, "{}", a), |
|
|
|
Sexp::Atom(ref a, _) => write!(f, "{}", a), |
|
|
|
Sexp::List(ref xs) => { |
|
|
|
Sexp::List(ref xs, _) => { |
|
|
|
write!(f, "(")?; |
|
|
|
write!(f, "(")?; |
|
|
|
for (i, x) in xs.iter().enumerate() { |
|
|
|
for (i, x) in xs.iter().enumerate() { |
|
|
|
let s = if i == 0 { "" } else { " " }; |
|
|
|
let s = if i == 0 { "" } else { " " }; |
|
|
|