Now the growings animation looks pretty cool :)
[supertux.git] / src / lispreader.cpp
index 8f8bbed..51ff97c 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#include <assert.h>
+#include <iostream>
+#include <string>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-
-#include <lispreader.h>
+#include "setup.h"
+#include "lispreader.h"
 
 #define TOKEN_ERROR                   -1
 #define TOKEN_EOF                     0
 static char token_string[MAX_TOKEN_LENGTH + 1] = "";
 static int token_length = 0;
 
-static lisp_object_t end_marker = { LISP_TYPE_EOF };
-static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR };
-static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR };
-static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR };
+static lisp_object_t end_marker = { LISP_TYPE_EOF, {{0, 0}} };
+static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR , {{0,0}}  };
+static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR , {{0,0}}  };
+static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
 
 static void
 _token_clear (void)
@@ -62,7 +63,8 @@ _token_clear (void)
 static void
 _token_append (char c)
 {
-  assert(token_length < MAX_TOKEN_LENGTH);
+  if (token_length >= MAX_TOKEN_LENGTH)
+    throw LispReaderException("_token_append()", __FILE__, __LINE__);
 
   token_string[token_length++] = c;
   token_string[token_length] = '\0';
@@ -91,7 +93,8 @@ _next_char (lisp_stream_t *stream)
     case LISP_STREAM_ANY:
       return stream->v.any.next_char(stream->v.any.data);
     }
-  assert(0);
+
+  throw LispReaderException("_next_char()", __FILE__, __LINE__);
   return EOF;
 }
 
@@ -113,7 +116,7 @@ _unget_char (char c, lisp_stream_t *stream)
       break;
 
     default :
-      assert(0);
+      throw LispReaderException("_unget_char()", __FILE__, __LINE__);
     }
 }
 
@@ -265,7 +268,7 @@ _scan (lisp_stream_t *stream)
         }
     }
 
-  assert(0);
+  throw LispReaderException("_scan()", __FILE__, __LINE__);
   return TOKEN_ERROR;
 }
 
@@ -303,7 +306,8 @@ lisp_stream_init_any (lisp_stream_t *stream, void *data,
                       int (*next_char) (void *data),
                       void (*unget_char) (char c, void *data))
 {
-  assert(next_char != 0 && unget_char != 0);
+  if (next_char == 0 || unget_char == 0)
+    throw LispReaderException("lisp_stream_init_any()", __FILE__, __LINE__);
 
   stream->type = LISP_STREAM_ANY;
   stream->v.any.data = data;
@@ -491,7 +495,7 @@ lisp_read (lisp_stream_t *in)
       return lisp_make_boolean(0);
     }
 
-  assert(0);
+  throw LispReaderException("lisp_read()", __FILE__, __LINE__);
   return &error_object;
 }
 
@@ -567,7 +571,8 @@ _compile_pattern (lisp_object_t **obj, int *index)
         int type;
         int i;
         lisp_object_t *pattern;
-
+        type = -1;
+       
         if (lisp_type(lisp_car(*obj)) != LISP_TYPE_SYMBOL)
           return 0;
 
@@ -640,7 +645,8 @@ static int _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_obje
 static int
 _match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars)
 {
-  assert(lisp_type(pattern) == LISP_TYPE_PATTERN_VAR);
+  if (lisp_type(pattern) != LISP_TYPE_PATTERN_VAR)
+    throw LispReaderException("_match_pattern_var", __FILE__, __LINE__);
 
   switch (pattern->v.pattern.type)
     {
@@ -684,7 +690,8 @@ _match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **
 
         for (sub = pattern->v.pattern.sub; sub != 0; sub = lisp_cdr(sub))
           {
-            assert(lisp_type(sub) == LISP_TYPE_CONS);
+            if (lisp_type(sub) != LISP_TYPE_CONS)
+              throw LispReaderException("_match_pattern_var()", __FILE__, __LINE__);
 
             if (_match_pattern(lisp_car(sub), obj, vars))
               matched = 1;
@@ -696,7 +703,7 @@ _match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **
       break;
 
     default :
-      assert(0);
+      throw LispReaderException("_match_pattern_var()", __FILE__, __LINE__);
     }
 
   if (vars != 0)
@@ -746,7 +753,7 @@ _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars
       break;
 
     default :
-      assert(0);
+      throw LispReaderException("_match_pattern()", __FILE__, __LINE__);
     }
 
   return 0;
@@ -801,7 +808,8 @@ lisp_type (lisp_object_t *obj)
 int
 lisp_integer (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_INTEGER);
+  if (obj->type != LISP_TYPE_INTEGER)
+    throw LispReaderException("lisp_integer()", __FILE__, __LINE__);
 
   return obj->v.integer;
 }
