Added type checking for __custom functions
[supertux.git] / tools / miniswig / parser.yy
index e66b58c..03fb00c 100644 (file)
@@ -1,10 +1,11 @@
 %{
+#include <config.h>
 
 #include <iostream>
 #include <sstream>
 #include <stdexcept>
-#include "tree.h"
-#include "globals.h"
+#include "tree.hpp"
+#include "globals.hpp"
 
 %}
 
@@ -15,6 +16,7 @@
     float       fval;
     Class*      _class;
     Function*   function;
+    Field*      field;
     Type*       type;
     AtomicType* atomic_type;
     Namespace*  _namespace;
@@ -30,9 +32,10 @@ bool search_down = true;
 Namespace* search_namespace = 0;
 Namespace* current_namespace = 0;
 static Class* current_class = 0;
-static Function* currentFunction = 0;
+static Function* current_function = 0;
 static Type* current_type = 0;
-static ClassMember::Visbility current_visibility;
+static Field* current_field = 0;
+static ClassMember::Visibility current_visibility;
 
 class ParseError : public std::exception
 {
@@ -40,7 +43,8 @@ public:
     ParseError(const std::string& message) throw()
     {
         std::ostringstream msg;
-        msg << "Parse error in line " << yylineno << ": "
+        msg << "Parse error in '" << current_file
+            << "' line " << getCurrentLine() << ": "
             << message;
         this->message = msg.str();
     }
@@ -62,10 +66,12 @@ private:
 %token <str>  T_STRING
 %token <str>  T_ID
 %token <atomic_type> T_ATOMIC_TYPE
-%token <_namespace> T_NAMESPACEREF;
+%token <_namespace> T_NAMESPACEREF
 %token T_CLASS
 %token T_STRUCT
 %token T_STATIC
+%token T_SUSPEND
+%token T_CUSTOM
 %token T_CONST
 %token T_UNSIGNED
 %token T_SIGNED
@@ -73,9 +79,7 @@ private:
 %token T_BOOL
 %token T_CHAR
 %token T_SHORT
-%token T_INT
 %token T_LONG
-%token T_FLOAT
 %token T_DOUBLE
 %token T_PUBLIC
 %token T_PROTECTED
@@ -87,6 +91,7 @@ private:
 %type <function> function_declaration
 %type <function> constructor_declaration;
 %type <function> destructor_declaration;
+%type <field> field_declaration;
 %type <type>   type
 %type <atomic_type> type_identifier
 
@@ -132,22 +137,53 @@ namespace_member:
     | function_declaration
         { current_namespace->functions.push_back($1); }
     | namespace_declaration
+    | field_declaration
+        { current_namespace->fields.push_back($1); }
 ;  
 
 class_declaration:
-    T_CLASS T_ID '{' 
+    T_CLASS T_ID 
         {
             current_class = new Class();
             current_class->name = $2;
             free($2);
+            current_class->docu_comment = last_docucomment;
+            last_docucomment = "";
             current_visibility = ClassMember::PROTECTED;
         }
-    class_body '}' ';'
+    superclass_list '{' class_body '}' ';'
         {
             $$ = current_class;
         }
 ;
 
+superclass_list:
+    /* empty */
+    | ':' superclasses
+;
+
+superclasses:
+      superclass
+    | superclasses ',' superclass
+;
+
+superclass:
+    superclass_visibility type_identifier
+        {
+            Class* superclass = dynamic_cast<Class*> ($2);
+            if(superclass == 0)
+                throw ParseError("SuperClass is not a Class type");
+            current_class->super_classes.push_back(superclass);
+            superclass->sub_classes.push_back(current_class);
+        }
+;
+
+superclass_visibility:
+    T_PUBLIC
+    | T_PROTECTED
+    | T_PRIVATE
+;
+
 class_body: /* empty */
         | class_body class_body_element
 ;
@@ -169,7 +205,11 @@ class_body_element:
                 $1->visibility = current_visibility;
                 current_class->members.push_back($1);
             }
-        | variable_declaration
+        | field_declaration
+            {
+                $1->visibility = current_visibility;
+                current_class->members.push_back($1);
+            }
 ;
 
 visibility_change:
