From 27340eb5cd735dcaebb0a3a83ec3fcaab2e36544 Mon Sep 17 00:00:00 2001 From: Marc Slemko Date: Thu, 10 Aug 2006 20:45:55 +0000 Subject: [PATCH] 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 --- compiler/src/parser.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/compiler/src/parser.py b/compiler/src/parser.py index af428fbc..1f45f867 100644 --- a/compiler/src/parser.py +++ b/compiler/src/parser.py @@ -34,8 +34,11 @@ class Error(object): 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 @@ class Identifier(Definition): 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 @@ class PrimitiveType(Type): 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 @@ class CollectionType(Type): 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 @@ class Map(CollectionType): 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 @@ class Program(object): 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 @@ class Program(object): if len(errors): raise ErrorException(errors) - class Parser(object): @@ -870,7 +895,11 @@ class Parser(object): 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: -- 2.17.1