c2hal: allow c++11 enum class and enum struct

Test: `make c2hal` and run c2hal on c2hal/test/test.h

Change-Id: I76654b37d44578027b5cb2348d02296b3af45d77
diff --git a/c2hal/c2hal_l.ll b/c2hal/c2hal_l.ll
index 089dba6..9873de2 100644
--- a/c2hal/c2hal_l.ll
+++ b/c2hal/c2hal_l.ll
@@ -191,6 +191,7 @@
 "struct"                          { return STRUCT; }
 "union"                           { return UNION; }
 "enum"                            { return ENUM; }
+"class"                           { return CLASS; }
 "const"                           { return CONST; }
 "typedef"                         { return TYPEDEF; }
 "void"                            { return VOID; }
diff --git a/c2hal/c2hal_y.yy b/c2hal/c2hal_y.yy
index 3e34e07..596b211 100644
--- a/c2hal/c2hal_y.yy
+++ b/c2hal/c2hal_y.yy
@@ -76,7 +76,7 @@
 %glr-parser
 
 /* These have to do with the fact that
- * struct_or_enum_declaration and enum_declaration
+ * struct_or_union_declaration and enum_declaration
  * both start with STRUCT/UNION/ENUM opt_id
  * and type_qualifiers contain these.
  */
@@ -88,6 +88,7 @@
 %token STRUCT
 %token UNION
 %token ENUM
+%token CLASS
 %token CONST
 %token VOID
 %token INCLUDE
@@ -113,6 +114,8 @@
 %right '~' '!' UMINUS UPLUS
 %left ARRAY_SUBSCRIPT FUNCTION_CALL
 
+%right STRUCT ENUM
+
 %token<str> ID
 %token<str> COMMENT
 %token<str> VALUE
@@ -127,6 +130,7 @@
 %type<expression> expr
 %type<expressions> args
 %type<type> type
+%type<type> opt_enum_base_type
 %type<qualifier> type_qualifier
 %type<qualifiers> type_qualifiers
 %type<declaration> declaration
@@ -301,18 +305,34 @@
     | ','
     ;
 
+enum_key
+    : ENUM
+    | ENUM CLASS  /* c++11 */
+    | ENUM STRUCT /* c++11 */
+    ;
+
+opt_enum_base_type
+    : /* EMPTY */ { $$ = NULL; }
+    | ':' type    { $$ = $2; }
+    ;
+
 enum_declaration
-    : ENUM opt_id
+    : enum_key opt_id
       {
         $<str>$ = strdup(get_last_comment().c_str());
       }
-                           '{' enum_vars '}' opt_id
+                        opt_enum_base_type '{' enum_vars '}' opt_id
       {
-        $$ = new CompositeDeclaration(Type::Qualifier::ENUM, $2, $5);
+        $$ = new CompositeDeclaration(Type::Qualifier::ENUM, $2, $6);
         $$->setComment($<str>3);
 
-        if(!std::string($7).empty()) {
-          $$->setName($7);
+        if($4) {
+          $$->setEnumTypeName($4->decorateName(""));
+          delete $4;
+        }
+
+        if(!std::string($8).empty()) {
+          $$->setName($8);
         }
       }
     ;
@@ -499,7 +519,7 @@
     | CONST                   { $$ = new Type::Qualifier(Type::Qualifier::CONST); }
     | ID                      { $$ = new Type::Qualifier(Type::Qualifier::ID, $1); }
     | '<' type '>'            { $$ = new Type::Qualifier(Type::Qualifier::GENERICS, $2); }
-    | ENUM                    { $$ = new Type::Qualifier(Type::Qualifier::ENUM); }
+    | enum_key                { $$ = new Type::Qualifier(Type::Qualifier::ENUM); }
     | struct_or_union         { $$ = new Type::Qualifier($1); }
     ;
 
diff --git a/c2hal/test/test.h b/c2hal/test/test.h
index 49d3345..e53e296 100644
--- a/c2hal/test/test.h
+++ b/c2hal/test/test.h
@@ -367,6 +367,18 @@
    EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
 };
 
+
+namespace myspace {
+enum class enum_class : int32_t {
+    great,
+};
+} // namespace myspace
+
+enum struct enum_struct {
+    great,
+};
+
+
 __END_DECLS
 
 #endif