X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Flisp%2Flexer.cpp;h=90f4aa28c831f87c6690451f210c4a0bf7e21df3;hb=b917bb4789b14d1bb1445b9777ab494e9623fd50;hp=9b4220b0829b51b3afbc4365f8cf2936b3437325;hpb=cb75d04970c73721c3e044eceaa90d8e4ab1142c;p=supertux.git diff --git a/src/lisp/lexer.cpp b/src/lisp/lexer.cpp index 9b4220b08..90f4aa28c 100644 --- a/src/lisp/lexer.cpp +++ b/src/lisp/lexer.cpp @@ -16,32 +16,26 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - #include #include +#include #include #include +#include #include "lexer.hpp" namespace lisp { -class EOFException -{ -}; - Lexer::Lexer(std::istream& newstream) : stream(newstream), eof(false), linenumber(0) { - try { - // trigger a refill of the buffer - c = 0; - bufend = 0; - nextChar(); - } catch(EOFException& e) { - } + // trigger a refill of the buffer + bufpos = NULL; + bufend = NULL; + nextChar(); } Lexer::~Lexer() @@ -51,14 +45,15 @@ Lexer::~Lexer() void Lexer::nextChar() { - ++c; - if(c >= bufend) { - if(eof) - throw EOFException(); + if(bufpos >= bufend) { + if(eof) { + c = EOF; + return; + } stream.read(buffer, BUFFER_SIZE); size_t bytes_read = stream.gcount(); - c = buffer; + bufpos = buffer; bufend = buffer + bytes_read; // the following is a hack that appends an additional ' ' at the end of @@ -70,6 +65,17 @@ Lexer::nextChar() ++bufend; } } + c = *bufpos++; + if(c == '\n') + ++linenumber; +} + +void +Lexer::addChar() +{ + if(token_length < MAX_TOKEN_LENGTH) + token_string[token_length++] = c; + nextChar(); } Lexer::TokenType @@ -77,142 +83,124 @@ Lexer::getNextToken() { static const char* delims = "\"();"; - try { - while(isspace(*c)) { - if(*c == '\n') - ++linenumber; - nextChar(); - }; + while(isspace(c)) { + nextChar(); + } - token_length = 0; + token_length = 0; - switch(*c) { - case ';': // comment - while(true) { - nextChar(); - if(*c == '\n') { - ++linenumber; - break; - } - } - return getNextToken(); // and again - case '(': + switch(c) { + case ';': // comment + while(c != '\n') { nextChar(); - return TOKEN_OPEN_PAREN; - case ')': + } + return getNextToken(); // and again + case '(': + nextChar(); + return TOKEN_OPEN_PAREN; + case ')': + nextChar(); + return TOKEN_CLOSE_PAREN; + case '"': { // string + int startline = linenumber; + while(1) { nextChar(); - return TOKEN_CLOSE_PAREN; - case '"': { // string - int startline = linenumber; - try { - while(1) { - nextChar(); - if(*c == '"') - break; - else if (*c == '\r') // XXX this breaks with pure \r EOL - continue; - else if(*c == '\n') - linenumber++; - else if(*c == '\\') { - nextChar(); - switch(*c) { - case 'n': - *c = '\n'; - break; - case 't': - *c = '\t'; - break; - } - } - if(token_length < MAX_TOKEN_LENGTH) - token_string[token_length++] = *c; + switch(c) { + case '"': + nextChar(); + goto string_finished; + case '\r': + continue; + case '\n': + break; + case '\\': + nextChar(); + switch(c) { + case 'n': + c = '\n'; + break; + case 't': + c = '\t'; + break; } - token_string[token_length] = 0; - } catch(EOFException& ) { + break; + case EOF: { std::stringstream msg; msg << "Parse error in line " << startline << ": " - << "EOF while parsing string."; + << "EOF while parsing string."; throw std::runtime_error(msg.str()); } - nextChar(); - return TOKEN_STRING; - } - case '#': // constant - try { - nextChar(); - - while(isalnum(*c) || *c == '_') { - if(token_length < MAX_TOKEN_LENGTH) - token_string[token_length++] = *c; - nextChar(); - } - token_string[token_length] = 0; - } catch(EOFException& ) { - std::stringstream msg; - msg << "Parse Error in line " << linenumber << ": " - << "EOF while parsing constant."; - throw std::runtime_error(msg.str()); + default: + break; } + if(token_length < MAX_TOKEN_LENGTH) + token_string[token_length++] = c; + } +string_finished: + token_string[token_length] = 0; + return TOKEN_STRING; + } + case '#': // constant + nextChar(); - if(strcmp(token_string, "t") == 0) - return TOKEN_TRUE; - if(strcmp(token_string, "f") == 0) - return TOKEN_FALSE; + while(isalnum(c) || c == '_') { + addChar(); + } + token_string[token_length] = 0; - // we only handle #t and #f constants at the moment... + if(strcmp(token_string, "t") == 0) + return TOKEN_TRUE; + if(strcmp(token_string, "f") == 0) + return TOKEN_FALSE; - { - std::stringstream msg; - msg << "Parse Error in line " << linenumber << ": " + // we only handle #t and #f constants at the moment... + { + std::stringstream msg; + msg << "Parse Error in line " << linenumber << ": " << "Unknown constant '" << token_string << "'."; - throw std::runtime_error(msg.str()); - } + throw std::runtime_error(msg.str()); + } + + case EOF: + return TOKEN_EOF; + + default: + if(isdigit(c) || c == '-') { + bool have_nondigits = false; + bool have_digits = false; + int have_floating_point = 0; + + do { + if(isdigit(c)) + have_digits = true; + else if(c == '.') + ++have_floating_point; + else if(isalnum(c) || c == '_') + have_nondigits = true; - default: - if(isdigit(*c) || *c == '-') { - bool have_nondigits = false; - bool have_digits = false; - int have_floating_point = 0; - - do { - if(isdigit(*c)) - have_digits = true; - else if(*c == '.') - ++have_floating_point; - else if(isalnum(*c) || *c == '_') - have_nondigits = true; - - if(token_length < MAX_TOKEN_LENGTH) - token_string[token_length++] = *c; - - nextChar(); - } while(!isspace(*c) && !strchr(delims, *c)); - - token_string[token_length] = 0; - - // no nextChar - - if(have_nondigits || !have_digits || have_floating_point > 1) - return TOKEN_SYMBOL; - else if(have_floating_point == 1) - return TOKEN_REAL; - else - return TOKEN_INTEGER; - } else { - do { - if(token_length < MAX_TOKEN_LENGTH) - token_string[token_length++] = *c; - nextChar(); - } while(!isspace(*c) && !strchr(delims, *c)); - token_string[token_length] = 0; - - // no nextChar + addChar(); + } while(!isspace(c) && !strchr(delims, c)); + token_string[token_length] = 0; + + // no nextChar + + if(have_nondigits || !have_digits || have_floating_point > 1) return TOKEN_SYMBOL; - } - } - } catch(EOFException& ) { - return TOKEN_EOF; + else if(have_floating_point == 1) + return TOKEN_REAL; + else + return TOKEN_INTEGER; + } else { + do { + addChar(); + } while(!isspace(c) && !strchr(delims, c)); + token_string[token_length] = 0; + + // no nextChar + + return TOKEN_SYMBOL; + } } }