Fixed parser to ensure that map key-type and set value-type are comparable (ie primivitive or a typedef that resolves to a primitive) at parse-time
to avoid unsightly errors at stub/skel compilation time.


			       


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664748 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/src/parser.py b/compiler/src/parser.py
index af428fb..1f45f86 100644
--- a/compiler/src/parser.py
+++ b/compiler/src/parser.py
@@ -34,8 +34,11 @@
 	return str(self.start)+": error: "+self.message
 
 class SyntaxError(Error):
-    def __init__(self, lexToken):
-	Error.__init__(self, lexToken.lineno, lexToken.lineno, "syntax error "+str(lexToken.value))
+    def __init__(self, yaccSymbol):
+	if isinstance(yaccSymbol, yacc.YaccSymbol):
+	    Error.__init__(self, yaccSymbol.lineno, yaccSymbol.lineno, "syntax error "+str(yaccSymbol.value))
+	else:
+	    Error.__init__(self, 1, 1, "syntax error "+str(yaccSymbol))
 
 class SymanticsError(Error):
 
@@ -79,6 +82,17 @@
 	    result+="="+str(self.id)
 	return result
 
+
+def toCanonicalType(ttype):
+    if isinstance(ttype, TypeDef):
+	return toCanonicalType(ttype.definitionType)
+    else:
+	return ttype
+
+def isComparableType(ttype):
+    ttype = toCanonicalType(ttype)
+    return isinstance(ttype, PrimitiveType) or isinstance(ttype, Enum)
+
 class Type(Definition):
     """ Abstract Type definition """
 
@@ -105,7 +119,6 @@
     def __init__(self, name):
 	Type.__init__(self, None, name)
 
-
 STOP_TYPE =  PrimitiveType("stop")
 VOID_TYPE =  PrimitiveType("void")
 BOOL_TYPE = PrimitiveType("bool")
@@ -151,6 +164,9 @@
     def __init__(self, symbols, name):
 	Type.__init__(self, symbols, name)
 
+    def validate(self):
+	return True
+
 class Map(CollectionType):
 
     def __init__(self, symbols, keyType, valueType):
@@ -158,12 +174,20 @@
 	self.keyType = keyType
 	self.valueType = valueType
 
+    def validate(self):
+	if not isComparableType(self.keyType):
+	    raise ErrorException([SymanticsError(self, "key type \""+str(self.keyType)+"\" is not a comparable type.")])
+
 class Set(CollectionType):
 
     def __init__(self, symbols, valueType):
 	CollectionType.__init__(self, symbols, "set<"+valueType.name+">")
 	self.valueType = valueType
 
+    def validate(self):
+	if not isComparableType(self.valueType):
+	    raise ErrorException([SymanticsError(self, "value type \""+str(self.valueType)+"\" is not a comparable type.")])
+
 class List(CollectionType):
 
     def __init__(self, symbols, valueType):
@@ -452,6 +476,8 @@
                     collection.keyType = self.getType(collection, collection.keyType)
 
                 collection.valueType = self.getType(collection, collection.valueType)
+		
+		collection.validate()
             
             except ErrorException, e:
                 errors+= e.errors
@@ -481,7 +507,6 @@
 
 	if len(errors):
 	    raise ErrorException(errors)
-		    
 
 class Parser(object):
     
@@ -870,7 +895,11 @@
 	p[0] = List(p, p[3])
 
     def p_error(self, p):
-        self.errors.append(SyntaxError(p))
+	# p_error is called with an empty token if eof was encountered unexpectedly.
+	if not p:
+	    self.errors.append(SyntaxError("Unexpected end of file"))
+	else:
+	    self.errors.append(SyntaxError(p))
 
     def pdebug(self, name, p):
 	if self.debug: