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: