Thrift: docstring revamp step 1.

Summary:
Allow constants to be documented.
Now any "Definition" can be documented, so we can move the docstring stuff
up to a a higher node in the parse tree.

Reviewed By: mcslee

Test Plan:
Recompiled thrift.
Checked out DocTest.thrift and a few other thrifts.

Revert Plan: ok


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665200 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index ed38b07..76676f3 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -433,10 +433,11 @@
 
 /**
  * Dumps docstrings to stdout
- * Only works for typedefs and whole program
+ * Only works for top-level definitions and the whole program doc
+ * (i.e., not enum constants, struct fields, or functions.
  */
 void dump_docstrings(t_program* program) {
-  string progdoc = g_program->get_doc();
+  string progdoc = program->get_doc();
   if (!progdoc.empty()) {
     printf("Whole program doc:\n%s\n", progdoc.c_str());
   }
@@ -445,7 +446,47 @@
   for (t_iter = typedefs.begin(); t_iter != typedefs.end(); ++t_iter) {
     t_typedef* td = *t_iter;
     if (td->has_doc()) {
-      printf("%s:\n%s\n", td->get_name().c_str(), td->get_doc().c_str());
+      printf("typedef %s:\n%s\n", td->get_name().c_str(), td->get_doc().c_str());
+    }
+  }
+  const vector<t_enum*>& enums = program->get_enums();
+  vector<t_enum*>::const_iterator e_iter;
+  for (e_iter = enums.begin(); e_iter != enums.end(); ++e_iter) {
+    t_enum* en = *e_iter;
+    if (en->has_doc()) {
+      printf("enum %s:\n%s\n", en->get_name().c_str(), en->get_doc().c_str());
+    }
+  }
+  const vector<t_const*>& consts = program->get_consts();
+  vector<t_const*>::const_iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    t_const* co = *c_iter;
+    if (co->has_doc()) {
+      printf("const %s:\n%s\n", co->get_name().c_str(), co->get_doc().c_str());
+    }
+  }
+  const vector<t_struct*>& structs = program->get_structs();
+  vector<t_struct*>::const_iterator s_iter;
+  for (s_iter = structs.begin(); s_iter != structs.end(); ++s_iter) {
+    t_struct* st = *s_iter;
+    if (st->has_doc()) {
+      printf("struct %s:\n%s\n", st->get_name().c_str(), st->get_doc().c_str());
+    }
+  }
+  const vector<t_struct*>& xceptions = program->get_xceptions();
+  vector<t_struct*>::const_iterator x_iter;
+  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+    t_struct* xn = *x_iter;
+    if (xn->has_doc()) {
+      printf("xception %s:\n%s\n", xn->get_name().c_str(), xn->get_doc().c_str());
+    }
+  }
+  const vector<t_service*>& services = program->get_services();
+  vector<t_service*>::const_iterator v_iter;
+  for (v_iter = services.begin(); v_iter != services.end(); ++v_iter) {
+    t_service* sv = *v_iter;
+    if (sv->has_doc()) {
+      printf("service %s:\n%s\n", sv->get_name().c_str(), sv->get_doc().c_str());
     }
   }
 }
diff --git a/compiler/cpp/src/parse/t_const.h b/compiler/cpp/src/parse/t_const.h
index 9cae45b..dadcfd2 100644
--- a/compiler/cpp/src/parse/t_const.h
+++ b/compiler/cpp/src/parse/t_const.h
@@ -18,7 +18,7 @@
  *
  * @author Mark Slee <mcslee@facebook.com>
  */
-class t_const {
+class t_const : public t_doc {
  public:
   t_const(t_type* type, std::string name, t_const_value* value) :
     type_(type),
diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy
index 1ad0c35..5f7e3b9 100644
--- a/compiler/cpp/src/thrifty.yy
+++ b/compiler/cpp/src/thrifty.yy
@@ -37,6 +37,7 @@
   int            iconst;
   double         dconst;
   bool           tbool;
+  t_doc*         tdoc;
   t_type*        ttype;
   t_base_type*   tbase;
   t_typedef*     ttypedef;
@@ -48,7 +49,7 @@
   t_service*     tservice;
   t_function*    tfunction;
   t_field*       tfield;
-  char*          tdoc;
+  char*          dtext;
 }
 
 /**
@@ -56,7 +57,7 @@
  */
 %token<id>     tok_identifier
 %token<id>     tok_literal
-%token<tdoc>   tok_doctext
+%token<dtext>  tok_doctext
 
 /**
  * Constant values
@@ -130,6 +131,7 @@
 %type<ttype>     SetType
 %type<ttype>     ListType
 
+%type<tdoc>      Definition
 %type<ttype>     TypeDefinition
 
 %type<ttypedef>  Typedef
@@ -173,7 +175,7 @@
 %type<tstruct>   XsdAttributes
 %type<id>        CppType
 
-%type<tdoc>      DocTextOptional
+%type<dtext>     DocTextOptional
 
 %%
 
@@ -273,9 +275,12 @@
     }
 
 DefinitionList:
-  DefinitionList Definition
+  DefinitionList DocTextOptional Definition
     {
       pdebug("DefinitionList -> DefinitionList Definition");
+      if ($2 != NULL && $3 != NULL) {
+        $3->set_doc($2);
+      }
     }
 |
     {
@@ -289,6 +294,7 @@
       if (g_parse_mode == PROGRAM) {
         g_program->add_const($1);
       }    
+      $$ = $1;
     }
 | TypeDefinition
     {
@@ -299,6 +305,7 @@
           g_parent_scope->add_type(g_parent_prefix + $1->get_name(), $1);
         }
       }
+      $$ = $1;
     }
 | Service
     {
@@ -310,6 +317,7 @@
         }
         g_program->add_service($1);
       }
+      $$ = $1;
     }
 
 TypeDefinition:
@@ -350,14 +358,11 @@
     }
 
 Typedef:
-  DocTextOptional tok_typedef DefinitionType tok_identifier 
+  tok_typedef DefinitionType tok_identifier 
     {
       pdebug("TypeDef -> tok_typedef DefinitionType tok_identifier");
-      t_typedef *td = new t_typedef(g_program, $3, $4);
+      t_typedef *td = new t_typedef(g_program, $2, $3);
       $$ = td;
-      if ($1 != NULL) {
-        td->set_doc($1);
-      }
     }
 
 DocTextOptional:
@@ -380,14 +385,11 @@
     {}
 
 Enum:
-  DocTextOptional tok_enum tok_identifier '{' EnumDefList '}'
+  tok_enum tok_identifier '{' EnumDefList '}'
     {
       pdebug("Enum -> tok_enum tok_identifier { EnumDefList }");
-      $$ = $5;
-      $$->set_name($3);
-      if ($1 != NULL) {
-        $$->set_doc($1);
-      }
+      $$ = $4;
+      $$->set_name($2);
     }
 
 EnumDefList:
@@ -432,13 +434,10 @@
     }
 
 Senum:
-  DocTextOptional tok_senum tok_identifier '{' SenumDefList '}'
+  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);
-      }
+      $$ = new t_typedef(g_program, $4, $2);
     }
 
 SenumDefList:
@@ -565,15 +564,12 @@
     }
 
 Struct:
-  DocTextOptional tok_struct tok_identifier XsdAll '{' FieldList '}'
+  tok_struct tok_identifier XsdAll '{' FieldList '}'
     {
       pdebug("Struct -> tok_struct tok_identifier { FieldList }");
-      $6->set_name($3);
-      if ($1 != NULL) {
-        $6->set_doc($1);
-      }
-      $6->set_xsd_all($4);
-      $$ = $6;
+      $5->set_name($2);
+      $5->set_xsd_all($3);
+      $$ = $5;
       y_field_val = -1;
     }
 
@@ -628,15 +624,12 @@
     }
 
 Service:
-  DocTextOptional tok_service tok_identifier Extends '{' FunctionList '}'
+  tok_service tok_identifier Extends '{' FunctionList '}'
     {
       pdebug("Service -> tok_service tok_identifier { FunctionList }");
-      $$ = $6;
-      $$->set_name($3);
-      $$->set_extends($4);
-      if ($1 != NULL) {
-        $$->set_doc($1);
-      }
+      $$ = $5;
+      $$->set_name($2);
+      $$->set_extends($3);
     }
 
 Extends: