Added namespace declaration
      
    Added namespace declaration to thrift grammar
    
    Modified C++ code generator to produce equivalent C++ namespace for thrift namespace if specified
    


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664755 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/src/cpp_generator.py b/compiler/src/cpp_generator.py
index d518230..8003f1e 100644
--- a/compiler/src/cpp_generator.py
+++ b/compiler/src/cpp_generator.py
@@ -18,9 +18,11 @@
 #define ${source}_types_h_ 1
 
 #include <Thrift.h>
+${namespacePrefix}
 """)
 
 CPP_TYPES_FOOTER = Template("""
+${namespaceSuffix}
 #endif // !defined(${source}_types_h_)
 """)
 
@@ -33,16 +35,23 @@
 #include <protocol/TProtocol.h>
 #include <transport/TTransport.h>
 #include \"${source}_types.h\"
+
+${namespacePrefix}
 """)
 
 CPP_SERVICES_FOOTER = Template("""
+${namespaceSuffix}
 #endif // !defined(${source}_h_)""")
 
 CPP_IMPL_HEADER = Template(HEADER_COMMENT+"""
 #include \"${source}.h\"
+
+${namespacePrefix}
 """)
 
-CPP_IMPL_FOOTER = Template("")
+CPP_IMPL_FOOTER = Template("""
+${namespaceSuffix}
+""")
 
 def cpp_debug(arg):
     print(arg)
@@ -123,7 +132,19 @@
     SetType : "std::set",
 }
 
-def typeToCTypeDeclaration(ttype):
+def toCNamespacePrefix(namespace):
+    if not namespace:
+	return ""
+    else:
+	return string.join(["namespace "+token + " {" for token in string.split(namespace, ".")], " ")
+
+def toCNamespaceSuffix(namespace):
+    if not namespace:
+	return ""
+    else:
+	return string.join(["}" for token in string.split(namespace, ".")], "")
+
+def toCTypeDeclaration(ttype):
     """ Converts the thrift IDL type to the corresponding C/C++ type.  Note that if ttype is FieldType, this function c
 converts to type declaration followed by field name, i.e. \"string string_thing\""""
 
@@ -135,10 +156,10 @@
         result = CPP_CONTAINER_MAP[type(ttype)]+"<"
         
         if isinstance(ttype, MapType):
-            result+= typeToCTypeDeclaration(ttype.keyType)+", "+ typeToCTypeDeclaration(ttype.valueType)
+            result+= toCTypeDeclaration(ttype.keyType)+", "+ toCTypeDeclaration(ttype.valueType)
 
         elif isinstance(ttype, SetType) or isinstance(ttype, ListType):
-            result+= typeToCTypeDeclaration(ttype.valueType)
+            result+= toCTypeDeclaration(ttype.valueType)
 
         else:
             raise Exception, "Unknown Collection Type "+str(ttype)
@@ -157,13 +178,13 @@
         return ttype.name;
 
     elif isinstance(ttype, Function):
-        result = typeToCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([typeToCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
+        result = toCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([toCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
 	if len(ttype.exceptions()):
-	    result+= " throw("+string.join([typeToCTypeDeclaration(exceptions.type) for exceptions in ttype.exceptions()], ", ")+")"
+	    result+= " throw("+string.join([toCTypeDeclaration(exceptions.type) for exceptions in ttype.exceptions()], ", ")+")"
 	return result
 
     elif isinstance(ttype, Field):
-        return typeToCTypeDeclaration(ttype.type)+ " "+ttype.name
+        return toCTypeDeclaration(ttype.type)+ " "+ttype.name
 
     else:
         raise Exception, "Unknown type "+str(ttype)
@@ -171,7 +192,7 @@
 def toTypeDefDefinition(typedef):
     """ Converts a thrift typedef to a C/C++ typedef """
 
-    return "typedef "+typeToCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
+    return "typedef "+toCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
 
 def toEnumDefinition(enum):
     """ Converts a thrift enum to a C/C++ enum """
@@ -198,7 +219,7 @@
 
     for field in struct.fieldList:
 	if toCanonicalType(field.type) != VOID_TYPE:
-	    result += "    "+typeToCTypeDeclaration(field)+";\n"
+	    result += "    "+toCTypeDeclaration(field)+";\n"
 
     result+= "    struct {\n"
 
@@ -247,7 +268,7 @@
 def toServiceInterfaceDeclaration(service, debugp=None):
     """Converts a thrift service definition into a C++ abstract base class"""
 
-    functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
+    functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
 
     return CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
 
@@ -350,7 +371,7 @@
 """)
 
 def toWireType(ttype):
-    """Converts a thrift type to the corresponding wire type.   This differs from typeToCTypeDeclaration in that it reduces typedefs
+    """Converts a thrift type to the corresponding wire type.   This differs from toCTypeDeclaration in that it reduces typedefs
 to their canonical form and converts enums to signedf 32 bit integers"""
 
     if isinstance(ttype, PrimitiveType):
@@ -454,11 +475,11 @@
     """Converts a thrift service method declaration into a server method-call processoror function"""
     result = ""
 
-    argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
+    argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
 
     argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
 
-    resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
+    resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
 
     resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
 
@@ -478,7 +499,7 @@
     if len(exceptions) > 0:
 	functionCallPrefix= "try {"+functionCallPrefix
 
-	functionCallSuffix = functionCallSuffix+"} "+string.join(["catch("+typeToCTypeDeclaration(exceptions[ix].type)+"& e"+str(ix)+") {__result."+exceptions[ix].name+" = e"+str(ix)+"; __result.__isset."+exceptions[ix].name+"  = true;}" for ix in range(len(exceptions))], "")
+	functionCallSuffix = functionCallSuffix+"} "+string.join(["catch("+toCTypeDeclaration(exceptions[ix].type)+"& e"+str(ix)+") {__result."+exceptions[ix].name+" = e"+str(ix)+"; __result.__isset."+exceptions[ix].name+"  = true;}" for ix in range(len(exceptions))], "")
 
     functionCall = functionCallPrefix+functionCall+functionCallSuffix
 
@@ -511,29 +532,29 @@
 
 def toClientDeclaration(service, debugp=None):
 
-    functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
+    functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
 
     return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
 
 def toClientFunctionDefinition(servicePrefix, function, debugp=None):
     """Converts a thrift service method declaration to a client stub implementation"""
 
-    returnDeclaration = typeToCTypeDeclaration(function.returnType())
+    returnDeclaration = toCTypeDeclaration(function.returnType())
 
-    argsDeclaration = string.join([typeToCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
+    argsDeclaration = string.join([toCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
 
-    exceptionDeclaration = string.join([typeToCTypeDeclaration(exception.type) for exception in function.exceptions()], ", ")
+    exceptionDeclaration = string.join([toCTypeDeclaration(exception.type) for exception in function.exceptions()], ", ")
 
     if len(exceptionDeclaration)> 0:
 	exceptionDeclaration = "throw("+exceptionDeclaration+")"
 
-    argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
+    argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
 
     argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
 
     argsToStruct= string.join(["    __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
     
-    resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
+    resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
 
     resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
 
@@ -637,11 +658,11 @@
 
     basename = toBasename(filename)
 
-    cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime()))
+    cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
 
     cfile.write(toDefinitions(program.definitions))
 
-    cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename))
+    cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
 
     cfile.close()
 
@@ -672,7 +693,7 @@
 
     basename = toBasename(filename)
 
-    cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime()))
+    cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
 
     services = []
 
@@ -686,7 +707,7 @@
 
         cfile.write(toServiceDeclaration(service))
 
-    cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename))
+    cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
 
     cfile.close()
 
@@ -789,10 +810,10 @@
         return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
 
     elif isinstance(ttype, TypedefType):
-        return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
+        return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
 
     elif isinstance(ttype, EnumType):
-        return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
+        return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
 
     else:
         raise Exception, "Unknown type "+str(ttype)
@@ -816,10 +837,10 @@
         return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
 
     elif isinstance(ttype, TypedefType):
-        return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
+        return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
 
     elif isinstance(ttype, EnumType):
-        return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
+        return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
 
     else:
         raise Exception, "Unknown type "+str(ttype)
@@ -901,10 +922,10 @@
     valueReaderCall= toReaderCall("elem", collection.valueType)
 
     if isinstance(collection, MapType):
-        return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
-                                                  keyType=typeToCTypeDeclaration(collection.keyType),
+        return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
+                                                  keyType=toCTypeDeclaration(collection.keyType),
                                                   keyReaderCall=keyReaderCall,
-                                                  valueType=typeToCTypeDeclaration(collection.valueType),
+                                                  valueType=toCTypeDeclaration(collection.valueType),
                                                   valueReaderCall=valueReaderCall)
 
     else:
@@ -913,9 +934,9 @@
 	else:
 	    insert="insert"
 
-        return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
+        return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
                                                    valueReaderCall=valueReaderCall,
-                                                   valueType=typeToCTypeDeclaration(collection.valueType),
+                                                   valueType=toCTypeDeclaration(collection.valueType),
 						   insert=insert)
 
 
