1import string,re 2from types import * 3 4data_type=["string", "int", "float", 5 "list", "map"] 6 7class Object: 8 def __init__(self, name="", type="", value=""): 9 self.name=name 10 self.type=type 11 self.value=value #for mapping: only attributes that are defined in object itself 12 self.attr_container_obj=None 13 self.definition=None 14 self.attr={} #for mappping: all attributes, including inherited ones 15 self.attr_list=[] #ditto, but in list format 16 self.debug=None 17 def append(self, value): 18 self.value.append(value) 19 value.attr_container_obj=self 20 if value.name: 21 self.attr[value.name]=value 22 self.attr_list.append(value) 23 if (value.name=="id" and self.attr.has_key("parents")) or \ 24 (value.name=="parents" and self.attr.has_key("id")): 25 self.append(Object(name="children",value=[])) 26 def append_inherited(self, value): 27 self.attr[value.name]=value 28 self.attr_list.append(value) 29 def add_children(self, obj): 30 inst_obj=self.attr.get("children") 31 if not inst_obj: #checked earlier 32 raise SyntaxError, ("id attribute not defined and thus children neither", 33 self.debug) 34 id=obj.attr.get("id") 35 if not id: #checked earlier 36 raise SyntaxError, ("id attribute not defined", 37 obj.debug) 38 inst_obj.value.append(id.value) 39 def has_parent(self, dict, id): 40 """search parent hierarchy to find if any of it is same as type""" 41 id_obj=self.attr.get('id') 42 if not id_obj: #hmm.. attribute, look for parent type 43 type_obj=dict[self.name] 44 return type_obj.has_parent(dict,id) 45 if id_obj.value==id: return 1 46 for parent in self.attr['parents'].value: 47 par_obj=dict[parent] 48 if par_obj.has_parent(dict,id): 49 return 1 50 return 0 51 52 def __repr__(self): 53 return self.name+":"+self.type+":"+str(self.value) 54 55debug_reading=0 56class ParseDef: 57 """reads 'atlas def' files and created suitable 'web' for html/xml generators""" 58 def __init__(self): 59 self.id_dict={} 60 self.objects=Object(type="list",value=[]) 61 self.lineno=0 62 def read_lines(self, fp, depth, parent_obj, line0=None): 63 """read object definitions in one level: 64 call itself recursively for sub objects""" 65 last_obj=None 66 while 1: 67 if line0: #line was already read, given as line0 argument 68 line=line0 69 line0=None 70 if debug_reading: 71 print "???",line,self.lineno 72 else: 73 line=fp.readline() 74 self.lineno=self.lineno+1 75 if debug_reading: 76 print "!!!",self.lineno,line, 77 if not line: break 78 if line[0] in '#\n': continue 79 space_count=len(re.match("( *)",line).group(1)) 80 if space_count==len(line)-1: continue #Only spaces in line 81 #print " "*depth,depth,space_count,"{",line[:-1],"}",parent_obj 82 if space_count>depth: #sub object 83 if not last_obj: 84 raise SyntaxError, ("Unexpected indentation", 85 (self.filename, self.lineno, space_count, line)) 86 #current line belongs to sub object, lets call ourself 87 #it returns next line from our object 88 line0=self.read_lines(fp,space_count,last_obj,line) 89 last_obj=None 90 continue 91 if space_count<depth: #all objects in this level done 92 #and return line belonging to our parent 93 return line 94 #split into parts using ':' but not inside string 95 parts=[] 96 rest=line[space_count:-1] 97 while 1: 98 match=re.match("""([^"':]*):(.*)""",rest) #' (for xemacs highlight) 99 if match: 100 parts.append(match.group(1)) 101 rest=match.group(2) 102 else: 103 parts.append(rest) 104 break 105 if len(parts)==3: #hmm.. probably name undefined 106 name,type,value=parts 107 elif len(parts)==2: #name and value defined, type undefined 108 name,value=parts 109 if len(value)==0: 110 type="list" #guessing 111 else: 112 type="" 113 else: 114 raise SyntaxError, ("Unexpected element numbers (things delimited with ':')", 115 (self.filename, self.lineno, space_count, line)) 116 if type in ["list", "map"]: #new subojects 117 obj=last_obj=Object(name,type,value=[]) 118 else: 119 #hack: reading several lines if """ string 120 if value[:3]=='"""' and not value[-3:]=='"""': 121 value=value+"\n" 122 while 1: 123 line=fp.readline() 124 self.lineno=self.lineno+1 125 value=value+line 126 if not line or string.find(line,'"""')>=0: 127 break 128 try: 129 evaled_value=eval(value) 130 except: 131 print "Error at:",(self.filename, self.lineno, space_count, line) 132 raise 133 obj=Object(name,type,evaled_value) 134 last_obj=None 135 parent_obj.append(obj) 136 obj.debug=(self.filename, self.lineno, space_count, line) 137 def read_file(self, filename): 138 """read one file""" 139 self.filename=filename 140 self.lineno=0 141 fp=open(filename) 142 self.read_lines(fp,0,self.objects) 143 fp.close() 144 def fill(self): 145 self.fill_id_dict() 146 self.fill_type() 147 self.fill_inherited_attributes() 148 def fill_id_dict(self): 149 """fill id_dict with all objects""" 150 for obj in self.objects.value: 151 id=None 152 for obj2 in obj.value: 153 if obj2.name=="id": 154 id=obj2.value 155 break 156 if not id: 157 raise SyntaxError, ("Id attribute is not specified for object",obj.debug) 158 if self.id_dict.has_key(id): 159 raise SyntaxError, ('Object with "'+id+'"-id already exists',obj.debug) 160 self.id_dict[id]=obj 161 def search_type(self, name): 162 """find type for this name""" 163 if name in data_type: return name 164 obj=self.id_dict[name] 165 if not obj.attr.has_key('parents'): 166 raise SyntaxError, ("Parents attribute is not specified for object",obj.debug) 167 parent_list=obj.attr['parents'].value 168 if not parent_list: 169 raise SyntaxError, ("Didn't found data_type for object",obj.debug) 170 return self.search_type(parent_list[0]) 171 def fill_type_object(self, obj): 172 """recursively find types for all objects""" 173 if type(obj)!=InstanceType: return 174 if obj.name: 175 if not self.id_dict.has_key(obj.name): 176 raise SyntaxError, ('Name "'+obj.name+'" is not specified',obj.debug) 177 obj.type=self.search_type(obj.name) 178 if type(obj.value)==ListType: 179 for sub_obj in obj.value: 180 self.fill_type_object(sub_obj) 181 def fill_type(self): 182 self.fill_type_object(self.objects) 183 def fill_inherited_attributes_object(self, obj, p_obj,depth): 184 """recursively find attributes that are inherited from parents""" 185 if type(obj)!=InstanceType: return 186 if not p_obj.attr.has_key('parents'): 187 raise SyntaxError, ("Parents attribute is not specified for object", 188 p_obj.debug) 189 if depth==1: 190 p_obj.add_children(obj) 191 #print obj.attr['id'].value,p_obj.attr['id'].value 192 for p_sub_obj in p_obj.value: 193 name=p_sub_obj.name 194 #print "-->",p_sub_obj.name 195 if not obj.attr.has_key(p_sub_obj.name): 196 obj.append_inherited(p_sub_obj) 197 for parent in p_obj.attr['parents'].value: 198 if not self.id_dict.has_key(parent): 199 raise SyntaxError, ("Parent \""+parent+"\" doesn't exist.", 200 obj.attr['parents'].debug) 201 self.fill_inherited_attributes_object(obj,self.id_dict[parent],depth+1) 202 def fill_inherited_attributes(self): 203 for obj in self.objects.value: 204 self.fill_inherited_attributes_object(obj,obj,0) 205 206 207def read_all_defs(filelist): 208 parser=ParseDef() 209 for file in filelist: 210 parser.read_file(file) 211 parser.fill() 212 #for item in parser.id_dict.items(): print item 213 return parser 214 215if __name__=="__main__": 216 parser=read_all_defs() 217