00001 // SuperTux 00002 // Copyright (C) 2006 Matthias Braun <matze@braunis.de> 00003 // 00004 // This program is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 00017 #ifndef HEADER_SUPERTUX_LISP_LISP_HPP 00018 #define HEADER_SUPERTUX_LISP_LISP_HPP 00019 00020 #include <assert.h> 00021 #include <string> 00022 #include <vector> 00023 00024 namespace lisp { 00025 00026 class Lisp 00027 { 00028 public: 00029 ~Lisp(); 00030 00031 enum LispType { 00032 TYPE_CONS, 00033 TYPE_SYMBOL, 00034 TYPE_INTEGER, 00035 TYPE_STRING, 00036 TYPE_REAL, 00037 TYPE_BOOLEAN 00038 }; 00039 00040 LispType get_type() const 00041 { return type; } 00042 00043 const Lisp* get_car() const 00044 { return v.cons.car; } 00045 const Lisp* get_cdr() const 00046 { return v.cons.cdr; } 00047 00048 bool get(std::string& val) const 00049 { 00050 if(type != TYPE_STRING && type != TYPE_SYMBOL) 00051 return false; 00052 val = v.string; 00053 return true; 00054 } 00055 00056 std::string get_symbol() const 00057 { 00058 assert(type == TYPE_SYMBOL); 00059 return v.string; 00060 } 00061 00062 std::string get_string() const 00063 { 00064 assert(type == TYPE_STRING); 00065 return v.string; 00066 } 00067 00068 bool get(unsigned int& val) const 00069 { 00070 if(type != TYPE_INTEGER) 00071 return false; 00072 val = v.integer; 00073 return true; 00074 } 00075 00076 bool get(int& val) const 00077 { 00078 if(type != TYPE_INTEGER) 00079 return false; 00080 val = v.integer; 00081 return true; 00082 } 00083 00084 int get_int() const 00085 { 00086 assert(type == TYPE_INTEGER); 00087 return v.integer; 00088 } 00089 00090 bool get(float& val) const 00091 { 00092 if(type != TYPE_REAL) { 00093 if(type == TYPE_INTEGER) { 00094 val = (float) v.integer; 00095 return true; 00096 } 00097 return false; 00098 } 00099 val = v.real; 00100 return true; 00101 } 00102 00103 float get_float() const 00104 { 00105 assert(type == TYPE_REAL); 00106 return v.real; 00107 } 00108 00109 bool get(bool& val) const 00110 { 00111 if(type != TYPE_BOOLEAN) 00112 return false; 00113 val = v.boolean; 00114 return true; 00115 } 00116 00117 bool get_bool() const 00118 { 00119 assert(type == TYPE_BOOLEAN); 00120 return v.boolean; 00121 } 00122 00131 template<class T> 00132 bool get(const char* name, T& val) const 00133 { 00134 const Lisp* lisp = get_lisp(name); 00135 if(!lisp) 00136 return false; 00137 00138 if(lisp->get_type() != TYPE_CONS) 00139 return false; 00140 lisp = lisp->get_car(); 00141 if(!lisp) 00142 return false; 00143 return lisp->get(val); 00144 } 00145 00146 template<class T> 00147 bool get(const char* name, std::vector<T>& vec) const 00148 { 00149 vec.clear(); 00150 00151 const Lisp* child = get_lisp(name); 00152 if(!child) 00153 return false; 00154 00155 for( ; child != 0; child = child->get_cdr()) { 00156 T val; 00157 if(!child->get_car()) 00158 continue; 00159 if(child->get_car()->get(val)) { 00160 vec.push_back(val); 00161 } 00162 } 00163 00164 return true; 00165 } 00166 00167 const Lisp* get_lisp(const char* name) const; 00168 const Lisp* get_lisp(const std::string& name) const 00169 { return get_lisp(name.c_str()); } 00170 00171 // for debugging 00172 void print(int indent = 0) const; 00173 00174 private: 00175 friend class Parser; 00176 Lisp(LispType newtype); 00177 00178 LispType type; 00179 union 00180 { 00181 struct 00182 { 00183 const Lisp* car; 00184 const Lisp* cdr; 00185 } cons; 00186 00187 char* string; 00188 int integer; 00189 bool boolean; 00190 float real; 00191 } v; 00192 }; 00193 00194 } // end of namespace lisp 00195 00196 #endif 00197 00198 /* EOF */