@@ -932,16 +953,16 @@
 	valueWriterCall= toWriterCall("*ix", collection.valueType)
 
     if isinstance(collection, MapType):
-        return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
-                                                  keyType=typeToCTypeDeclaration(collection.keyType),
+        return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
+                                                  keyType=toCTypeDeclaration(collection.keyType),
                                                   keyWriterCall=keyWriterCall,
-                                                  valueType=typeToCTypeDeclaration(collection.valueType),
+                                                  valueType=toCTypeDeclaration(collection.valueType),
                                                   valueWriterCall=valueWriterCall)
 
     else:
-        return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
+        return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
                                                    valueWriterCall=valueWriterCall,
-                                                   valueType=typeToCTypeDeclaration(collection.valueType))
+                                                   valueType=toCTypeDeclaration(collection.valueType))
 
 
 CPP_READ_STRUCT_DEFINITION = Template("""
@@ -1007,7 +1028,7 @@
         fieldSwitch+= "            case "+str(field.id)+": "
         fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
 
-    return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(struct), fieldSwitch=fieldSwitch)
+    return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(struct), fieldSwitch=fieldSwitch)
 
 
 def toStructWriterDefinition(struct):
@@ -1025,7 +1046,7 @@
 
     fieldWriterCalls = "    "+string.join(fieldWriterCalls, "\n    ")
 
-    return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=typeToCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
+    return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
     
 CPP_WRITE_RESULT_STRUCT_DEFINITION = Template("""
 uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
@@ -1054,7 +1075,7 @@
 
     fieldWriterCalls = "    "+string.join(fieldWriterCalls, "\n    else ")
 
-    return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=typeToCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
+    return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
 
 def toReaderDefinition(ttype):
     """Converts thrift type to a reader function definition"""
@@ -1213,7 +1234,7 @@
 
     basename = toBasename(filename)
 
-    cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime()))
+    cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
 
     cfile.write(toIOMethodImplementations(program))
 
@@ -1221,7 +1242,7 @@
 
     cfile.write(toClientDefinition(program))
 
-    cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename))
+    cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
 
     cfile.close()
 
diff --git a/compiler/src/parser.py b/compiler/src/parser.py
index 5500f1c..8bd96f2 100644
--- a/compiler/src/parser.py
+++ b/compiler/src/parser.py
@@ -384,11 +384,19 @@
 
 class Program(object):
 
