blob: 3b0bdc174d8cd729abc7a0e427f5f204ea5fe8ac [file] [log] [blame]
Marc Slemkoc0e07a22006-08-09 23:34:57 +00001#!python
Marc Slemkob2039e72006-08-09 01:00:17 +00002""" Thrift IDL parser/compiler
3
4 This parser uses the Python PLY LALR parser generator to build a parser for the Thrift IDL grammar.
5
6 If a compiles \"thyc\" file exists for a given source \"thrift\" file it computes a hash of the file and determines
7 if if it is the source of the \"thyc\" file. If so, it simply returns the parse tree previously computed, otherwise it
8 parses the source and generates a new \"thyc\" file (assuming of course the source file contains no errors.)
9
10 When the parser encounters import statements it searches for corresponding \"thrift\" or \"thyc\" files in paths corresponding to
11 the specified namespace.
12
13 Author(s): Mark Slee(mclee@facebook.com), Marc Kwiatkowski (marc@facebook.com)
14
15 $Id:
16"""
17
18import lex
19import os
20import pickle
21import string
Marc Slemkob2039e72006-08-09 01:00:17 +000022import yacc
23
24class Error(object):
25
26 def __init__(self, start=0, end=0, message=""):
27 if len(message) == 0:
28 raise Exception, "NO MESSAGE"
29 self.message = message
30 self.start = start
31 self.end = end
32
33 def __str__(self):
34 return str(self.start)+": error: "+self.message
35
36class SyntaxError(Error):
Marc Slemko27340eb2006-08-10 20:45:55 +000037 def __init__(self, yaccSymbol):
38 if isinstance(yaccSymbol, yacc.YaccSymbol):
39 Error.__init__(self, yaccSymbol.lineno, yaccSymbol.lineno, "syntax error "+str(yaccSymbol.value))
40 else:
41 Error.__init__(self, 1, 1, "syntax error "+str(yaccSymbol))
Marc Slemkob2039e72006-08-09 01:00:17 +000042
43class SymanticsError(Error):
44
45 def __init__(self, definition, message):
46 Error.__init__(self, definition.start, definition.end, message)
47 self.definition = definition
48
49 def __str__(self):
50 return str(self.start)+": error: "+self.message
51
52class ErrorException(Exception):
53
54 def __init__(self, errors=None):
55 self.errors = errors
56
57class Definition(object):
58 """ Abstract thrift IDL definition unit """
59
60 def __init__(self, symbols=None, name="", id=None):
61 if symbols:
62 self.lines(symbols)
63 self.name = name
64 self.id = id
65
66 def validate(self):
67 pass
68
69 def lines(self, symbols):
70 self.start = symbols.lineno(1)
71 self.end = symbols.lineno(len(symbols) - 1)
72
73class Identifier(Definition):
74 """ An Identifier - name and optional integer id """
75
76 def __init__(self, symbols, name, id=None):
77 Definition.__init__(self, symbols, name, id)
78
79 def __str__(self):
80 result = self.name
81 if self.id != 0:
82 result+="="+str(self.id)
83 return result
84
Marc Slemko27340eb2006-08-10 20:45:55 +000085
86def toCanonicalType(ttype):
Marc Slemko5b126d62006-08-11 23:03:42 +000087 if isinstance(ttype, TypedefType):
Marc Slemko27340eb2006-08-10 20:45:55 +000088 return toCanonicalType(ttype.definitionType)
89 else:
90 return ttype
91
92def isComparableType(ttype):
93 ttype = toCanonicalType(ttype)
Marc Slemko5b126d62006-08-11 23:03:42 +000094 return isinstance(ttype, PrimitiveType) or isinstance(ttype, EnumType)
Marc Slemko27340eb2006-08-10 20:45:55 +000095
Marc Slemkob2039e72006-08-09 01:00:17 +000096class Type(Definition):
97 """ Abstract Type definition """
98
99 def __init__(self, symbols, name):
100 Definition.__init__(self, symbols, name)
101 self.name = name
102
103 def __str__(self):
104 return self.name
105
Marc Slemko5b126d62006-08-11 23:03:42 +0000106class TypedefType(Type):
Marc Slemkob2039e72006-08-09 01:00:17 +0000107
108 def __init__(self, symbols, name, definitionType):
109 Type.__init__(self, symbols, name)
110 self.definitionType = definitionType
111
112 def __str__(self):
113 return self.name+"<"+str(self.name)+", "+str(self.definitionType)+">"
114
115""" Primitive Types """
116
117class PrimitiveType(Type):
118
119 def __init__(self, name):
120 Type.__init__(self, None, name)
121
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000122STOP_TYPE = PrimitiveType("stop")
Marc Slemkob2039e72006-08-09 01:00:17 +0000123VOID_TYPE = PrimitiveType("void")
124BOOL_TYPE = PrimitiveType("bool")
Marc Slemkobf4fd192006-08-15 21:29:39 +0000125STRING_TYPE = PrimitiveType("utf7")
126UTF7_TYPE = STRING_TYPE
Marc Slemkob2039e72006-08-09 01:00:17 +0000127UTF8_TYPE = PrimitiveType("utf8")
128UTF16_TYPE = PrimitiveType("utf16")
129BYTE_TYPE = PrimitiveType("u08")
130I08_TYPE = PrimitiveType("i08")
131I16_TYPE = PrimitiveType("i16")
132I32_TYPE = PrimitiveType("i32")
133I64_TYPE = PrimitiveType("i64")
134U08_TYPE = PrimitiveType("u08")
135U16_TYPE = PrimitiveType("u16")
136U32_TYPE = PrimitiveType("u32")
137U64_TYPE = PrimitiveType("u64")
138FLOAT_TYPE = PrimitiveType("float")
Marc Slemkod8b10512006-08-14 23:30:37 +0000139DOUBLE_TYPE = PrimitiveType("double")
Marc Slemkob2039e72006-08-09 01:00:17 +0000140
141PRIMITIVE_MAP = {
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000142 "stop" : STOP_TYPE,
Marc Slemkob2039e72006-08-09 01:00:17 +0000143 "void" : VOID_TYPE,
144 "bool" : BOOL_TYPE,
145 "string": UTF7_TYPE,
146 "utf7": UTF7_TYPE,
147 "utf8": UTF8_TYPE,
148 "utf16": UTF16_TYPE,
149 "byte" : U08_TYPE,
150 "i08": I08_TYPE,
151 "i16": I16_TYPE,
152 "i32": I32_TYPE,
153 "i64": I64_TYPE,
154 "u08": U08_TYPE,
155 "u16": U16_TYPE,
156 "u32": U32_TYPE,
157 "u64": U64_TYPE,
Marc Slemkod8b10512006-08-14 23:30:37 +0000158 "float": FLOAT_TYPE,
159 "double": DOUBLE_TYPE
Marc Slemkob2039e72006-08-09 01:00:17 +0000160}
161
162""" Collection Types """
163
164class CollectionType(Type):
165
166 def __init__(self, symbols, name):
167 Type.__init__(self, symbols, name)
168
Marc Slemko27340eb2006-08-10 20:45:55 +0000169 def validate(self):
170 return True
171
Marc Slemko5b126d62006-08-11 23:03:42 +0000172class MapType(CollectionType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000173
174 def __init__(self, symbols, keyType, valueType):
175 CollectionType.__init__(self, symbols, "map<"+keyType.name+","+valueType.name +">")
176 self.keyType = keyType
177 self.valueType = valueType
178
Marc Slemko27340eb2006-08-10 20:45:55 +0000179 def validate(self):
180 if not isComparableType(self.keyType):
181 raise ErrorException([SymanticsError(self, "key type \""+str(self.keyType)+"\" is not a comparable type.")])
182
Marc Slemko5b126d62006-08-11 23:03:42 +0000183class SetType(CollectionType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000184
185 def __init__(self, symbols, valueType):
186 CollectionType.__init__(self, symbols, "set<"+valueType.name+">")
187 self.valueType = valueType
188
Marc Slemko27340eb2006-08-10 20:45:55 +0000189 def validate(self):
190 if not isComparableType(self.valueType):
191 raise ErrorException([SymanticsError(self, "value type \""+str(self.valueType)+"\" is not a comparable type.")])
192
Marc Slemko5b126d62006-08-11 23:03:42 +0000193class ListType(CollectionType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000194
195 def __init__(self, symbols, valueType):
196 CollectionType.__init__(self, symbols, "list<"+valueType.name+">")
197 self.valueType = valueType
198
Marc Slemko5b126d62006-08-11 23:03:42 +0000199class EnumType(Definition):
Marc Slemkob2039e72006-08-09 01:00:17 +0000200
201 def __init__(self, symbols, name, enumDefs):
202 Definition.__init__(self, symbols, name)
203 self.enumDefs = enumDefs
204
205 def validate(self):
206 ids = {}
207 names = {}
208 errors = []
209
210 for enumDef in self.enumDefs:
211
212 if enumDef.name in names:
213 errors.append(SymanticsError(enumDef, self.name+"."+str(enumDef.name)+" already defined at line "+str(names[enumDef.name].start)))
214 else:
215 names[enumDef.name] = enumDef
216
217 if enumDef.id != None:
218 oldEnumDef = ids.get(enumDef.id)
219 if oldEnumDef:
220 errors.append(SymanticsError(enumDef, "enum "+self.name+" \""+str(enumDef.name)+"\" uses constant already assigned to \""+oldEnumDef.name+"\""))
221 else:
222 ids[enumDef.id] = enumDef
223
224 if len(errors):
225 raise ErrorException(errors)
226
227 def assignId(enumDef, currentId, ids):
228 'Finds the next available id number for an enum definition'
229
230 id= currentId + 1
231
232 while id in ids:
233 id += 1
234
235 enumDef.id = id
236
237 ids[enumDef.id] = enumDef
238
239 # assign ids for all enum defs with unspecified ids
240
241 currentId = 0
242
243 for enumDef in self.enumDefs:
244 if not enumDef.id:
245 assignId(enumDef, currentId, ids)
246 currentId = enumDef.id
247
248 def __repr__(self):
249 return str(self)
250
251 def __str__(self):
252 return self.name+"<"+string.join(map(lambda enumDef: str(enumDef), self.enumDefs), ", ")
253
254class EnumDef(Definition):
255
256 def __init__(self, symbols, name, id=None):
257 Definition.__init__(self, symbols, name, id)
258
259 def __repr__(self):
260 return str(self)
261
262 def __str__(self):
263 result = self.name
264 if self.id:
265 result+= ":"+str(self.id)
266 return result
267
268
269class Field(Definition):
270
271 def __init__(self, symbols, type, identifier):
272 Definition.__init__(self, symbols, identifier.name, identifier.id)
273 self.type = type
274 self.identifier = identifier
275
276 def __str__(self):
277 return "<"+str(self.type)+", "+str(self.identifier)+">"
278
279def validateFieldList(fieldList):
280
281 errors = []
282 names = {}
283 ids = {}
284
285 for field in fieldList:
286
287 if field.name in names:
288 oldField = names[field.name]
289 errors.append(SymanticsError(field, "field \""+field.name+"\" already defined at "+str(oldField.start)))
290 else:
291 names[field.name] = field
292
293 if field.id != None:
294 oldField = ids.get(field.id)
295 if oldField:
296 errors.append(SymanticsError(field, "field \""+field.name+"\" uses constant already assigned to \""+oldField.name+"\""))
297 else:
298 ids[field.id] = field
299
300 if len(errors):
301 raise ErrorException(errors)
302
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000303 def assignId(field, currentId, ids):
304 'Finds the next available id number for a field'
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000305 id = currentId - 1
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000306
307 while id in ids:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000308 id-= 1
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000309
310 field.id = id
311
312 ids[field.id] = field
313
314 return id
315
316 # assign ids for all fields with unspecified ids
317
318 currentId = 0
319
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000320 for field in fieldList:
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000321 if not field.id:
322 currentId = assignId(field, currentId, ids)
323
Marc Slemko5b126d62006-08-11 23:03:42 +0000324class StructType(Type):
Marc Slemkob2039e72006-08-09 01:00:17 +0000325
326 def __init__(self, symbols, name, fieldList):
327 Type.__init__(self, symbols, name)
328 self.fieldList = fieldList
329
330 def validate(self):
331 validateFieldList(self.fieldList)
332
333 def __str__(self):
334 return self.name+"<"+string.join(map(lambda a: str(a), self.fieldList), ", ")+">"
335
Marc Slemkod8b10512006-08-14 23:30:37 +0000336class ExceptionType(StructType):
337
338 def __init__(self, symbols, name, fieldList):
339 StructType.__init__(self, symbols, name, fieldList)
340
Marc Slemkob2039e72006-08-09 01:00:17 +0000341class Function(Definition):
342
Marc Slemko5b126d62006-08-11 23:03:42 +0000343 def __init__(self, symbols, name, resultStruct, argsStruct, ):
Marc Slemkob2039e72006-08-09 01:00:17 +0000344 Definition.__init__(self, symbols, name)
Marc Slemko5b126d62006-08-11 23:03:42 +0000345 self.resultStruct = resultStruct
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000346 self.argsStruct = argsStruct
Marc Slemkob2039e72006-08-09 01:00:17 +0000347
348 def validate(self):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000349 validateFieldList(self.argsStruct.fieldList)
Marc Slemkod8b10512006-08-14 23:30:37 +0000350 validateFieldList(self.resultStruct.fieldList)
Marc Slemko5b126d62006-08-11 23:03:42 +0000351
352 def args(self):
353 return self.argsStruct.fieldList
354
355 def returnType(self):
356 return self.resultStruct.fieldList[0].type
Marc Slemkod8b10512006-08-14 23:30:37 +0000357
358 def exceptions(self):
359 return self.resultStruct.fieldList[1:]
Marc Slemkob2039e72006-08-09 01:00:17 +0000360
361 def __str__(self):
Marc Slemkod8b10512006-08-14 23:30:37 +0000362 return self.name+"("+str(self.argsStruct)+") => "+str(self.resultStruct)
Marc Slemkob2039e72006-08-09 01:00:17 +0000363
364class Service(Definition):
365
366 def __init__(self, symbols, name, functionList):
367 Definition.__init__(self, symbols, name)
368 self.functionList = functionList
369
370 def validate(self):
371
372 errors = []
373 functionNames = {}
374 for function in self.functionList:
375 if function.name in functionNames:
376 oldFunction = functionName[function.name]
377 errors.append(SymanticsError(function, "function "+function.name+" already defined at "+str(oldFunction.start)))
378
379 if len(errors):
380 raise ErrorException(errors)
381
382 def __str__(self):
383 return self.name+"("+string.join(map(lambda a: str(a), self.functionList), ", ")+")"
384
385class Program(object):
386
Marc Slemko17859852006-08-15 00:21:31 +0000387 def __init__(self, symbols=None, name="",
388 namespace="",
389 definitions=None,
390 serviceMap=None,
391 typedefMap=None,
392 enumMap=None, structMap=None,
393 collectionMap=None,
Marc Slemkob2039e72006-08-09 01:00:17 +0000394 primitiveMap=None):
395
396 self.name = name
397
Marc Slemko17859852006-08-15 00:21:31 +0000398 self.namespace = namespace
399
Marc Slemkob2039e72006-08-09 01:00:17 +0000400 if not definitions:
401 definitions = []
402 self.definitions = definitions
403
404 if not serviceMap:
405 serviceMap = {}
406 self.serviceMap = serviceMap
407
408 if not typedefMap:
409 typedefMap = {}
410 self.typedefMap = typedefMap
411
412 if not enumMap:
413 enumMap = {}
414 self.enumMap = enumMap
415
416 if not structMap:
417 structMap = {}
418 self.structMap = structMap
419
420 if not collectionMap:
421 collectionMap = {}
422 self.collectionMap = collectionMap
423
424 if not primitiveMap:
425 primitiveMap = PRIMITIVE_MAP
426 self.primitiveMap = primitiveMap
427
428 def addDefinition(self, definition, definitionMap, definitionTypeName):
429
430 oldDefinition = definitionMap.get(definition.name)
431 if oldDefinition:
432 raise ErrorException([SymanticsError(definition, definitionTypeName+" "+definition.name+" is already defined at "+str(oldDefinition.start))])
433 else:
434 definitionMap[definition.name] = definition
435
436 # keep an ordered list of definitions so that stub/skel generators can determine the original order
437
438 self.definitions.append(definition)
439
440 def addStruct(self, struct):
441 self.addDefinition(struct, self.structMap, "struct")
442
443 def addTypedef(self, typedef):
444 self.addDefinition(typedef, self.typedefMap, "typedef")
445
446 def addEnum(self, enum):
447 self.addDefinition(enum, self.enumMap, "enum")
448
449 def addService(self, service):
450 self.addDefinition(service, self.serviceMap, "service")
451
452 def addCollection(self, collection):
453 if collection.name in self.collectionMap:
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000454 return self.collectionMap[collection.name]
Marc Slemkob2039e72006-08-09 01:00:17 +0000455 else:
456 self.collectionMap[collection.name] = collection
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000457 return collection
Marc Slemkob2039e72006-08-09 01:00:17 +0000458
459 def getType(self, parent, symbol):
460 """ Get the type definition for a symbol"""
461
462 typeName = None
463
464 if isinstance(symbol, Type):
465 return symbol
466 elif isinstance(symbol, Field):
467 typeName = symbol.type.name
468 elif isinstance(symbol, Identifier):
469 typeName = symbol.name
470 else:
471 raise ErrorException([SymanticsError(parent, "unknown symbol \""+str(symbol)+"\"")])
472
473 for map in (self.primitiveMap, self.collectionMap, self.typedefMap, self.enumMap, self.structMap):
474 if typeName in map:
475 return map[typeName]
476
477 raise ErrorException([SymanticsError(parent, "\""+typeName+"\" is not defined.")])
478
479 def hasType(self, parent, symbol):
480 """ Determine if a type definition exists for the symbol"""
481
482 return self.getType(parent, symbol) == True
483
484 def validate(self):
485
486 errors = []
487
488 # Verify that struct fields types, collection key and element types, and typedef defined types exists and replaces
489 # type names with references to the type objects
490
491 for struct in self.structMap.values():
492 for field in struct.fieldList:
493 try:
494 field.type = self.getType(struct, field)
495 except ErrorException, e:
496 errors+= e.errors
497
498 for collection in self.collectionMap.values():
499 try:
Marc Slemko5b126d62006-08-11 23:03:42 +0000500 if isinstance(collection, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000501 collection.keyType = self.getType(collection, collection.keyType)
502
503 collection.valueType = self.getType(collection, collection.valueType)
Marc Slemko27340eb2006-08-10 20:45:55 +0000504
505 collection.validate()
Marc Slemkob2039e72006-08-09 01:00:17 +0000506
507 except ErrorException, e:
508 errors+= e.errors
509
510 for typedef in self.typedefMap.values():
511 try:
512 typedef.definitionType = self.getType(self, typedef.definitionType)
513
514 except ErrorException, e:
515 errors+= e.errors
516
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000517 # Verify that service function result and arg list types exist and replace type name with reference to definition
Marc Slemkob2039e72006-08-09 01:00:17 +0000518
519 for service in self.serviceMap.values():
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000520
Marc Slemkob2039e72006-08-09 01:00:17 +0000521 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000522
523 for field in function.resultStruct.fieldList:
524 try:
525 field.type = self.getType(function, field)
526 except ErrorException, e:
527 errors+= e.errors
Marc Slemkob2039e72006-08-09 01:00:17 +0000528
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000529 for field in function.argsStruct.fieldList:
Marc Slemkob2039e72006-08-09 01:00:17 +0000530 try:
531 field.type = self.getType(function, field)
532 except ErrorException, e:
533 errors+= e.errors
534
535 if len(errors):
536 raise ErrorException(errors)
Marc Slemkob2039e72006-08-09 01:00:17 +0000537
Marc Slemko17859852006-08-15 00:21:31 +0000538 def validateNamespace(self, namespace):
539
540 if self.namespace != "":
541 raise ErrorException([SymanticsError, self, "namespace already defined as \""+self.namespace+"\""])
542 self.namespace = namespace
543
Marc Slemkob2039e72006-08-09 01:00:17 +0000544class Parser(object):
545
546 reserved = ("BYTE",
547 # "CONST",
548 "DOUBLE",
549 "ENUM",
Marc Slemkod8b10512006-08-14 23:30:37 +0000550 "EXCEPTION",
Marc Slemkob2039e72006-08-09 01:00:17 +0000551 # "EXTENDS",
552 "I08",
553 "I16",
554 "I32",
555 "I64",
556 "LIST",
557 "MAP",
Marc Slemko17859852006-08-15 00:21:31 +0000558 "NAMESPACE",
Marc Slemkob2039e72006-08-09 01:00:17 +0000559 "SERVICE",
560 "SET",
561 # "STATIC",
562 "STRING",
563 "STRUCT",
564 # "SYNCHRONIZED",
Marc Slemkod8b10512006-08-14 23:30:37 +0000565 "THROWS",
Marc Slemkob2039e72006-08-09 01:00:17 +0000566 "TYPEDEF",
567 "U08",
568 "U16",
569 "U32",
570 "U64",
571 "UTF16",
572 "UTF8",
573 "VOID"
574 )
575
576 tokens = reserved + (
577 # Literals (identifier, integer constant, float constant, string constant, char const)
Marc Slemko17859852006-08-15 00:21:31 +0000578 'ID', 'ICONST', # 'SCONST', 'FCONST',
Marc Slemkob2039e72006-08-09 01:00:17 +0000579 # Operators default=, optional*, variable...
580 'ASSIGN', #'OPTIONAL', 'ELLIPSIS',
581 # Delimeters ( ) { } < > , . ; :
582 'LPAREN', 'RPAREN',
583 'LBRACE', 'RBRACE',
584 'LANGLE', 'RANGLE',
Marc Slemko17859852006-08-15 00:21:31 +0000585 'COMMA', 'PERIOD' #, 'SEMI' , 'COLON'
Marc Slemkob2039e72006-08-09 01:00:17 +0000586 )
587
588 precendence = ()
589
590 reserved_map = {}
591
592 for r in reserved:
593 reserved_map[r.lower()] = r
594
595 def t_ID(self, t):
596 r'[A-Za-z_][\w_]*'
597 t.type = self.reserved_map.get(t.value,"ID")
598 return t
599
600 # Completely ignored characters
601 t_ignore = ' \t\x0c'
602
603# t_OPTIONAL = r'\*'
604 t_ASSIGN = r'='
605
606 # Delimeters
607 t_LPAREN = r'\('
608 t_RPAREN = r'\)'
609 t_LANGLE = r'\<'
610 t_RANGLE = r'\>'
611 t_LBRACE = r'\{'
612 t_RBRACE = r'\}'
613 t_COMMA = r','
Marc Slemko17859852006-08-15 00:21:31 +0000614 t_PERIOD = r'\.'
Marc Slemkob2039e72006-08-09 01:00:17 +0000615# t_SEMI = r';'
616# t_COLON = r':'
617# t_ELLIPSIS = r'\.\.\.'
618
619 # Integer literal
620 t_ICONST = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?'
621
622 # Floating literal
Marc Slemko17859852006-08-15 00:21:31 +0000623# t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
Marc Slemkob2039e72006-08-09 01:00:17 +0000624
625 # String literal
Marc Slemko17859852006-08-15 00:21:31 +0000626# t_SCONST = r'\"([^\\\n]|(\\.))*?\"'
Marc Slemkob2039e72006-08-09 01:00:17 +0000627
628 # Comments
629 def t_comment(self, t):
630 r'(?:/\*(.|\n)*?\*/)|(?://[^\n]*\n)'
631 t.lineno += t.value.count('\n')
632
633 def t_error(self, t):
634 print "Illegal character %s" % repr(t.value[0])
635 t.skip(1)
636
637 # Newlines
638 def t_newline(self, t):
639 r'\n+'
640 t.lineno += t.value.count("\n")
641
642 def p_program(self, p):
643 'program : definitionlist'
644 pass
645
646 def p_definitionlist_1(self, p):
647 'definitionlist : definitionlist definition'
648 pass
649
650 def p_definitionlist_2(self, p):
651 'definitionlist :'
652 pass
653
654 def p_definition_1(self, p):
655 'definition : typedef'
656 self.pdebug("p_definition_1", p)
657 p[0] = p[1]
658 try:
659 self.program.addTypedef(p[0])
660 except ErrorException, e:
661 self.errors+= e.errors
662
663 def p_definition_2(self, p):
664 'definition : enum'
665 self.pdebug("p_definition_2", p)
666 p[0] = p[1]
667 try:
668 self.program.addEnum(p[0])
669 except ErrorException, e:
670 self.errors+= e.errors
671
672 def p_definition_3(self, p):
673 'definition : struct'
674 self.pdebug("p_definition_3", p)
675 p[0] = p[1]
676 try:
677 self.program.addStruct(p[0])
678 except ErrorException, e:
679 self.errors+= e.errors
680
681 def p_definition_4(self, p):
682 'definition : service'
683 self.pdebug("p_definition_4", p)
684 p[0] = p[1]
685 try:
686 self.program.addService(p[0])
687 except ErrorException, e:
688 self.errors+= e.errors
689
Marc Slemkod8b10512006-08-14 23:30:37 +0000690 def p_definition_5(self, p):
691 'definition : exception'
692 self.pdebug("p_definition_5", p)
693 p[0] = p[1]
694 try:
695 self.program.addStruct(p[0])
696 except ErrorException, e:
697 self.errors+= e.errors
698
Marc Slemko17859852006-08-15 00:21:31 +0000699 def p_definition_6(self, p):
700 'definition : namespace'
701 self.pdebug("p_definition_6", p)
702 p[0] = p[1]
703
Marc Slemkob2039e72006-08-09 01:00:17 +0000704 def p_typedef(self, p):
705 'typedef : TYPEDEF definitiontype ID'
706 self.pdebug("p_typedef", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000707 p[0] = TypedefType(p, p[3], p[2])
Marc Slemkob2039e72006-08-09 01:00:17 +0000708 try:
709 p[0].validate()
710
711 except ErrorException, e:
712 self.errors+= e.errors
713
Marc Slemkob2039e72006-08-09 01:00:17 +0000714 def p_enum(self, p):
715 'enum : ENUM ID LBRACE enumdeflist RBRACE'
716 self.pdebug("p_enum", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000717 p[0] = EnumType(p, p[2], p[4])
Marc Slemkob2039e72006-08-09 01:00:17 +0000718
719 try:
720 p[0].validate()
721 except ErrorException, e:
722 self.errors+= e.errors
723
724 def p_enumdeflist_1(self, p):
725 'enumdeflist : enumdeflist COMMA enumdef'
726 self.pdebug("p_enumdeflist_1", p)
727 p[0] = p[1] + (p[3],)
728
729 def p_enumdeflist_2(self, p):
730 'enumdeflist : enumdef'
731 self.pdebug("p_enumdeflist_2", p)
732 p[0] = (p[1],)
733
734 def p_enumdef_0(self, p):
735 'enumdef : ID ASSIGN ICONST'
736 self.pdebug("p_enumdef_0", p)
737 p[0] = EnumDef(p, p[1], int(p[3]))
738
739 def p_enumdef_1(self, p):
740 'enumdef : ID'
741 self.pdebug("p_enumdef_1", p)
742 p[0] = EnumDef(p, p[1])
743
744 def p_struct(self, p):
745 'struct : STRUCT ID LBRACE fieldlist RBRACE'
746 self.pdebug("p_struct", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000747 p[0] = StructType(p, p[2], p[4])
Marc Slemkob2039e72006-08-09 01:00:17 +0000748
749 try:
750 p[0].validate()
751 except ErrorException, e:
752 self.errors+= e.errors
753
Marc Slemkod8b10512006-08-14 23:30:37 +0000754 def p_exception(self, p):
755 'exception : EXCEPTION ID LBRACE fieldlist RBRACE'
756 self.pdebug("p_struct", p)
757 p[0] = ExceptionType(p, p[2], p[4])
758
759 try:
760 p[0].validate()
761 except ErrorException, e:
762 self.errors+= e.errors
763
Marc Slemko17859852006-08-15 00:21:31 +0000764 def p_namespace(self, p):
765 'namespace : NAMESPACE namespacespecifier'
766 self.pdebug("p_struct", p)
767 p[0] = p[2]
768
769 try:
770 self.program.validateNamespace(p[0])
771 except ErrorException, e:
772 self.errors+= e.errors
773
774 def p_namespacespecifier_1(self, p):
775 'namespacespecifier : ID'
776 self.pdebug("p_namespacespecifier", p)
777 p[0] = p[1]
778
779 def p_namespacespecifier_2(self, p):
780 'namespacespecifier : ID PERIOD namespacespecifier'
781 self.pdebug("p_namespacespecifier", p)
782 p[0] = p[1]+"."+p[3]
783
Marc Slemkob2039e72006-08-09 01:00:17 +0000784 def p_service(self, p):
785 'service : SERVICE ID LBRACE functionlist RBRACE'
786 self.pdebug("p_service", p)
787 p[0] = Service(p, p[2], p[4])
788 try:
789 p[0].validate()
790 except ErrorException, e:
791 self.errors+= e.errors
792
793 def p_functionlist_1(self, p):
Marc Slemkod8b10512006-08-14 23:30:37 +0000794 'functionlist : function COMMA functionlist'
Marc Slemkob2039e72006-08-09 01:00:17 +0000795 self.pdebug("p_functionlist_1", p)
Marc Slemkod8b10512006-08-14 23:30:37 +0000796 p[0] = (p[1],) + p[3]
Marc Slemkob2039e72006-08-09 01:00:17 +0000797
798 def p_functionlist_2(self, p):
Marc Slemkod8b10512006-08-14 23:30:37 +0000799 'functionlist : function'
Marc Slemkob2039e72006-08-09 01:00:17 +0000800 self.pdebug("p_functionlist_2", p)
Marc Slemkod8b10512006-08-14 23:30:37 +0000801 p[0] = (p[1],)
802
803 def p_functionlist_3(self, p):
804 'functionlist : '
805 self.pdebug("p_functionlist_3", p)
Marc Slemkob2039e72006-08-09 01:00:17 +0000806 p[0] = ()
807
808 def p_function(self, p):
Marc Slemkod8b10512006-08-14 23:30:37 +0000809 'function : functiontype functionmodifiers ID LPAREN fieldlist RPAREN exceptionspecifier'
Marc Slemkob2039e72006-08-09 01:00:17 +0000810 self.pdebug("p_function", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000811
Marc Slemkod8b10512006-08-14 23:30:37 +0000812 resultStruct = StructType(p, p[3]+"_result", (Field(p, p[1], Identifier(None, "success", 0)),)+p[7])
Marc Slemko5b126d62006-08-11 23:03:42 +0000813
814 p[0] = Function(p, p[3], resultStruct, StructType(p, p[3]+"_args", p[5]))
Marc Slemkob2039e72006-08-09 01:00:17 +0000815 try:
816 p[0].validate()
817 except ErrorException, e:
818 self.errors+= e.errors
819
820 def p_functionmodifiers(self, p):
821 'functionmodifiers :'
822 self.pdebug("p_functionmodifiers", p)
823 p[0] = ()
824
825 def p_fieldlist_1(self, p):
Marc Slemkod8b10512006-08-14 23:30:37 +0000826 'fieldlist : field COMMA fieldlist'
Marc Slemkob2039e72006-08-09 01:00:17 +0000827 self.pdebug("p_fieldlist_1", p)
Marc Slemkod8b10512006-08-14 23:30:37 +0000828 p[0] = (p[1],) + p[3]
Marc Slemkob2039e72006-08-09 01:00:17 +0000829
830 def p_fieldlist_2(self, p):
831 'fieldlist : field'
832 self.pdebug("p_fieldlist_2", p)
833 p[0] = (p[1],)
834
835 def p_fieldlist_3(self, p):
836 'fieldlist :'
837 self.pdebug("p_fieldlist_3", p)
838 p[0] = ()
839
840 def p_field_1(self, p):
841 'field : fieldtype ID ASSIGN ICONST'
842 self.pdebug("p_field_1", p)
843 p[0] = Field(p, p[1], Identifier(None, p[2], int(p[4])))
844
845 def p_field_2(self, p):
846 'field : fieldtype ID'
847 self.pdebug("p_field_2", p)
848 p[0] = Field(p, p[1], Identifier(None, p[2]))
849
Marc Slemkod8b10512006-08-14 23:30:37 +0000850 def p_exceptionSpecifier_1(self, p):
851 'exceptionspecifier : THROWS LPAREN fieldlist RPAREN'
852 self.pdebug("p_exceptionspecifier", p)
853 p[0] = p[3]
854
855 def p_exceptionSpecifier_2(self, p):
856 'exceptionspecifier : empty'
857 self.pdebug("p_exceptionspecifier", p)
858 p[0] = ()
859
Marc Slemkob2039e72006-08-09 01:00:17 +0000860 def p_definitiontype_1(self, p):
861 'definitiontype : basetype'
862 self.pdebug("p_definitiontype_1", p)
863 p[0] = p[1]
864
865 def p_definitiontype_2(self, p):
866 'definitiontype : collectiontype'
867 self.pdebug("p_definitiontype_2", p)
868 p[0] = p[1]
869
870 def p_functiontype_1(self, p):
871 'functiontype : fieldtype'
872 self.pdebug("p_functiontype_1", p)
873 p[0] = p[1]
874
875 def p_functiontype_2(self, p):
876 'functiontype : VOID'
877 self.pdebug("p_functiontype_2", p)
878 p[0] = self.program.primitiveMap[p[1].lower()]
879
880 def p_fieldtype_1(self, p):
881 'fieldtype : ID'
882 self.pdebug("p_fieldtype_1", p)
883 p[0] = Identifier(p, p[1])
884
885 def p_fieldtype_2(self, p):
886 'fieldtype : basetype'
887 self.pdebug("p_fieldtype_2", p)
888 p[0] = p[1]
889
890 def p_fieldtype_3(self, p):
891 'fieldtype : collectiontype'
892 self.pdebug("p_fieldtype_3", p)
893 p[0] = p[1]
894
895 def p_basetype_1(self, p):
896 'basetype : STRING'
897 self.pdebug("p_basetype_1", p)
898 p[0] = self.program.primitiveMap[p[1].lower()]
899
900 def p_basetype_2(self, p):
901 'basetype : BYTE'
902 self.pdebug("p_basetype_2", p)
903 p[0] = self.program.primitiveMap[p[1].lower()]
904
905 def p_basetype_3(self, p):
906 'basetype : I08'
907 self.pdebug("p_basetype_3", p)
908 p[0] = self.program.primitiveMap[p[1].lower()]
909
910 def p_basetype_4(self, p):
911 'basetype : U08'
912 self.pdebug("p_basetype_4", p)
913 p[0] = self.program.primitiveMap[p[1].lower()]
914
915 def p_basetype_5(self, p):
916 'basetype : I16'
917 self.pdebug("p_basetype_5", p)
918 p[0] = self.program.primitiveMap[p[1].lower()]
919
920 def p_basetype_6(self, p):
921 'basetype : U16'
922 self.pdebug("p_basetype_6", p)
923 p[0] = self.program.primitiveMap[p[1].lower()]
924
925 def p_basetype_7(self, p):
926 'basetype : I32'
927 self.pdebug("p_basetype_7", p)
928 p[0] = self.program.primitiveMap[p[1].lower()]
929
930 def p_basetype_8(self, p):
931 'basetype : U32'
932 self.pdebug("p_basetype_8", p)
933 p[0] = self.program.primitiveMap[p[1].lower()]
934
935 def p_basetype_9(self, p):
936 'basetype : I64'
937 self.pdebug("p_basetype_9", p)
938 p[0] = self.program.primitiveMap[p[1].lower()]
939
940 def p_basetype_10(self, p):
941 'basetype : U64'
942 self.pdebug("p_basetype_10", p)
943 p[0] = self.program.primitiveMap[p[1].lower()]
944
945 def p_basetype_11(self, p):
946 'basetype : UTF8'
947 self.pdebug("p_basetype_11", p)
948 p[0] = self.program.primitiveMap[p[1].lower()]
949
950 def p_basetype_12(self, p):
951 'basetype : UTF16'
952 self.pdebug("p_basetype_12", p)
953 p[0] = self.program.primitiveMap[p[1].lower()]
954
955 def p_basetype_13(self, p):
956 'basetype : DOUBLE'
957 self.pdebug("p_basetype_13", p)
958 p[0] = self.program.primitiveMap[p[1].lower()]
959
960 def p_collectiontype_1(self, p):
961 'collectiontype : maptype'
962 self.pdebug("p_collectiontype_1", p)
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000963 p[0] = self.program.addCollection(p[1])
Marc Slemkob2039e72006-08-09 01:00:17 +0000964
965 def p_collectiontype_2(self, p):
966 'collectiontype : settype'
967 self.pdebug("p_collectiontype_2", p)
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000968 p[0] = self.program.addCollection(p[1])
Marc Slemkob2039e72006-08-09 01:00:17 +0000969
970 def p_collectiontype_3(self, p):
971 'collectiontype : listtype'
972 self.pdebug("p_collectiontype_3", p)
Marc Slemkoc0e07a22006-08-09 23:34:57 +0000973 p[0] = self.program.addCollection(p[1])
Marc Slemkob2039e72006-08-09 01:00:17 +0000974
975 def p_maptype(self, p):
976 'maptype : MAP LANGLE fieldtype COMMA fieldtype RANGLE'
977 self.pdebug("p_maptype", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000978 p[0] = MapType(p, p[3], p[5])
Marc Slemkob2039e72006-08-09 01:00:17 +0000979
980 def p_settype(self, p):
981 'settype : SET LANGLE fieldtype RANGLE'
982 self.pdebug("p_settype", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000983 p[0] = SetType(p, p[3])
Marc Slemkob2039e72006-08-09 01:00:17 +0000984
985 def p_listtype(self, p):
986 'listtype : LIST LANGLE fieldtype RANGLE'
987 self.pdebug("p_listtype", p)
Marc Slemko5b126d62006-08-11 23:03:42 +0000988 p[0] = ListType(p, p[3])
Marc Slemkob2039e72006-08-09 01:00:17 +0000989
Marc Slemkod8b10512006-08-14 23:30:37 +0000990 def p_empty(self, p):
991 "empty : "
992 pass
993
Marc Slemkob2039e72006-08-09 01:00:17 +0000994 def p_error(self, p):
Marc Slemko27340eb2006-08-10 20:45:55 +0000995 # p_error is called with an empty token if eof was encountered unexpectedly.
996 if not p:
997 self.errors.append(SyntaxError("Unexpected end of file"))
998 else:
999 self.errors.append(SyntaxError(p))
Marc Slemkob2039e72006-08-09 01:00:17 +00001000
1001 def pdebug(self, name, p):
1002 if self.debug:
Marc Slemkod8b10512006-08-14 23:30:37 +00001003 print(name+"("+string.join(["P["+str(ix)+"]<<"+str(p[ix])+">>" for ix in range(len(p))], ", ")+")")
Marc Slemkob2039e72006-08-09 01:00:17 +00001004
1005 def __init__(self, **kw):
1006 self.debug = kw.get('debug', 0)
1007 self.names = { }
1008 self.program = Program()
1009 self.errors = []
1010
1011 try:
1012 modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__
1013 except:
1014 modname = "parser"+"_"+self.__class__.__name__
1015 self.debugfile = modname + ".dbg"
1016 self.tabmodule = modname + "_" + "parsetab"
1017 #print self.debugfile, self.tabmodule
1018
1019 # Build the lexer and parser
1020 lex.lex(module=self, debug=self.debug)
1021 yacc.yacc(module=self,
1022 debug=self.debug,
1023 debugfile=self.debugfile,
1024 tabmodule=self.tabmodule)
1025
1026 def parsestring(self, s, filename=""):
1027 yacc.parse(s)
1028
1029 if len(self.errors) == 0:
1030 try:
1031 self.program.validate()
1032 except ErrorException, e:
1033 self.errors+= e.errors
1034
1035 if len(self.errors):
1036 for error in self.errors:
1037 print(filename+":"+str(error))
1038
1039 def parse(self, filename, doPickle=True):
1040
1041 f = file(filename, "r")
1042
1043 self.parsestring(f.read(), filename)
1044
1045 if len(self.errors) == 0 and doPickle:
1046
1047 outf = file(os.path.splitext(filename)[0]+".thyc", "w")
1048
1049 pickle.dump(self.program, outf)