Thrift supports the "senum" type now

Summary: Enumerated lists of strings, enforced only in XSD

Reviewed By: xsd


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664987 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc
index 4c31d6c..fb39753 100644
--- a/compiler/cpp/src/generate/t_xsd_generator.cc
+++ b/compiler/cpp/src/generate/t_xsd_generator.cc
@@ -26,8 +26,23 @@
   indent(s_xsd_types_) <<
     "<xsd:simpleType name=\"" << ttypedef->get_name() << "\">" << endl;
   indent_up();
-  indent(s_xsd_types_) <<
-    "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\" />" << endl;
+  if (ttypedef->get_type()->is_string() && ((t_base_type*)ttypedef->get_type())->is_string_enum()) {
+    indent(s_xsd_types_) <<
+      "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\">" << endl;
+    indent_up();
+    const vector<string>& values = ((t_base_type*)ttypedef->get_type())->get_string_enum_vals();
+    vector<string>::const_iterator v_iter;
+    for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) {
+      indent(s_xsd_types_) <<
+        "<xsd:enumeration value=\"" << (*v_iter) << "\" />" << endl;
+    }
+    indent_down();
+    indent(s_xsd_types_) <<
+      "</xsd:restriction>" << endl;
+  } else {
+    indent(s_xsd_types_) <<
+      "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\" />" << endl;
+  }
   indent_down();
   indent(s_xsd_types_) <<
     "</xsd:simpleType>" << endl << endl;
diff --git a/compiler/cpp/src/parse/t_base_type.h b/compiler/cpp/src/parse/t_base_type.h
index b0d41d6..c9548bb 100644
--- a/compiler/cpp/src/parse/t_base_type.h
+++ b/compiler/cpp/src/parse/t_base_type.h
@@ -28,7 +28,8 @@
   t_base_type(std::string name, t_base base) :
     t_type(name),
     base_(base),
-    string_list_(false) {}
+    string_list_(false),
+    string_enum_(false) {}
     
   t_base get_base() const {
     return base_;
@@ -50,13 +51,32 @@
     return base_ == TYPE_STRING && string_list_;
   }
 
+  void set_string_enum(bool val) {
+    string_enum_ = true;
+  }
+
+  bool is_string_enum() const {
+    return base_ == TYPE_STRING && string_enum_;
+  }
+
+  void add_string_enum_val(std::string val) {
+    string_enum_vals_.push_back(val);
+  }
+
+  const std::vector<std::string>& get_string_enum_vals() const {
+    return string_enum_vals_;
+  }
+
   bool is_base_type() const {
     return true;
   }
     
  private:
   t_base base_;
+
   bool string_list_;
+  bool string_enum_;
+  std::vector<std::string> string_enum_vals_;
 };
 
 #endif
diff --git a/compiler/cpp/src/thriftl.ll b/compiler/cpp/src/thriftl.ll
index 593df10..abda14f 100644
--- a/compiler/cpp/src/thriftl.ll
+++ b/compiler/cpp/src/thriftl.ll
@@ -77,6 +77,7 @@
 "double"        { return tok_double;        }
 "string"        { return tok_string;        }
 "slist"         { return tok_slist;         }
+"senum"         { return tok_senum;         }
 "map"           { return tok_map;           }
 "list"          { return tok_list;          }
 "set"           { return tok_set;           }
diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy
index 19f1ba8..519f20d 100644
--- a/compiler/cpp/src/thrifty.yy
+++ b/compiler/cpp/src/thrifty.yy
@@ -33,6 +33,7 @@
   double         dconst;
   bool           tbool;
   t_type*        ttype;
+  t_base_type*   tbase;
   t_typedef*     ttypedef;
   t_enum*        tenum;
   t_enum_value*  tenumv;
@@ -82,6 +83,7 @@
 %token tok_byte
 %token tok_string
 %token tok_slist
+%token tok_senum
 %token tok_i16
 %token tok_i32
 %token tok_i64
@@ -136,6 +138,10 @@
 %type<tenum>     EnumDefList
 %type<tenumv>    EnumDef
 
+%type<ttypedef>  Senum
+%type<tbase>     SenumDefList
+%type<id>        SenumDef
+
 %type<tconst>    Const
 %type<tconstv>   ConstValue
 %type<tconstv>   ConstList
@@ -304,6 +310,13 @@
         g_program->add_enum($1);
       }
     }
+| Senum
+    {
+      pdebug("TypeDefinition -> Senum");
+      if (g_parse_mode == PROGRAM) {
+        g_program->add_typedef($1);
+      }
+    }
 | Struct
     {
       pdebug("TypeDefinition -> Struct");
@@ -341,6 +354,13 @@
       $$ = NULL; 
     }
     
+CommaOrSemicolonOptional:
+  ','
+    {}
+| ';'
+    {}
+|
+    {}
 
 Enum:
   DocTextOptional tok_enum tok_identifier '{' EnumDefList '}'
@@ -353,14 +373,6 @@
       }
     }
 
-CommaOrSemicolonOptional:
-  ','
-    {}
-| ';'
-    {}
-|
-    {}
-
 EnumDefList:
   EnumDefList EnumDef
     {
@@ -396,6 +408,37 @@
       }
     }
 
+Senum:
+  DocTextOptional tok_senum tok_identifier '{' SenumDefList '}'
+    {
+      pdebug("Senum -> tok_senum tok_identifier { SenumDefList }");
+      $$ = new t_typedef(g_program, $5, $3);
+      if ($1 != NULL) {
+        $$->set_doc($1);
+      }
+    }
+
+SenumDefList:
+  SenumDefList SenumDef
+    {
+      pdebug("SenumDefList -> SenumDefList SenumDef");
+      $$ = $1;
+      $$->add_string_enum_val($2);
+    }
+|
+    {
+      pdebug("SenumDefList -> ");
+      $$ = new t_base_type("string", t_base_type::TYPE_STRING);
+      $$->set_string_enum(true);
+    }
+
+SenumDef:
+  tok_literal CommaOrSemicolonOptional
+    {
+      pdebug("SenumDef -> tok_literal");
+      $$ = $1;
+    }
+
 Const:
   tok_const FieldType tok_identifier '=' ConstValue CommaOrSemicolonOptional
     {