-    def __init__(self, symbols=None, name="", definitions=None, serviceMap=None, typedefMap=None, enumMap=None, structMap=None, collectionMap=None,
+    def __init__(self, symbols=None, name="", 
+		 namespace="",
+		 definitions=None, 
+		 serviceMap=None, 
+		 typedefMap=None, 
+		 enumMap=None, structMap=None, 
+		 collectionMap=None,
                  primitiveMap=None):
 
 	self.name = name
 
+	self.namespace = namespace
+
         if not definitions:
             definitions = []
         self.definitions = definitions
@@ -527,6 +535,12 @@
 	if len(errors):
 	    raise ErrorException(errors)
 
+    def validateNamespace(self,  namespace):
+
+	if self.namespace != "":
+	    raise ErrorException([SymanticsError, self, "namespace already defined as \""+self.namespace+"\""])
+	self.namespace = namespace
+
 class Parser(object):
     
     reserved = ("BYTE",
@@ -541,6 +555,7 @@
 		"I64",
 		"LIST", 
 		"MAP",
+		"NAMESPACE",
 		"SERVICE", 
 		"SET",
                 # "STATIC",
@@ -560,14 +575,14 @@
 
     tokens = reserved + (
 	# Literals (identifier, integer constant, float constant, string constant, char const)
-	'ID', 'ICONST', 'SCONST', 'FCONST', 
+	'ID', 'ICONST', # 'SCONST', 'FCONST', 
 	# Operators default=, optional*, variable...
 	'ASSIGN',  #'OPTIONAL', 'ELLIPSIS',
 	# Delimeters ( ) { } < > , . ; :
 	'LPAREN', 'RPAREN',
 	'LBRACE', 'RBRACE',
 	'LANGLE', 'RANGLE',
-	'COMMA' #, 'PERIOD', 'SEMI' , 'COLON'
+	'COMMA', 'PERIOD' #, 'SEMI' , 'COLON'
 	)
 
     precendence = ()
@@ -596,7 +611,7 @@
     t_LBRACE           = r'\{'
     t_RBRACE           = r'\}'
     t_COMMA            = r','
-#    t_PERIOD           = r'\.'
+    t_PERIOD           = r'\.'
 #    t_SEMI             = r';'
 #    t_COLON            = r':'
 #    t_ELLIPSIS         = r'\.\.\.'
@@ -605,10 +620,10 @@
     t_ICONST = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?'
 
     # Floating literal
-    t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
+#    t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
 
     # String literal
-    t_SCONST = r'\"([^\\\n]|(\\.))*?\"'
+#    t_SCONST = r'\"([^\\\n]|(\\.))*?\"'
 
     # Comments
     def t_comment(self, t):
@@ -681,6 +696,11 @@
 	except ErrorException, e:
 	    self.errors+= e.errors
 
+    def p_definition_6(self, p):
+	'definition : namespace'
+	self.pdebug("p_definition_6", p)
+	p[0] = p[1]
+
     def p_typedef(self, p):
 	'typedef : TYPEDEF definitiontype ID'
 	self.pdebug("p_typedef", p)
@@ -741,6 +761,26 @@
 	except ErrorException, e:
 	    self.errors+= e.errors
 
+    def p_namespace(self, p):
+	'namespace :  NAMESPACE namespacespecifier'
+	self.pdebug("p_struct", p)
+	p[0] = p[2]
+
+	try:
+	    self.program.validateNamespace(p[0])
+	except ErrorException, e:
+	    self.errors+= e.errors
+
+    def p_namespacespecifier_1(self, p):
+	'namespacespecifier : ID'
+	self.pdebug("p_namespacespecifier", p)
+	p[0] = p[1]
+	
+    def p_namespacespecifier_2(self, p):
+	'namespacespecifier : ID PERIOD namespacespecifier'
+	self.pdebug("p_namespacespecifier", p)
+	p[0] = p[1]+"."+p[3]
+
     def p_service(self, p):
 	'service : SERVICE ID LBRACE functionlist RBRACE'
 	self.pdebug("p_service", p)
diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift
index 178f4df..abbeb0c 100644
--- a/test/ThriftTest.thrift
+++ b/test/ThriftTest.thrift
@@ -1,3 +1,5 @@
+//namespace thrift.test
+
 enum Numberz
 {
   ONE = 1,