@@ -809,7 +817,8 @@ lisp_integer (lisp_object_t *obj)
 char*
 lisp_symbol (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_SYMBOL);
+  if (obj->type != LISP_TYPE_SYMBOL)
+    throw LispReaderException("lisp_symbol()", __FILE__, __LINE__);
 
   return obj->v.string;
 }
@@ -817,7 +826,8 @@ lisp_symbol (lisp_object_t *obj)
 char*
 lisp_string (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_STRING);
+  if (obj->type != LISP_TYPE_STRING)
+    throw LispReaderException("lisp_string()", __FILE__, __LINE__);
 
   return obj->v.string;
 }
@@ -825,7 +835,8 @@ lisp_string (lisp_object_t *obj)
 int
 lisp_boolean (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_BOOLEAN);
+  if (obj->type != LISP_TYPE_BOOLEAN)
+    throw LispReaderException("lisp_boolean()", __FILE__, __LINE__);
 
   return obj->v.integer;
 }
@@ -833,7 +844,8 @@ lisp_boolean (lisp_object_t *obj)
 float
 lisp_real (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_REAL || obj->type == LISP_TYPE_INTEGER);
+  if (obj->type != LISP_TYPE_REAL && obj->type != LISP_TYPE_INTEGER)
+    throw LispReaderException("lisp_real()", __FILE__, __LINE__);
 
   if (obj->type == LISP_TYPE_INTEGER)
     return obj->v.integer;
@@ -843,7 +855,8 @@ lisp_real (lisp_object_t *obj)
 lisp_object_t*
 lisp_car (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
+  if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
+    throw LispReaderException("lisp_car()", __FILE__, __LINE__);
 
   return obj->v.cons.car;
 }
@@ -851,7 +864,8 @@ lisp_car (lisp_object_t *obj)
 lisp_object_t*
 lisp_cdr (lisp_object_t *obj)
 {
-  assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
+  if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
+    throw LispReaderException("lisp_cdr()", __FILE__, __LINE__);
 
   return obj->v.cons.cdr;
 }
@@ -867,7 +881,7 @@ lisp_cxr (lisp_object_t *obj, const char *x)
     else if (x[i] == 'd')
       obj = lisp_cdr(obj);
     else
-      assert(0);
+      throw LispReaderException("lisp_cxr()", __FILE__, __LINE__);
 
   return obj;
 }
