|
|
|
@ -165,7 +165,7 @@ fn peek(s: &str, pos: &usize) -> ERes<(char, usize)> { |
|
|
|
|
|
|
|
|
|
fn expect(s: &str, pos: &mut usize, c: char) -> ERes<()> { |
|
|
|
|
dbg("expect", pos); |
|
|
|
|
let (ch, next) = try!(peek(s, pos)); |
|
|
|
|
let (ch, next) = peek(s, pos)?; |
|
|
|
|
*pos = next; |
|
|
|
|
if ch == c { Ok(()) } else { err("unexpected character", s, pos) } |
|
|
|
|
} |
|
|
|
@ -173,7 +173,7 @@ fn expect(s: &str, pos: &mut usize, c: char) -> ERes<()> { |
|
|
|
|
fn consume_until_newline(s: &str, pos: &mut usize) -> ERes<()> { |
|
|
|
|
loop { |
|
|
|
|
if *pos == s.len() { return Ok(()) } |
|
|
|
|
let (ch, next) = try!(peek(s, pos)); |
|
|
|
|
let (ch, next) = peek(s, pos)?; |
|
|
|
|
*pos = next; |
|
|
|
|
if ch == '\n' { return Ok(()) } |
|
|
|
|
} |
|
|
|
@ -184,9 +184,9 @@ fn zspace(s: &str, pos: &mut usize) -> ERes<()> { |
|
|
|
|
dbg("zspace", pos); |
|
|
|
|
loop { |
|
|
|
|
if *pos == s.len() { return Ok(()) } |
|
|
|
|
let (ch, next) = try!(peek(s, pos)); |
|
|
|
|
let (ch, next) = peek(s, pos)?; |
|
|
|
|
|
|
|
|
|
if ch == ';' { try!(consume_until_newline(s, pos)) } |
|
|
|
|
if ch == ';' { consume_until_newline(s, pos)? } |
|
|
|
|
else if ch.is_whitespace() { *pos = next; } |
|
|
|
|
else { return Ok(()) } |
|
|
|
|
} |
|
|
|
@ -196,15 +196,15 @@ fn parse_quoted_atom(s: &str, pos: &mut usize) -> ERes<Atom> { |
|
|
|
|
dbg("parse_quoted_atom", pos); |
|
|
|
|
let mut cs: String = String::new(); |
|
|
|
|
|
|
|
|
|
try!(expect(s, pos, '"')); |
|
|
|
|
expect(s, pos, '"')?; |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
let (ch, next) = try!(peek(s, pos)); |
|
|
|
|
let (ch, next) = peek(s, pos)?; |
|
|
|
|
if ch == '"' { |
|
|
|
|
*pos = next; |
|
|
|
|
break; |
|
|
|
|
} else if ch == '\\' { |
|
|
|
|
let (postslash, nextnext) = try!(peek(s, &next)); |
|
|
|
|
let (postslash, nextnext) = peek(s, &next)?; |
|
|
|
|
if postslash == '"' || postslash == '\\' { |
|
|
|
|
cs.push(postslash); |
|
|
|
|
} else { |
|
|
|
@ -228,9 +228,9 @@ fn parse_unquoted_atom(s: &str, pos: &mut usize) -> ERes<Atom> { |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
if *pos == s.len() { break } |
|
|
|
|
let (c, next) = try!(peek(s, pos)); |
|
|
|
|
let (c, next) = peek(s, pos)?; |
|
|
|
|
|
|
|
|
|
if c == ';' { try!(consume_until_newline(s, pos)); break } |
|
|
|
|
if c == ';' { consume_until_newline(s, pos)?; break } |
|
|
|
|
if c.is_whitespace() || c == '(' || c == ')' { break } |
|
|
|
|
cs.push(c); |
|
|
|
|
*pos = next; |
|
|
|
@ -241,7 +241,7 @@ fn parse_unquoted_atom(s: &str, pos: &mut usize) -> ERes<Atom> { |
|
|
|
|
|
|
|
|
|
fn parse_atom(s: &str, pos: &mut usize) -> ERes<Atom> { |
|
|
|
|
dbg("parse_atom", pos); |
|
|
|
|
let (ch, _) = try!(peek(s, pos)); |
|
|
|
|
let (ch, _) = peek(s, pos)?; |
|
|
|
|
|
|
|
|
|
if ch == '"' { parse_quoted_atom (s, pos) } |
|
|
|
|
else { parse_unquoted_atom(s, pos) } |
|
|
|
@ -249,34 +249,34 @@ fn parse_atom(s: &str, pos: &mut usize) -> ERes<Atom> { |
|
|
|
|
|
|
|
|
|
fn parse_list(s: &str, pos: &mut usize) -> ERes<Vec<Sexp>> { |
|
|
|
|
dbg("parse_list", pos); |
|
|
|
|
try!(zspace(s, pos)); |
|
|
|
|
try!(expect(s, pos, '(')); |
|
|
|
|
zspace(s, pos)?; |
|
|
|
|
expect(s, pos, '(')?; |
|
|
|
|
|
|
|
|
|
let mut sexps: Vec<Sexp> = Vec::new(); |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
try!(zspace(s, pos)); |
|
|
|
|
let (c, next) = try!(peek(s, pos)); |
|
|
|
|
zspace(s, pos)?; |
|
|
|
|
let (c, next) = peek(s, pos)?; |
|
|
|
|
if c == ')' { |
|
|
|
|
*pos = next; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
sexps.push(try!(parse_sexp(s, pos))); |
|
|
|
|
sexps.push(parse_sexp(s, pos)?); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try!(zspace(s, pos)); |
|
|
|
|
zspace(s, pos)?; |
|
|
|
|
|
|
|
|
|
Ok(sexps) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn parse_sexp(s: &str, pos: &mut usize) -> ERes<Sexp> { |
|
|
|
|
dbg("parse_sexp", pos); |
|
|
|
|
try!(zspace(s, pos)); |
|
|
|
|
let (c, _) = try!(peek(s, pos)); |
|
|
|
|
zspace(s, pos)?; |
|
|
|
|
let (c, _) = peek(s, pos)?; |
|
|
|
|
let r = |
|
|
|
|
if c == '(' { Ok(Sexp::List(try!(parse_list(s, pos)))) } |
|
|
|
|
else { Ok(Sexp::Atom(try!(parse_atom(s, pos)))) }; |
|
|
|
|
try!(zspace(s, pos)); |
|
|
|
|
if c == '(' { Ok(Sexp::List(parse_list(s, pos)?)) } |
|
|
|
|
else { Ok(Sexp::Atom(parse_atom(s, pos)?)) }; |
|
|
|
|
zspace(s, pos)?; |
|
|
|
|
r |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -304,7 +304,7 @@ pub fn list(xs: &[Sexp]) -> Sexp { |
|
|
|
|
#[inline(never)] |
|
|
|
|
pub fn parse(s: &str) -> Result<Sexp, Box<Error>> { |
|
|
|
|
let mut pos = 0; |
|
|
|
|
let ret = try!(parse_sexp(s, &mut pos)); |
|
|
|
|
let ret = parse_sexp(s, &mut pos)?; |
|
|
|
|
if pos == s.len() { Ok(ret) } else { err("unrecognized post-s-expression data", s, &pos) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -352,10 +352,10 @@ impl fmt::Display for Sexp { |
|
|
|
|
match *self { |
|
|
|
|
Sexp::Atom(ref a) => write!(f, "{}", a), |
|
|
|
|
Sexp::List(ref xs) => { |
|
|
|
|
try!(write!(f, "(")); |
|
|
|
|
write!(f, "(")?; |
|
|
|
|
for (i, x) in xs.iter().enumerate() { |
|
|
|
|
let s = if i == 0 { "" } else { " " }; |
|
|
|
|
try!(write!(f, "{}{}", s, x)); |
|
|
|
|
write!(f, "{}{}", s, x)?; |
|
|
|
|
} |
|
|
|
|
write!(f, ")") |
|
|
|
|
}, |
|
|
|
|