099e13b82baeec50e427dca8d4832031e24f4b19
[supertux.git] / src / lisp / lisp.hpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #ifndef __LISPREADER_H__
21 #define __LISPREADER_H__
22
23 #include <string>
24 #include <vector>
25 #include <assert.h>
26
27 namespace lisp
28 {
29
30 class Lisp
31 {
32 public:
33   ~Lisp();
34
35   enum LispType {
36     TYPE_CONS,
37     TYPE_SYMBOL,
38     TYPE_INTEGER,
39     TYPE_STRING,
40     TYPE_REAL,
41     TYPE_BOOLEAN
42   };
43
44   LispType get_type() const
45   { return type; }
46
47   const Lisp* get_car() const
48   { return v.cons.car; }
49   const Lisp* get_cdr() const
50   { return v.cons.cdr; }
51
52   bool get(std::string& val) const
53   {
54     if(type != TYPE_STRING && type != TYPE_SYMBOL)
55       return false;
56     val = v.string;
57     return true;
58   }
59
60   std::string get_symbol() const
61   {
62     assert(type == TYPE_SYMBOL);
63     return v.string;
64   }
65
66   std::string get_string() const
67   {
68     assert(type == TYPE_STRING);
69     return v.string;
70   }
71
72   bool get(unsigned int& val) const
73   {
74     if(type != TYPE_INTEGER)
75       return false;
76     val = v.integer;
77     return true;
78   }
79
80   bool get(int& val) const
81   {
82     if(type != TYPE_INTEGER)
83       return false;
84     val = v.integer;
85     return true;
86   }
87
88   int get_int() const
89   {
90     assert(type == TYPE_INTEGER);
91     return v.integer;
92   }
93
94   bool get(float& val) const
95   {
96     if(type != TYPE_REAL) {
97       if(type == TYPE_INTEGER) {
98         val = (float) v.integer;
99         return true;
100       }
101       return false;
102     }
103     val = v.real;
104     return true;
105   }
106
107   float get_float() const
108   {
109     assert(type == TYPE_REAL);
110     return v.real;
111   }
112
113   bool get(bool& val) const
114   {
115     if(type != TYPE_BOOLEAN)
116       return false;
117     val = v.boolean;
118     return true;
119   }
120
121   bool get_bool() const
122   {
123     assert(type == TYPE_BOOLEAN);
124     return v.boolean;
125   }
126
127   /** convenience functions which traverse the list until a child with a
128    * specified name is found. The value part is then interpreted in a specific
129    * way. The functions return true, if a child was found and could be
130    * interpreted correctly, otherwise false is returned and the variable value
131    * is not changed.
132    * (Please note that searching the lisp structure is O(n) so these functions
133    *  are not a good idea for performance critical areas)
134    */
135   template<class T>
136   bool get(const char* name, T& val) const
137   {
138     const Lisp* lisp = get_lisp(name);
139     if(!lisp)
140       return false;
141
142     if(lisp->get_type() != TYPE_CONS)
143       return false;
144     lisp = lisp->get_car();
145     if(!lisp)
146       return false;
147     return lisp->get(val);
148   }
149
150   template<class T>
151   bool get(const char* name, std::vector<T>& vec) const
152   {
153     vec.clear();
154
155     const Lisp* child = get_lisp(name);
156     if(!child)
157       return false;
158
159     for( ; child != 0; child = child->get_cdr()) {
160       T val;
161       if(!child->get_car())
162         continue;
163       if(child->get_car()->get(val)) {
164         vec.push_back(val);
165       }
166     }
167
168     return true;
169   }
170
171   const Lisp* get_lisp(const char* name) const;
172   const Lisp* get_lisp(const std::string& name) const
173   { return get_lisp(name.c_str()); }
174
175   // for debugging
176   void print(int indent = 0) const;
177
178 private:
179   friend class Parser;
180   Lisp(LispType newtype);
181
182   LispType type;
183   union
184   {
185     struct
186     {
187       const Lisp* car;
188       const Lisp* cdr;
189     } cons;
190
191     char* string;
192     int integer;
193     bool boolean;
194     float real;
195   } v;
196 };
197
198 } // end of namespace lisp
199
200 #endif