@@ -879,7 +893,8 @@ lisp_list_length (lisp_object_t *obj)
 
   while (obj != 0)
     {
-      assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
+      if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
+        throw LispReaderException("lisp_list_length()", __FILE__, __LINE__);
 
       ++length;
       obj = obj->v.cons.cdr;
@@ -893,8 +908,10 @@ lisp_list_nth_cdr (lisp_object_t *obj, int index)
 {
   while (index > 0)
     {
-      assert(obj != 0);
-      assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
+      if (obj == 0)
+        throw LispReaderException("lisp_list_nth_cdr()", __FILE__, __LINE__);
+      if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
+        throw LispReaderException("lisp_list_nth_cdr()", __FILE__, __LINE__);
 
       --index;
       obj = obj->v.cons.cdr;
@@ -908,7 +925,8 @@ lisp_list_nth (lisp_object_t *obj, int index)
 {
   obj = lisp_list_nth_cdr(obj, index);
 
-  assert(obj != 0);
+  if (obj == 0)
+    throw LispReaderException("lisp_list_nth()", __FILE__, __LINE__);
 
   return obj->v.cons.car;
 }
@@ -990,18 +1008,43 @@ lisp_dump (lisp_object_t *obj, FILE *out)
       break;
 
     default :
-      assert(0);
+      throw LispReaderException("lisp_dump()", __FILE__, __LINE__);
     }
 }
 
 using namespace std;
 
 LispReader::LispReader (lisp_object_t* l)
-    : lst (l)
+    : owner(0), lst (l)
+{
+}
+
+LispReader::~LispReader()
 {
-  //std::cout << "LispReader: " << std::flush;
-  //lisp_dump(lst, stdout);
-  //std::cout << std::endl;
+  if(owner)
+    lisp_free(owner);
+}
+
+LispReader*
+LispReader::load(const std::string& filename, const std::string& toplevellist)
+{
+  lisp_object_t* obj = lisp_read_from_file(filename);
+
+  if(obj->type == LISP_TYPE_EOF || obj->type == LISP_TYPE_PARSE_ERROR) {
+    lisp_free(obj);
+    throw LispReaderException("LispReader::load", __FILE__, __LINE__);
+  }
+
+  if(toplevellist != lisp_symbol(lisp_car(obj))) {
+    lisp_car(obj);
+    throw LispReaderException("LispReader::load wrong toplevel symbol",
+        __FILE__, __LINE__);
+  }
+  
+  LispReader* reader = new LispReader(lisp_cdr(obj));  
+  reader->owner = obj;
+
+  return reader;
 }
 
 lisp_object_t*
@@ -1034,118 +1077,169 @@ LispReader::search_for(const char* name)
 }
 
 bool
-LispReader::read_int (const char* name, int* i)
+LispReader::read_int (const char* name, int& i)
 {
   lisp_object_t* obj = search_for (name);
-  if (obj)
-    {
-      *i = lisp_integer(lisp_car(obj));
-      return true;
-    }
-  return false;
+  if(!obj)
+    return false;
+      
+  if (!lisp_integer_p(lisp_car(obj)))
+    return false;
+  
+  i = lisp_integer(lisp_car(obj));
+  return true;
 }
 
 bool
-LispReader::read_float (const char* name, float* f)
+LispReader::read_lisp(const char* name, lisp_object_t*& b)
 {
   lisp_object_t* obj = search_for (name);
-  if (obj)
-    {
-      *f = lisp_real(lisp_car(obj));
-      return true;
-    }
-  return false;
+  if (!obj)
+    return false;
+  
+  b = obj;
+  return true;
 }
 
-bool
-LispReader::read_bool (const char* name, bool* b)
+LispReader*
+LispReader::read_lisp(const char* name)
 {
-  lisp_object_t* obj = search_for (name);
-  if (obj)
-    {
-      *b = lisp_boolean(lisp_car(obj));
-      return true;
-    }
-  return false;
-}
+  lisp_object_t* obj = search_for(name);
+  if(!obj)
+    return 0;
 
-LispWriter::LispWriter (const char* name)
-{
-  lisp_objs.push_back(lisp_make_symbol (name));
+  return new LispReader(obj);
 }
 
-void
-LispWriter::append (lisp_object_t* obj)
+bool
+LispReader::read_float (const char* name, float& f)
 {
-  lisp_objs.push_back(obj);
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
+  
+  if (!lisp_real_p(lisp_car(obj)) && !lisp_integer_p(lisp_car(obj)))
+    st_abort("LispReader expected type real at token: ", name);
+  
+  f = lisp_real(lisp_car(obj));
+  return true;
 }
 
-lisp_object_t*
-LispWriter::make_list3 (lisp_object_t* a, lisp_object_t* b, lisp_object_t* c)
+bool
+LispReader::read_string_vector (const char* name, std::vector<std::string>& vec)
 {
-  return lisp_make_cons (a, lisp_make_cons(b, lisp_make_cons(c, lisp_nil())));
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
+
+  vec.clear();
+  while(!lisp_nil_p(obj))
+  {
+    if (!lisp_string_p(lisp_car(obj)))
+      st_abort("LispReader expected type string at token: ", name);
+    vec.push_back(lisp_string(lisp_car(obj)));
+    obj = lisp_cdr(obj);
+  }
+  return true;
 }
 
