@@ -146,7 +146,7 @@ fn is_period_char(chr: char) -> bool {
146
146
///
147
147
/// Clojure defines a whitespace as either a comma or an unicode whitespace.
148
148
fn is_clojure_whitespace ( c : char ) -> bool {
149
- c. is_whitespace ( ) || c == ','
149
+ c. is_whitespace ( ) || c == ','
150
150
}
151
151
////////////////////////////////////////////////////////////////////////////////////////////////////
152
152
// End predicates
@@ -163,8 +163,25 @@ fn is_clojure_whitespace(c: char) -> bool {
163
163
///
164
164
/// A whitespace is either an ASCII whitespace or a comma.
165
165
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)
168
185
}
169
186
170
187
// 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 {
515
532
// loop over and ask for more lines, accumulating them in input_buffer until we can read
516
533
loop {
517
534
let maybe_line = reader. by_ref ( ) . lines ( ) . next ( ) ;
535
+
518
536
match maybe_line {
519
537
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 " ) ; } ,
521
541
None => {
522
542
return Value :: Condition ( String :: from ( "Tried to read empty stream; unexpected EOF" ) )
523
543
}
@@ -834,6 +854,47 @@ mod tests {
834
854
consume_clojure_whitespaces_parser( & s) . ok( )
835
855
) ;
836
856
}
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
+ }
837
898
}
838
899
839
900
mod is_clojure_whitespace_tests {
0 commit comments