fa4bda554c1cb12a63f9bc2ec5c79bd2adc4cb31
[supertux.git] / src / lisp / lisp.hpp
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 #ifndef __LISPREADER_H__
21 #define __LISPREADER_H__
22
23 #include <string>
24 #include <vector>
25
26 namespace lisp
27 {
28
29 class Lisp
30 {
31 public:
32   ~Lisp();
33     
34   enum LispType {
35     TYPE_CONS,
36     TYPE_SYMBOL,
37     TYPE_INTEGER,
38     TYPE_STRING,
39     TYPE_REAL,
40     TYPE_BOOLEAN
41   };
42
43   LispType get_type() const
44   { return type; } 
45
46   Lisp* get_car() const
47   { return v.cons.car; }
48   Lisp* get_cdr() const
49   { return v.cons.cdr; }
50   bool get(std::string& val) const
51   { 
52     if(type != TYPE_STRING && type != TYPE_SYMBOL)
53       return false;
54     val = v.string;
55     return true;
56   }
57   bool get(unsigned int& val) const
58   {
59     if(type != TYPE_INTEGER)
60       return false;
61     val = v.integer;
62     return true;
63   }
64   bool get(int& val) const
65   {
66     if(type != TYPE_INTEGER)
67       return false;
68     val = v.integer;
69     return true;
70   }
71   bool get(float& val) const
72   {
73     if(type != TYPE_REAL) {
74       if(type == TYPE_INTEGER) {
75         val = v.integer;
76         return true;
77       }
78       return false;
79     }
80     val = v.real;
81     return true;
82   }
83   bool get(bool& val) const
84   {
85     if(type != TYPE_BOOLEAN)
86       return false;
87     val = v.boolean;
88     return true;
89   }
90
91   /** conveniance functions which traverse the list until a child with a
92    * specified name is found. The value part is then interpreted in a specific
93    * way. The functions return true, if a child was found and could be
94    * interpreted correctly, otherwise false is returned and the variable value
95    * is not changed.
96    * (Please note that searching the lisp structure is O(n) so these functions
97    *  are no good idea for performance critical areas)
98    */
99   template<class T>
100   bool get(const char* name, T& val) const
101   {
102     const Lisp* lisp = get_lisp(name);
103     if(!lisp)
104       return false;
105
106     if(lisp->get_type() != TYPE_CONS)
107       return false;
108     lisp = lisp->get_car();
109     if(!lisp)
110       return false;
111     return lisp->get(val);
112   }
113
114   template<class T>
115   bool get_vector(const char* name, std::vector<T>& vec) const
116   {
117     vec.clear();
118     
119     const Lisp* child = get_lisp(name);
120     if(!child)
121       return false;
122     
123     for( ; child != 0; child = child->get_cdr()) {
124       T val;
125       if(!child->get_car())
126         continue;
127       if(child->get_car()->get(val)) {
128         vec.push_back(val);
129       }
130     }
131     
132     return true;
133   }
134   
135   Lisp* get_lisp(const char* name) const;
136   Lisp* get_lisp(const std::string& name) const
137   { return get_lisp(name.c_str()); }
138
139   // for debugging
140   void print(int indent = 0) const;
141
142 private:
143   friend class Parser;
144   Lisp(LispType newtype);
145
146   LispType type;
147   union
148   {
149     struct
150     {
151       Lisp* car;
152       Lisp* cdr;
153     } cons;
154
155     char* string;
156     int integer;
157     bool boolean;
158     float real;
159   } v;
160 };
161
162 } // end of namespace lisp
163
164 #endif
165