-lisp_object_t*
-LispWriter::make_list2 (lisp_object_t* a, lisp_object_t* b)
+bool
+LispReader::read_int_vector (const char* name, std::vector<int>& vec)
 {
-  return lisp_make_cons (a, lisp_make_cons(b, lisp_nil()));
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
+
+  vec.clear();
+  while(!lisp_nil_p(obj))
+  {
+    if (!lisp_integer_p(lisp_car(obj)))
+      st_abort("LispReader expected type integer at token: ", name);
+    vec.push_back(lisp_integer(lisp_car(obj)));
+    obj = lisp_cdr(obj);
+  }
+  return true;
 }
 
-void
-LispWriter::write_float (const char* name, float f)
+bool
+LispReader::read_int_vector (const char* name, std::vector<unsigned int>& vec)
 {
-  append(make_list2 (lisp_make_symbol (name),
-                     lisp_make_real(f)));
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
+
+  vec.clear();
+  while(!lisp_nil_p(obj))
+  {
+    if (!lisp_integer_p(lisp_car(obj)))
+      st_abort("LispReader expected type integer at token: ", name);
+    vec.push_back(lisp_integer(lisp_car(obj)));
+    obj = lisp_cdr(obj);
+  }
+  return true;
 }
 
-void
-LispWriter::write_int (const char* name, int i)
+bool
+LispReader::read_char_vector (const char* name, std::vector<char>& vec)
 {
-  append(make_list2 (lisp_make_symbol (name),
-                     lisp_make_integer(i)));
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
+  vec.clear();
+  while(!lisp_nil_p(obj))
+  {
+    vec.push_back(*lisp_string(lisp_car(obj)));
+    obj = lisp_cdr(obj);
+  }
+  return true;
 }
 
-void
-LispWriter::write_string (const char* name, const char* str)
+bool
+LispReader::read_string (const char* name, std::string& str)
 {
-  append(make_list2 (lisp_make_symbol (name),
-                     lisp_make_string(str)));
-}
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
 
-void
-LispWriter::write_symbol (const char* name, const char* symname)
-{
-  append(make_list2 (lisp_make_symbol (name),
-                     lisp_make_symbol(symname)));
+  if (!lisp_string_p(lisp_car(obj)))
+    st_abort("LispReader expected type string at token: ", name);
+  str = lisp_string(lisp_car(obj));
+  return true;
 }
 
-void
-LispWriter::write_lisp_obj(const char* name, lisp_object_t* lst)
+bool
+LispReader::read_bool (const char* name, bool& b)
 {
-  append(make_list2 (lisp_make_symbol (name),
-                     lst));
+  lisp_object_t* obj = search_for (name);
+  if (!obj)
+    return false;
+  
+  if (!lisp_boolean_p(lisp_car(obj)))
+    st_abort("LispReader expected type bool at token: ", name);
+  b = lisp_boolean(lisp_car(obj));
+  return true;
 }
 
-void
-LispWriter::write_boolean (const char* name, bool b)
+lisp_object_t*
+LispReader::get_lisp()
 {
-  append(make_list2 (lisp_make_symbol (name),
-                     lisp_make_boolean(b)));
+  return lst;
 }
 
-lisp_object_t*
-LispWriter::create_lisp ()
+lisp_object_t* lisp_read_from_file(const std::string& filename)
 {
-  lisp_object_t* lisp_obj = lisp_nil();
+  FILE* in = fopen(filename.c_str(), "r");
 
-  for(std::vector<lisp_object_t*>::reverse_iterator i = lisp_objs.rbegin ();
-      i != lisp_objs.rend (); ++i)
-    {
-      lisp_obj = lisp_make_cons (*i, lisp_obj);
-    }
-  lisp_objs.clear();
+  if(!in)
+    return 0;
 
-  return lisp_obj;
+  lisp_stream_t stream;
+  lisp_stream_init_file(&stream, in);
+  lisp_object_t* obj = lisp_read(&stream);
+  fclose(in);
+
+  return obj;
 }
 
+// EOF //