add missing assert include
[supertux.git] / lib / lisp / parser.cpp
1 //  $Id$
2 //
3 //  TuxKart - a fun racing game with go-kart
4 //  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
5 //  code in this file based on lispreader from Mark Probst
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 #include <config.h>
21
22 #include <sstream>
23 #include <stdexcept>
24 #include <fstream>
25 #include <cassert>
26
27 #include "parser.h"
28 #include "lisp.h"
29
30 namespace lisp
31 {
32
33 Parser::Parser()
34   : lexer(0)
35 {
36 }
37
38 Parser::~Parser()
39 {
40   delete lexer;
41 }
42
43 Lisp*
44 Parser::parse(const std::string& filename)
45 {
46   std::ifstream in(filename.c_str());
47   if(!in.good()) {
48     std::stringstream msg;
49     msg << "Parser problem: Couldn't open file '" << filename << "'.";
50     throw std::runtime_error(msg.str());
51   }
52   return parse(in);
53 }
54
55 Lisp*
56 Parser::parse(std::istream& stream)
57 {
58   delete lexer;
59   lexer = new Lexer(stream);
60
61   token = lexer->getNextToken();
62   Lisp* result = new Lisp(Lisp::TYPE_CONS);
63   result->v.cons.car = read();
64   result->v.cons.cdr = 0;
65   
66   delete lexer;
67   lexer = 0;
68
69   return result;    
70 }
71
72 Lisp*
73 Parser::read()
74 {
75   Lisp* result;
76   switch(token) {
77     case Lexer::TOKEN_EOF: {
78       std::stringstream msg;
79       msg << "Parse Error at line " << lexer->getLineNumber() << ": "
80         << "Unexpected EOF.";
81       throw std::runtime_error(msg.str());
82     }
83     case Lexer::TOKEN_CLOSE_PAREN: {
84       std::stringstream msg;
85       msg << "Parse Error at line " << lexer->getLineNumber() << ": "
86         << "Unexpected ')'.";
87       throw std::runtime_error(msg.str());
88     }
89     case Lexer::TOKEN_OPEN_PAREN: {
90       result = new Lisp(Lisp::TYPE_CONS);
91       
92       token = lexer->getNextToken();
93       if(token == Lexer::TOKEN_CLOSE_PAREN) {
94         result->v.cons.car = 0;
95         result->v.cons.cdr = 0;
96         break;
97       }
98
99       Lisp* cur = result;
100       do {
101         cur->v.cons.car = read();
102         if(token == Lexer::TOKEN_CLOSE_PAREN) {
103           cur->v.cons.cdr = 0;
104           break;
105         }
106         cur->v.cons.cdr = new Lisp(Lisp::TYPE_CONS);
107         cur = cur->v.cons.cdr;
108       } while(1);
109
110       break;
111     }
112     case Lexer::TOKEN_SYMBOL: {
113       result = new Lisp(Lisp::TYPE_SYMBOL);
114       size_t len = strlen(lexer->getString()) + 1;
115       result->v.string = new char[len];
116       memcpy(result->v.string, lexer->getString(), len);
117       break;
118     }
119     case Lexer::TOKEN_STRING: {
120       result = new Lisp(Lisp::TYPE_STRING);
121       size_t len = strlen(lexer->getString()) + 1;
122       result->v.string = new char[len];
123       memcpy(result->v.string, lexer->getString(), len);
124       break;
125     }
126     case Lexer::TOKEN_INTEGER:
127       result = new Lisp(Lisp::TYPE_INTEGER);
128       sscanf(lexer->getString(), "%d", &result->v.integer);
129       break;
130     case Lexer::TOKEN_REAL:
131       result = new Lisp(Lisp::TYPE_REAL);
132       sscanf(lexer->getString(), "%f", &result->v.real);
133       break;
134     case Lexer::TOKEN_TRUE:
135       result = new Lisp(Lisp::TYPE_BOOLEAN);
136       result->v.boolean = true;
137       break;
138     case Lexer::TOKEN_FALSE:
139       result = new Lisp(Lisp::TYPE_BOOLEAN);
140       result->v.boolean = false;
141       break;
142
143     default:
144       // this should never happen
145       assert(false);
146   }
147
148   token = lexer->getNextToken();
149   return result;
150 }
151
152 } // end of namespace lisp