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