2 // This file contains a slimmed down version of read_real().
3 // It does not pull in all the floating-point, complex and transcendental
7 #include "base/cl_sysdep.h"
10 #include "cln/rational_io.h"
15 #include "cln/input.h"
17 #include "base/string/cl_spushstring.h"
21 // We read an entire token (or even more, if it begins with #C) into a
22 // buffer and then call read_rational() on the buffer.
24 class pushstring_hack : public cl_spushstring {
26 char* start_pointer (void) { return buffer; }
27 char* end_pointer (void) { return buffer+index; }
30 static bool number_char_p (char c)
32 if ((c >= '0') && (c <= '9'))
34 if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))
37 case '+': case '-': case '.': case '_': case '/':
44 const cl_RA read_rational (std::istream& stream, const cl_read_flags& flags)
46 // One pre-allocated buffer. This reduces the allocation/free cost.
47 static pushstring_hack buffer;
50 // Skip whitespace at the beginning.
53 if (stream.eof() || stream.fail()) goto eof;
54 if ((c == ' ') || (c == '\t') || (c == '\n'))
59 // Found first non-whitespace character.
60 // Numbers cannot cross lines. We can treat EOF and '\n' the same way.
63 if (!(flags.lsyntax & lsyntax_commonlisp))
66 // Read some digits, then a letter, then a token.
69 if (stream.eof() || stream.fail()) goto eof;
71 if ((c >= '0') && (c <= '9'))
76 if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))))
79 if (stream.eof() || stream.fail()) goto eof;
81 // Read a number token.
82 if (!number_char_p(c))
86 c = stream.peek(); // Avoid fail state on EOF.
87 if (stream.eof() || stream.fail() || !number_char_p(c))
92 return read_rational(flags,
93 buffer.start_pointer(), buffer.end_pointer(),
97 // Handle syntax error.
98 syntax1: buffer.push(c);
99 throw read_number_bad_syntax_exception(buffer.start_pointer(),buffer.end_pointer());
101 // Handle premature EOF.
102 eof: throw read_number_eof_exception();