@@ -184,46 +224,106 @@ visibility_change:
 constructor_declaration:    
     T_ID '('
         {
-            currentFunction = new Function();
-            currentFunction->type = Function::CONSTRUCTOR;
+            current_function = new Function();
+            current_function->type = Function::CONSTRUCTOR;
+            current_function->docu_comment = last_docucomment;
+            last_docucomment = "";
             free($1);
         }
     parameter_list ')' ';'
         {
-            $$ = currentFunction;
+            $$ = current_function;
         }
 ;
 
 destructor_declaration:
-    '~' T_ID '(' ')' ';'
+    '~' T_ID '(' ')' abstract_declaration ';'
         {
-            currentFunction = new Function();
-            currentFunction->type = Function::DESTRUCTOR;
+            current_function = new Function();
+            current_function->type = Function::DESTRUCTOR;
+            current_function->docu_comment = last_docucomment;
+            last_docucomment = "";
             free($2);
-            $$ = currentFunction;
+            $$ = current_function;
         }
 ;
 
-variable_declaration:
-    type T_ID ';'
+field_declaration:
+    type T_ID 
+        {
+            current_field = new Field();
+            current_field->type = $1;
+            current_field->docu_comment = last_docucomment;
+            last_docucomment = "";
+            current_field->name = $2;
+            free($2);
+        }
+    maybe_const_initialisation ';'
+        {
+            $$ = current_field;
+        }
 ;
 
+maybe_const_initialisation:
+    /* empty */
+    | '=' T_INT
+        {
+            if(current_field->type->atomic_type == &BasicType::FLOAT) {
+                current_field->const_float_value = (float) $2;
+            } else {
+                current_field->const_int_value = $2;
+            }
+            current_field->has_const_value = true;
+        }
+    | '=' T_FLOAT
+        {
+            current_field->const_float_value = $2;
+            current_field->has_const_value = true;
+        }
+    | '=' T_STRING
+        {
+            current_field->const_string_value = $2;
+            current_field->has_const_value = true;
+        }
+;          
+
 function_declaration:
     type T_ID '(' 
         {
-            currentFunction = new Function();
-            currentFunction->type = Function::FUNCTION;
-            currentFunction->return_type = *($1);
+            current_function = new Function();
+            current_function->type = Function::FUNCTION;
+            current_function->return_type = *($1);
             delete $1;
-            currentFunction->name = $2;
+            current_function->name = $2;
             free($2);
+            current_function->docu_comment = last_docucomment;
+            last_docucomment = "";
         }                           
-    parameter_list ')' ';'
+    parameter_list ')' function_attributes abstract_declaration ';'
         {
-            $$ = currentFunction;
+            $$ = current_function;
         }
 ;
 
+function_attributes:
+    /* empty */
+    | T_CONST function_attributes
+    | T_CUSTOM '(' T_STRING ')' function_attributes
+      {
+        current_function->parameter_spec = $3;
+        current_function->custom = true;
+      }
+    | T_SUSPEND function_attributes
+      {
+        current_function->suspend = true;
+      }
+;
+
+abstract_declaration:
+    /* empty */
+    | '=' T_INT
+;
+
 parameter_list:
     /* empty */
     | parameters
@@ -240,16 +340,16 @@ parameter:
             Parameter parameter;
             parameter.type = *($1);
             delete $1;
-            currentFunction->parameters.push_back(parameter);
+            current_function->parameters.push_back(parameter);
         }
     | type T_ID
         {
             Parameter parameter;
             parameter.type = *($1);
             delete $1;
-            parameter.name = *($2);
+            parameter.name = $2;
             free($2);
-            currentFunction->parameters.push_back(parameter);
+            current_function->parameters.push_back(parameter);
         }
 ;
 
@@ -270,9 +370,13 @@ prefix_type_modifiers:
 
 prefix_type_modifier:
     T_UNSIGNED
+        { current_type->_unsigned = true; }
     | T_SIGNED
+        { current_type->_unsigned = false; }
     | T_STATIC
+        { current_type->_static = true; }
     | T_CONST
+        { current_type->_const = true; }
 ;
 
 postfix_type_modifiers:
@@ -313,7 +417,6 @@ atomic_type:
 type_identifier:
     T_ATOMIC_TYPE
         {
-            // search for type in current compilation unit...
             $$ = $1;
         }
     | namespace_refs "::" T_ATOMIC_TYPE