X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Flisp%2Flexer.cpp;h=ef1925fba31a963cecb0eea688228035ef4c803c;hb=5240d812e12e6b53dc3c36bf313361d2d457382a;hp=7352c8212b483bb516209744e2b67a94999e5cf7;hpb=c307442e4bf1352cf1807b171b5ab175ba063b31;p=supertux.git diff --git a/src/lisp/lexer.cpp b/src/lisp/lexer.cpp index 7352c8212..ef1925fba 100644 --- a/src/lisp/lexer.cpp +++ b/src/lisp/lexer.cpp @@ -1,12 +1,10 @@ -// $Id$ -// // SuperTux // Copyright (C) 2006 Matthias Braun // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,34 +12,31 @@ // GNU General Public License for more details. // // 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. +// along with this program. If not, see . -#include +#include "lisp/lexer.hpp" +#include #include #include -#include - -#include "lexer.hpp" - -namespace lisp +#include + +namespace lisp { + +Lexer::Lexer(std::istream& newstream) : + stream(newstream), + eof(false), + linenumber(0), + bufend(), + bufpos(), + c(), + token_string(), + token_length() { - -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& ) { - } + // trigger a refill of the buffer + bufpos = '\0'; + bufend = '\0'; + nextChar(); } Lexer::~Lexer() @@ -51,14 +46,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 +66,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,143 +84,127 @@ 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) { + switch(c) { + case '"': + nextChar(); + goto string_finished; + case '\r': + continue; + case '\n': + break; + case '\\': 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; - } + switch(c) { + case 'n': + c = '\n'; + break; + case 't': + c = '\t'; + break; } - if(token_length < MAX_TOKEN_LENGTH) - token_string[token_length++] = *c; + break; + case EOF: { + std::stringstream msg; + msg << "Parse error in line " << startline << ": " + << "EOF while parsing string."; + throw std::runtime_error(msg.str()); } - token_string[token_length] = 0; - } catch(EOFException& ) { - std::stringstream msg; - msg << "Parse error in line " << startline << ": " - << "EOF while parsing string."; - throw std::runtime_error(msg.str()); + default: + break; } - nextChar(); - return TOKEN_STRING; + if(token_length < MAX_TOKEN_LENGTH) + token_string[token_length++] = c; } - 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()); - } + 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()); + } - default: - if(isdigit(*c) || *c == '-') { - bool have_nondigits = false; - bool have_digits = false; - int have_floating_point = 0; + case EOF: + return TOKEN_EOF; - 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; - if(token_length < MAX_TOKEN_LENGTH) - token_string[token_length++] = *c; + do { + if(isdigit(c)) + have_digits = true; + else if(c == '.') + ++have_floating_point; + else if(isalnum(c) || c == '_') + have_nondigits = true; - 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; + addChar(); + } while(!isspace(c) && !strchr(delims, c)); - // no nextChar + 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; + } } } } // end of namespace lisp + +/* EOF */