Back to index

supertuxkart  0.5+dfsg1
parser.cpp
Go to the documentation of this file.
00001 //  $Id: parser.cpp 2111 2008-05-31 07:04:30Z cosmosninja $
00002 //
00003 //  TuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
00005 //  code in this file based on lispreader from Mark Probst
00006 //
00007 //  This program is free software; you can redistribute it and/or
00008 //  modify it under the terms of the GNU General Public License
00009 //  as published by the Free Software Foundation; either version 2
00010 //  of the License, or (at your option) any later version.
00011 //
00012 //  This program is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU General Public License
00018 //  along with this program; if not, write to the Free Software
00019 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020 #include <sstream>
00021 #include <stdexcept>
00022 #include <fstream>
00023 
00024 #include "parser.hpp"
00025 #include "lisp.hpp"
00026 #include "translation.hpp"
00027 #if defined(WIN32) && !defined(__CYGWIN__)
00028 #  define snprintf _snprintf
00029 #endif
00030 
00031 namespace lisp
00032 {
00033 
00034     Parser::Parser()
00035             : m_lexer(0)
00036     {}
00037 
00038 //-----------------------------------------------------------------------------
00039 
00040     Parser::~Parser()
00041     {
00042         delete m_lexer;
00043     }
00044 
00045 //-----------------------------------------------------------------------------
00046 
00047     Lisp*
00048     Parser::parse(const std::string& filename)
00049     {
00050         std::ifstream in(filename.c_str());
00051         if(!in.good())
00052         {
00053             char msg[MAX_ERROR_MESSAGE_LENGTH];
00054             snprintf(msg, sizeof(msg), 
00055                      "Couldn't open file '%s'.",
00056                      filename.c_str());
00057             throw std::runtime_error(msg);
00058         }
00059         return parse(in);
00060     }
00061 
00062 //-----------------------------------------------------------------------------
00063 
00064     Lisp*
00065     Parser::parse(std::istream& m_stream)
00066     {
00067         delete m_lexer;
00068         m_lexer = new Lexer(m_stream);
00069 
00070         m_token = m_lexer->getNextToken();
00071         Lisp* result = new Lisp(Lisp::TYPE_CONS);
00072         result->m_v.m_cons.m_car = 0;
00073         result->m_v.m_cons.m_cdr = readList();
00074 
00075         delete m_lexer;
00076         m_lexer = 0;
00077 
00078         return result;
00079     }
00080 
00081 //-----------------------------------------------------------------------------
00082 
00083     Lisp*
00084     Parser::read()
00085     {
00086         Lisp* result;
00087         switch(m_token)
00088         {
00089         case Lexer::TOKEN_EOF:
00090             {
00091                 char msg[MAX_ERROR_MESSAGE_LENGTH];
00092                 snprintf(msg, sizeof(msg), 
00093                          "Parse Error at line %d: Unexpected EOF.",
00094                          m_lexer->getLineNumber());
00095                 throw std::runtime_error(msg);
00096             }
00097         case Lexer::TOKEN_CLOSE_PAREN:
00098             {
00099                 char msg[MAX_ERROR_MESSAGE_LENGTH];
00100                 snprintf(msg, sizeof(msg), 
00101                          "Parse Error at line %d: Unexpected ')'.",
00102                          m_lexer->getLineNumber());
00103                 throw std::runtime_error(msg);
00104             }
00105         case Lexer::TOKEN_TRANSLATION:
00106            {
00107                    result = new Lisp(Lisp::TYPE_STRING);
00108                 m_token = m_lexer->getNextToken();
00109                 Lisp* next=read();
00110                 if(next->getType()!=Lisp::TYPE_STRING)
00111                 {
00112                     char msg[MAX_ERROR_MESSAGE_LENGTH];
00113                     snprintf(msg, sizeof(msg), 
00114                         "Parse Error at line %d: No string inside translation.",
00115                         m_lexer->getLineNumber());
00116                     throw std::runtime_error(msg);
00117                 }
00118                 const char* trans=_(next->m_v.m_string);
00119                 const size_t LEN = strlen(trans) + 1;
00120                 result->m_v.m_string = new char[LEN];
00121                 memcpy(result->m_v.m_string, trans, LEN);
00122                 delete next;
00123                 break;
00124            }
00125         case Lexer::TOKEN_OPEN_PAREN:
00126             result = new Lisp(Lisp::TYPE_CONS);
00127 
00128             m_token = m_lexer->getNextToken();
00129 
00130             result->m_v.m_cons.m_car = read();
00131             result->m_v.m_cons.m_cdr = readList();
00132 
00133             if(m_token != Lexer::TOKEN_CLOSE_PAREN)
00134             {
00135                 char msg[MAX_ERROR_MESSAGE_LENGTH];
00136                 snprintf(msg, sizeof(msg), 
00137                          "Parse Error at line %d: Expected ')'.",
00138                          m_lexer->getLineNumber());
00139                 throw std::runtime_error(msg);
00140             }
00141             break;
00142         case Lexer::TOKEN_SYMBOL:
00143             {
00144                 result = new Lisp(Lisp::TYPE_SYMBOL);
00145                 const size_t LEN = strlen(m_lexer->getString()) + 1;
00146                 result->m_v.m_string = new char[LEN];
00147                 memcpy(result->m_v.m_string, m_lexer->getString(), LEN);
00148                 break;
00149             }
00150         case Lexer::TOKEN_STRING:
00151             {
00152                 result = new Lisp(Lisp::TYPE_STRING);
00153                 const size_t LEN = strlen(m_lexer->getString()) + 1;
00154                 result->m_v.m_string = new char[LEN];
00155                 memcpy(result->m_v.m_string, m_lexer->getString(), LEN);
00156                 break;
00157             }
00158         case Lexer::TOKEN_INTEGER:
00159             result = new Lisp(Lisp::TYPE_INTEGER);
00160             sscanf(m_lexer->getString(), "%d", &result->m_v.m_integer);
00161             break;
00162         case Lexer::TOKEN_REAL:
00163             result = new Lisp(Lisp::TYPE_REAL);
00164             sscanf(m_lexer->getString(), "%f", &result->m_v.m_real);
00165             break;
00166         case Lexer::TOKEN_TRUE:
00167             result = new Lisp(Lisp::TYPE_BOOLEAN);
00168             result->m_v.m_boolean = true;
00169             break;
00170         case Lexer::TOKEN_FALSE:
00171             result = new Lisp(Lisp::TYPE_BOOLEAN);
00172             result->m_v.m_boolean = false;
00173             break;
00174 
00175         default:
00176             // this should never happen
00177             assert(false);
00178         }
00179 
00180         m_token = m_lexer->getNextToken();
00181         return result;
00182     }
00183 
00184 //-----------------------------------------------------------------------------
00185 
00186     Lisp*
00187     Parser::readList()
00188     {
00189         Lisp* result = 0;
00190 
00191         while(m_token != Lexer::TOKEN_CLOSE_PAREN && m_token != Lexer::TOKEN_EOF)
00192         {
00193             Lisp* newlisp = new Lisp(Lisp::TYPE_CONS);
00194             newlisp->m_v.m_cons.m_car = read();
00195             newlisp->m_v.m_cons.m_cdr = result;
00196             result = newlisp;
00197         }
00198 
00199         return result;
00200     }
00201 
00202 } // end of namespace lisp