You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
2.6 KiB
117 lines
2.6 KiB
// read_complex().
|
|
|
|
// General includes.
|
|
#include "cl_sysdep.h"
|
|
|
|
// Specification.
|
|
#include "cln/complex_io.h"
|
|
|
|
|
|
// Implementation.
|
|
|
|
#include "cln/io.h"
|
|
#include "cl_spushstring.h"
|
|
#include "cln/input.h"
|
|
|
|
namespace cln {
|
|
|
|
// We read an entire token (or even more, if it begins with #C) into a
|
|
// buffer and then call read_complex() on the buffer.
|
|
|
|
class pushstring_hack : public cl_spushstring {
|
|
public:
|
|
char* start_pointer (void) { return buffer; }
|
|
char* end_pointer (void) { return buffer+index; }
|
|
};
|
|
|
|
static bool number_char_p (char c)
|
|
{
|
|
if ((c >= '0') && (c <= '9'))
|
|
return true;
|
|
if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))
|
|
return true;
|
|
switch (c) {
|
|
case '+': case '-': case '.': case '_': case '/':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const cl_N read_complex (std::istream& stream, const cl_read_flags& flags)
|
|
{
|
|
// One pre-allocated buffer. This reduces the allocation/free cost.
|
|
static pushstring_hack buffer;
|
|
|
|
var int c;
|
|
// Skip whitespace at the beginning.
|
|
loop {
|
|
c = freadchar(stream);
|
|
if (c == cl_EOF) goto eof;
|
|
if ((c == ' ') || (c == '\t') || (c == '\n'))
|
|
continue;
|
|
else
|
|
break;
|
|
}
|
|
// Found first non-whitespace character.
|
|
// Numbers cannot cross lines. We can treat EOF and '\n' the same way.
|
|
buffer.reset();
|
|
if (c == '#') {
|
|
if (!(flags.lsyntax & lsyntax_commonlisp))
|
|
goto syntax1;
|
|
buffer.push(c);
|
|
// Read some digits, then a letter, then a list or token.
|
|
loop {
|
|
c = freadchar(stream);
|
|
if (c == cl_EOF) goto eof;
|
|
buffer.push(c);
|
|
if ((c >= '0') && (c <= '9'))
|
|
continue;
|
|
else
|
|
break;
|
|
}
|
|
if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))))
|
|
goto syntax1;
|
|
c = freadchar(stream);
|
|
if (c == cl_EOF) goto eof;
|
|
if (c == '(') {
|
|
var uintL paren_level = 0;
|
|
loop {
|
|
buffer.push(c);
|
|
if (c == '(') paren_level++;
|
|
else if (c == ')') paren_level--;
|
|
if (paren_level == 0) goto done;
|
|
c = freadchar(stream);
|
|
if ((c == cl_EOF) || (c == '\n')) goto syntax;
|
|
}
|
|
}
|
|
}
|
|
// Read a number token.
|
|
if (!number_char_p(c))
|
|
goto syntax1;
|
|
loop {
|
|
buffer.push(c);
|
|
c = freadchar(stream);
|
|
if (c == cl_EOF)
|
|
break;
|
|
if (!number_char_p(c)) {
|
|
funreadchar(stream,c);
|
|
break;
|
|
}
|
|
}
|
|
done:
|
|
// Parse the number.
|
|
return read_complex(flags,
|
|
buffer.start_pointer(), buffer.end_pointer(),
|
|
NULL
|
|
);
|
|
|
|
// Handle syntax error.
|
|
syntax1: buffer.push(c);
|
|
syntax: throw read_number_bad_syntax_exception(buffer.start_pointer(),buffer.end_pointer());
|
|
|
|
// Handle premature EOF.
|
|
eof: throw read_number_eof_exception();
|
|
}
|
|
|
|
} // namespace cln
|