@@ -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.
148148fn 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.
165165fn 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\n 1, 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 \n 1, 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