@@ -148,7 +148,7 @@ fn is_period_char(chr: char) -> bool {
148148///
149149/// Clojure defines a whitespace as either a comma or an unicode whitespace.
150150fn is_clojure_whitespace ( c : char ) -> bool {
151- c. is_whitespace ( ) || c == ','
151+ c. is_whitespace ( ) || c == ','
152152}
153153////////////////////////////////////////////////////////////////////////////////////////////////////
154154// End predicates
@@ -169,16 +169,16 @@ fn consume_clojure_whitespaces_parser(input: &str) -> IResult<&str, ()> {
169169
170170 named ! ( whitespace_parser<& str , ( ) >,
171171 value!( ( ) ,
172- many0!( alt!( comment_parser |
172+ many0!( alt!( comment_parser |
173173 take_while1!( is_clojure_whitespace) ) ) )
174174 ) ;
175175
176176 named ! ( no_whitespace_parser<& str , ( ) >, value!( ( ) , tag!( "" ) ) ) ;
177177
178- // @TODO rename / check that all parsers are consistent?
178+ // @TODO rename / check that all parsers are consistent?
179179 named ! ( parser<& str , ( ) >,
180180 // Because 'whitespace_parser' loops, we cannot include the case where there's no whitespace at all in
181- // its definition -- nom wouldn't allow it, as it would loop forever consuming no whitespace
181+ // its definition -- nom wouldn't allow it, as it would loop forever consuming no whitespace
182182 // So instead, we eat up all the whitespace first, and then use the no_whitespace_parser as our sort-of
183183 // base-case after
184184 alt!( whitespace_parser | no_whitespace_parser)
@@ -432,6 +432,16 @@ pub fn try_read_pattern(input: &str) -> IResult<&str, Value> {
432432 Ok ( ( rest_input, regex) )
433433}
434434
435+ /// This reader is needed for parsing the division sign /
436+ pub fn try_read_division_forward_slash ( input : & str ) -> IResult < & str , Value > {
437+ named ! ( slash_parser<& str , & str >, preceded!( consume_clojure_whitespaces_parser, tag!( "/" ) ) ) ;
438+
439+ let ( rest_input, slash) = slash_parser ( input) ?;
440+
441+ // If an error is thrown, this will be coerced into a condition
442+ Ok ( ( rest_input, Value :: Symbol ( Symbol :: intern ( slash) ) ) )
443+ }
444+
435445// @TODO Perhaps generalize this, or even generalize it as a reader macro
436446/// Tries to parse &str into Value::PersistentListMap, or some other Value::..Map
437447/// Example Successes:
@@ -533,6 +543,7 @@ pub fn try_read(input: &str) -> IResult<&str, Value> {
533543 try_read_bool,
534544 try_read_nil,
535545 try_read_symbol,
546+ try_read_division_forward_slash,
536547 try_read_keyword,
537548 try_read_list,
538549 try_read_vector,
@@ -560,12 +571,15 @@ pub fn read<R: BufRead>(reader: &mut R) -> Value {
560571 // loop over and ask for more lines, accumulating them in input_buffer until we can read
561572 loop {
562573 let maybe_line = reader. by_ref ( ) . lines ( ) . next ( ) ;
563-
574+
564575 match maybe_line {
565576 Some ( Err ( e) ) => return Value :: Condition ( format ! ( "Reader error: {}" , e) ) ,
566577 // `lines` does not include \n, but \n is part of the whitespace given to the reader
567- // (and is important for reading comments) so we will push a newline as well
568- Some ( Ok ( line) ) => { input_buffer. push_str ( & line) ; input_buffer. push_str ( "\n " ) ; } ,
578+ // (and is important for reading comments) so we will push a newline as well
579+ Some ( Ok ( line) ) => {
580+ input_buffer. push_str ( & line) ;
581+ input_buffer. push_str ( "\n " ) ;
582+ }
569583 None => {
570584 return Value :: Condition ( String :: from ( "Tried to read empty stream; unexpected EOF" ) )
571585 }
@@ -881,6 +895,14 @@ mod tests {
881895 fn try_read_bool_false_test ( ) {
882896 assert_eq ! ( Value :: Boolean ( false ) , try_read( "false " ) . ok( ) . unwrap( ) . 1 )
883897 }
898+
899+ #[ test]
900+ fn try_read_forward_slash_test ( ) {
901+ assert_eq ! (
902+ Value :: Symbol ( Symbol :: intern( & "/" ) ) ,
903+ try_read( "/ " ) . ok( ) . unwrap( ) . 1
904+ ) ;
905+ }
884906 }
885907
886908 mod regex_tests {
0 commit comments