1############################################################################## 2## Name: parse_attr.py 3## Purpose: 4## Author: Alex Thuering 5## Created: 2005/01/19 6## RCS-ID: $Id: parse_attr.py,v 1.2 2014/03/21 21:15:35 ntalex Exp $ 7## Copyright: (c) 2005 Alex Thuering 8## Notes: some modules adapted from svgl project 9############################################################################## 10 11import re, string 12import cpp 13import collections 14 15parenthesis_re = re.compile('\(|\)') 16 17def get_parenthesis_expr(content, pos=0): 18 depth=1 19 while depth!=0: 20 m = parenthesis_re.search(content, pos) 21 if m==None: 22 raise "pas bon "+defi[begdef:] 23 if m.group()=='(': 24 depth=depth+1 25 else: 26 depth=depth-1 27 pos = m.end() 28 return pos 29 30#------------ 31# attr_type 32 33#returns (implied, required, fixed, defaultvalue) 34 35class attr_type: 36 pass 37 38class attr_type_implied(attr_type): 39 def __str__(self): 40 return "#IMPLIED" 41 42class attr_type_required(attr_type): 43 def __str__(self): 44 return "#REQUIRED" 45 46class attr_type_fixed(attr_type): 47 def __init__(self, default_value): 48 self.default_value = default_value 49 50 def __str__(self): 51 return "#FIXED '" + self.default_value + "'" 52 53class attr_type_default_value(attr_type): 54 def __init__(self, default_value): 55 self.default_value = default_value 56 57 def __str__(self): 58 return "'" + self.default_value + "'" 59 60 61 62 63 64class attribute_def: 65 def __init__(self): 66 pass 67 68 def expand(self, entity_type_decls={}, entity_common_attrs={} ): 69 return [self] 70 71 72class attr_entity_ref (attribute_def): 73 def __init__(self, entity_name): 74 self.entity_name = entity_name 75 self.expandlist=None 76 77 def __str__(self): 78 return '%' + self.entity_name + ';' 79 80 def expand(self, entity_type_decls={}, entity_common_attrs={} ): 81 if self.entity_name in entity_type_decls: 82 return entity_type_decls[self.entity_name] 83 elif self.entity_name in entity_common_attrs: 84 entities = entity_common_attrs[self.entity_name] 85 l=[] 86 for i in entities: 87 l2 = i.expand(entity_type_decls, entity_common_attrs) 88 if isinstance(l2, collections.Iterable): 89 l.extend(l2) 90 return l 91 92 93class attr_named (attribute_def): 94 def __init__(self, name): 95 attribute_def.__init__(self) 96 self.name = name 97 self.type = None 98 99 def __str__(self): 100 return self.name + ' (' + str(self.type) + ') ' 101 102class attr_named_entity_ref (attr_named, attr_entity_ref): 103 def __init__(self, name, entity_name): 104 attr_named.__init__(self, name) 105 attr_entity_ref.__init__(self, entity_name) 106 107 def __str__(self): 108 return attr_named.__str__(self) + ' ' + attr_entity_ref.__str__(self) 109 110 def expand(self, entity_type_decls={}, entity_common_attrs={} ): 111 return [self] 112 113 114class attr_named_simple_type (attr_named): 115 def __init__(self, name, simple_type): 116 attr_named.__init__(self, name) 117 self.simple_type = simple_type 118 119 def __str__(self): 120 return attr_named.__str__(self) + ' ' + self.simple_type 121 122 123class attr_named_enum (attr_named): 124 def __init__(self, name, enums): 125 attr_named.__init__(self, name) 126 self.enums = enums 127 128 def __str__(self): 129 return attr_named.__str__(self) + ' ' + str(self.enums) 130 131class attr_expr (attr_named): 132 def __init__(self, name, expr): 133 attr_named.__init__(self, name) 134 self.expr = expr 135 136 def __str__(self): 137 return attr_named.__str__(self) + ' ' + self.expr 138 139 140 141implied_re = re.compile('#IMPLIED') 142required_re = re.compile('#REQUIRED') 143fixed_re = re.compile('#FIXED') 144default_value_re = re.compile("['\"]([^'\"]*)['|\"]") 145 146#returns (implied, required, fixed, defaultvalue) 147def get_attr_typedef(content): 148 m = implied_re.search(content) 149 if m: 150 return attr_type_implied() 151 else: 152 m = required_re.search(content) 153 if m: 154 return attr_type_required() 155 else: 156 m = fixed_re.search(content) 157 if m: 158 n = default_value_re.search(content, m.end()) 159 return attr_type_fixed(n.group(1)) 160 else: 161 m = default_value_re.search(content) 162 if m: 163 return attr_type_default_value(m.group(1)) 164 else: 165 raise("error attr type", content) 166 167 168def get_enums(content, beg=0): 169 pos=get_parenthesis_expr(content, beg) 170 tmp=content[beg:pos-1].split('|') 171 enums=[] 172 for i in tmp: 173 enums.append(i.strip()) 174 #print enums 175 return enums, pos 176 177 178name_re = re.compile('\s*((\w|:|-|_)+)\s*') 179entity_ref_re = re.compile('\s*%([\w\-_]+);\s*') 180eat_re = re.compile('[^\n]+\n?', re.MULTILINE) 181 182 183def parse_attr(defi): 184 defilen=len(defi) 185 begdefi=0 186 187 attributes=[] 188 189 while begdefi<defilen: 190 # check if entity ref %blah; 191 m = entity_ref_re.match(defi, begdefi) 192 if m: 193 entity_ref = m.group(1) 194 begdefi = m.end() 195 #print entity_ref 196 attributes.append(attr_entity_ref(entity_ref)) 197 continue 198 199 # otherwise it's maybe a 'name type default' 200 m = name_re.match(defi, begdefi) 201 if m: 202 attrname = m.group(1) 203 #print attrname 204 begdefi = m.end() 205 # is it a 'name %blah; something' ? 206 m = entity_ref_re.match(defi, begdefi) 207 if m: 208 entity_ref = m.group(1) 209 #print entity_ref 210 theattr=attr_named_entity_ref(attrname, entity_ref) 211 attributes.append(theattr) 212 begdefi = m.end() 213 else: 214 # is it a 'name CDATA something' ? 215 m=name_re.match(defi, begdefi) 216 if m: 217 thetype = m.group(1) 218 #print thetype 219 theattr = attr_named_simple_type(attrname, thetype) 220 attributes.append(theattr) 221 begdefi=m.end() 222 else: 223 # expression with parenthesis 224 if defi[begdefi]=='(': 225 enums, pos = get_enums(defi, begdefi+1) 226 begdefi=pos 227 #print enums 228 theattr = attr_named_enum(attrname, enums) 229 attributes.append(theattr) 230 231 else: 232 raise "aie"+defi[begdefi:] 233 m = eat_re.match(defi, begdefi) 234 theattrtype = get_attr_typedef(m.group()) 235 theattr.type = theattrtype 236 begdefi=m.end()+1 237 238 else: 239 # so it must be an (expr) 240 if defi[begdefi]=='(': 241 pos=get_parenthesis_expr(defi, begdefi+1) 242 #enums, pos = get_enums(defi, begdefi+1) 243 begdefi=pos 244 else: 245 raise "ouie"+defi[begdefi:] 246 if (len(defi[begdefi:])): 247 m = eat_re.match(defi, begdefi) 248 #print len(defi[begdefi:]) 249 begdefi=m.end()+1 250 251 return attributes 252 253 254 255