Skip to content

Commit effb834

Browse files
committed
Added ; to reader
1 parent 6fc04e0 commit effb834

File tree

1 file changed

+65
-4
lines changed

1 file changed

+65
-4
lines changed

src/reader.rs

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn is_period_char(chr: char) -> bool {
146146
///
147147
/// Clojure defines a whitespace as either a comma or an unicode whitespace.
148148
fn is_clojure_whitespace(c: char) -> bool {
149-
c.is_whitespace() || c == ','
149+
c.is_whitespace() || c == ','
150150
}
151151
////////////////////////////////////////////////////////////////////////////////////////////////////
152152
// End predicates
@@ -163,8 +163,25 @@ fn is_clojure_whitespace(c: char) -> bool {
163163
///
164164
/// A whitespace is either an ASCII whitespace or a comma.
165165
fn consume_clojure_whitespaces_parser(input: &str) -> IResult<&str, ()> {
166-
named!(parser<&str, &str>, take_while!(is_clojure_whitespace));
167-
parser(input).map(|(rest, _)| (rest, ()))
166+
named!(comment_parser<&str,&str>, delimited!(tag(";"),take_until!("\n"),tag("\n")));
167+
168+
named!(whitespace_parser<&str,()>,
169+
value!((),
170+
many0!(alt!(comment_parser |
171+
take_while1!(is_clojure_whitespace))))
172+
);
173+
174+
named!(no_whitespace_parser<&str,()>, value!((),tag!("")));
175+
176+
// @TODO rename / check that all parsers are consistent?
177+
named!(parser<&str,()>,
178+
// Because 'whitespace_parser' loops, we cannot include the case where there's no whitespace at all in
179+
// its definition -- nom wouldn't allow it, as it would loop forever consuming no whitespace
180+
// So instead, we eat up all the whitespace first, and then use the no_whitespace_parser as our sort-of
181+
// base-case after
182+
alt!(whitespace_parser | no_whitespace_parser)
183+
);
184+
parser(input)
168185
}
169186

170187
// This parser is made with nom's function combinator, rather than macros,
@@ -515,9 +532,12 @@ pub fn read<R: BufRead>(reader: &mut R) -> Value {
515532
// loop over and ask for more lines, accumulating them in input_buffer until we can read
516533
loop {
517534
let maybe_line = reader.by_ref().lines().next();
535+
518536
match maybe_line {
519537
Some(Err(e)) => return Value::Condition(format!("Reader error: {}", e)),
520-
Some(Ok(line)) => input_buffer.push_str(&line),
538+
// `lines` does not include \n, but \n is part of the whitespace given to the reader
539+
// (and is important for reading comments) so we will push a newline as well
540+
Some(Ok(line)) => { input_buffer.push_str(&line); input_buffer.push_str("\n"); },
521541
None => {
522542
return Value::Condition(String::from("Tried to read empty stream; unexpected EOF"))
523543
}
@@ -834,6 +854,47 @@ mod tests {
834854
consume_clojure_whitespaces_parser(&s).ok()
835855
);
836856
}
857+
858+
#[test]
859+
fn consume_whitespaces_with_comments_then_no_whitespace() {
860+
let s = ", ,, \n; Line starts as comment\n ; Line does not start as comment\n1, 2, 3, 4 5,,6 ";
861+
assert_eq!(
862+
Some(("1, 2, 3, 4 5,,6 ", ())),
863+
consume_clojure_whitespaces_parser(&s).ok()
864+
);
865+
}
866+
867+
#[test]
868+
fn consume_whitespaces_with_comments_then_whitespace() {
869+
let s = ", ,, \n; Line starts as comment\n ; Line does not start as comment\n, 1, 2, 3, 4 5,,6 ";
870+
assert_eq!(
871+
Some(("1, 2, 3, 4 5,,6 ", ())),
872+
consume_clojure_whitespaces_parser(&s).ok()
873+
);
874+
}
875+
#[test]
876+
fn consume_whitespaces_with_comments() {
877+
let mut s = "; Line starts as comment\n\n, 1, 2, 3, 4 5,,6 ";
878+
assert_eq!(
879+
Some(("1, 2, 3, 4 5,,6 ", ())),
880+
consume_clojure_whitespaces_parser(&s).ok()
881+
);
882+
883+
s = "; Line starts as comment\n\n1, 2, 3, 4 5,,6 ";
884+
assert_eq!(
885+
Some(("1, 2, 3, 4 5,,6 ", ())),
886+
consume_clojure_whitespaces_parser(&s).ok()
887+
);
888+
}
889+
890+
#[test]
891+
fn consume_whitespaces_multiline() {
892+
let s = " , , ,\n \n\n\n, 1, 2, 3, 4 5,,6 ";
893+
assert_eq!(
894+
Some(("1, 2, 3, 4 5,,6 ", ())),
895+
consume_clojure_whitespaces_parser(&s).ok()
896+
);
897+
}
837898
}
838899

839900
mod is_clojure_whitespace_tests {

0 commit comments

Comments
 (0)