Changeset 23
- Timestamp:
- 18/08/04 19:28:30 (4 years ago)
- Files:
-
- trunk/airspeed.py (modified) (20 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/airspeed.py
r22 r23 6 6 7 7 __all__ = ['TemplateSyntaxError', 'Template'] 8 8 9 9 10 ############################################################################### … … 28 29 29 30 class TemplateSyntaxError(Exception): 30 line = 031 31 def __init__(self, element, expected): 32 32 self.element = element … … 139 139 140 140 class Text(_Element): 141 MY_PATTERN = re.compile(r'((?:[^\\\$#]|\\[\$#])+|\$[^!\{a-z0-9_]|\$$|\\\\)(.*)$', re.S + re.I)141 PLAIN = re.compile(r'((?:[^\\\$#]|\\[\$#])+|\$[^!\{a-z0-9_]|\$$|\\\\)(.*)$', re.S + re.I) 142 142 ESCAPED_CHAR = re.compile(r'\\([\\\$#])') 143 def parse(self): 144 text, = self.identity_match(self.MY_PATTERN) 143 144 def parse(self): 145 text, = self.identity_match(self.PLAIN) 145 146 def unescape(match): 146 147 return match.group(1) … … 152 153 153 154 class IntegerLiteral(_Element): 154 MY_PATTERN = re.compile(r'(\d+)(.*)', re.S) 155 def parse(self): 156 self.value, = self.identity_match(self.MY_PATTERN) 155 INTEGER = re.compile(r'(\d+)(.*)', re.S) 156 157 def parse(self): 158 self.value, = self.identity_match(self.INTEGER) 157 159 self.value = int(self.value) 158 160 … … 162 164 163 165 class StringLiteral(_Element): 164 MY_PATTERN= re.compile(r'"((?:\\["nrbt\\\\]|[^"\n\r"\\])+)"(.*)', re.S)166 STRING = re.compile(r'"((?:\\["nrbt\\\\]|[^"\n\r"\\])+)"(.*)', re.S) 165 167 ESCAPED_CHAR = re.compile(r'\\([nrbt"\\])') 166 def parse(self): 167 value, = self.identity_match(self.MY_PATTERN) 168 169 def parse(self): 170 value, = self.identity_match(self.STRING) 168 171 def unescape(match): 169 172 return {'n': '\n', 'r': '\r', 'b': '\b', 't': '\t', '"': '"', '\\': '\\'}[match.group(1)] … … 183 186 184 187 class NameOrCall(_Element): 185 NAME _PATTERN= re.compile(r'([a-zA-Z_][a-zA-Z0-9_]*)(.*)$', re.S)188 NAME = re.compile(r'([a-zA-Z_][a-zA-Z0-9_]*)(.*)$', re.S) 186 189 parameters = None 187 def parse(self): 188 self.name, = self.identity_match(self.NAME_PATTERN) 190 191 def parse(self): 192 self.name, = self.identity_match(self.NAME) 189 193 try: self.parameters = self.next_element(ParameterList) 190 194 except NoMatch: pass 191 195 192 def calculate(self, namespace, top_namespace):193 try: result = getattr( namespace, self.name)196 def calculate(self, current_object, top_namespace): 197 try: result = getattr(current_object, self.name) 194 198 except AttributeError: 195 try: result = namespace[self.name]199 try: result = current_object[self.name] 196 200 except KeyError: result = None 197 201 if result is None: … … 203 207 204 208 209 class SubExpression(_Element): 210 DOT = re.compile('\.(.*)', re.S) 211 212 def parse(self): 213 self.identity_match(self.DOT) 214 self.expression = self.next_element(Expression) 215 216 def calculate(self, current_object, global_namespace): 217 return self.expression.calculate(current_object, global_namespace) 218 219 205 220 class Expression(_Element): 206 DOT = re.compile('\.(.*)', re.S) 207 def parse(self): 208 self.parts = [] 209 self.parts.append(self.require_next_element(NameOrCall, 'name')) 210 while self.optional_match(self.DOT): 211 try: 212 self.parts.append(self.next_element(NameOrCall)) 213 except NoMatch: 214 self.end -= 1 ### HACK 215 break # for the '$name. blah' case 216 217 def calculate(self, namespace): 218 value = namespace 219 for part in self.parts: 220 value = part.calculate(value, namespace) 221 if value is None: return None 221 subexpression = None 222 223 def parse(self): 224 self.part = self.next_element(NameOrCall) 225 try: self.subexpression = self.next_element(SubExpression) 226 except NoMatch: pass 227 228 def calculate(self, namespace, global_namespace=None): 229 if global_namespace == None: 230 global_namespace = namespace 231 value = self.part.calculate(namespace, global_namespace) 232 if self.subexpression: 233 value = self.subexpression.calculate(value, namespace) 222 234 return value 223 235 224 236 225 237 class ParameterList(_Element): 226 OPENING_PATTERN= re.compile(r'\(\s*(.*)$', re.S)227 CLOSING_PATTERN= re.compile(r'\s*\)(.*)$', re.S)228 COMMA _PATTERN= re.compile(r'\s*,\s*(.*)$', re.S)238 START = re.compile(r'\(\s*(.*)$', re.S) 239 END = re.compile(r'\s*\)(.*)$', re.S) 240 COMMA = re.compile(r'\s*,\s*(.*)$', re.S) 229 241 230 242 def parse(self): 231 243 self.values = [] 232 self.identity_match(self. OPENING_PATTERN)244 self.identity_match(self.START) 233 245 try: value = self.next_element(Value) 234 246 except NoMatch: … … 236 248 else: 237 249 self.values.append(value) 238 while self.optional_match(self.COMMA _PATTERN):250 while self.optional_match(self.COMMA): 239 251 value = self.require_next_element(Value, 'value') 240 252 self.values.append(value) 241 self.require_match(self. CLOSING_PATTERN, ')')253 self.require_match(self.END, ')') 242 254 243 255 244 256 class Placeholder(_Element): 245 MY_PATTERN = re.compile(r'\$(!?)(\{?)(.*)$', re.S) 246 CLOSING_BRACE_PATTERN = re.compile(r'\}(.*)$', re.S) 247 def parse(self): 248 self.silent, self.braces = self.identity_match(self.MY_PATTERN) 257 START = re.compile(r'\$(!?)(\{?)(.*)$', re.S) 258 CLOSING_BRACE = re.compile(r'\}(.*)$', re.S) 259 260 def parse(self): 261 self.silent, self.braces = self.identity_match(self.START) 249 262 self.expression = self.require_next_element(Expression, 'expression') 250 if self.braces: self.require_match(self.CLOSING_BRACE _PATTERN, '}')263 if self.braces: self.require_match(self.CLOSING_BRACE, '}') 251 264 252 265 def evaluate(self, namespace, stream): … … 260 273 class SimpleReference(_Element): 261 274 LEADING_DOLLAR = re.compile('\$(.*)', re.S) 275 262 276 def parse(self): 263 277 self.identity_match(self.LEADING_DOLLAR) … … 271 285 272 286 class Comment(_Element, Null): 273 COMMENT_PATTERN = re.compile('#(?:#.*?(?:\n|$)|\*.*?\*#(?:[ \t]*\n)?)(.*)$', re.M + re.S) 274 def parse(self): 275 self.identity_match(self.COMMENT_PATTERN) 287 COMMENT = re.compile('#(?:#.*?(?:\n|$)|\*.*?\*#(?:[ \t]*\n)?)(.*)$', re.M + re.S) 288 289 def parse(self): 290 self.identity_match(self.COMMENT) 276 291 277 292 278 293 class BinaryOperator(_Element): 279 PATTERN = re.compile(r'\s*(>=|<=|<|==|!=|>)\s*(.*)$', re.S) 280 def parse(self): 281 self.operator, = self.identity_match(self.PATTERN) 282 op = operator 283 self.operator = {'>': op.__gt__, '>=': op.__ge__, 284 '<': op.__lt__, '<=': op.__le__, 285 '==': op.__eq__, '!=': op.__ne__}[self.operator] 286 287 def apply_to(self, value1, value2): 288 return self.operator(value1, value2) 294 BINARY_OP = re.compile(r'\s*(>=|<=|<|==|!=|>)\s*(.*)$', re.S) 295 OPERATORS = {'>' : operator.__gt__, '>=': operator.__ge__, 296 '<' : operator.__lt__, '<=': operator.__le__, 297 '==': operator.__eq__, '!=': operator.__ne__} 298 def parse(self): 299 op_string, = self.identity_match(self.BINARY_OP) 300 self.apply_to = self.OPERATORS[op_string] 289 301 290 302 291 303 class Condition(_Element): 292 OPENING_PATTERN= re.compile(r'\(\s*(.*)$', re.S)293 CLOSING_PATTERN= re.compile(r'\s*\)(.*)$', re.S)304 START = re.compile(r'\(\s*(.*)$', re.S) 305 END = re.compile(r'\s*\)(.*)$', re.S) 294 306 binary_operator = None 295 307 value2 = None 296 def parse(self): 297 self.require_match(self.OPENING_PATTERN, '(') 308 309 def parse(self): 310 self.identity_match(self.START) 298 311 self.value = self.next_element(Value) 299 312 try: … … 302 315 except NoMatch: 303 316 pass 304 self.require_match(self. CLOSING_PATTERN, ') or >')317 self.require_match(self.END, ') or >') 305 318 306 319 def calculate(self, namespace): … … 314 327 class End(_Element): 315 328 END = re.compile(r'#end(.*)', re.I + re.S) 329 316 330 def parse(self): 317 331 self.identity_match(self.END) … … 320 334 class ElseBlock(_Element): 321 335 START = re.compile(r'#else(.*)$', re.S + re.I) 336 322 337 def parse(self): 323 338 self.identity_match(self.START) … … 328 343 class ElseifBlock(_Element): 329 344 START = re.compile(r'#elseif\b\s*(.*)$', re.S + re.I) 345 330 346 def parse(self): 331 347 self.identity_match(self.START) … … 338 354 class IfDirective(_Element): 339 355 START = re.compile(r'#if\b\s*(.*)$', re.S + re.I) 340 START_ELSEIF = re.compile(r'#elseif\b\s*(.*)$', re.S + re.I)341 356 else_block = Null() 342 357 … … 347 362 self.elseifs = [] 348 363 while True: 349 try: 350 elseif_block = self.next_element(ElseifBlock) 351 self.elseifs.append(elseif_block) 352 except NoMatch: 353 break 364 try: self.elseifs.append(self.next_element(ElseifBlock)) 365 except NoMatch: break 354 366 try: self.else_block = self.next_element(ElseBlock) 355 367 except NoMatch: pass 356 end =self.require_next_element(End, '#else, #elseif or #end')368 self.require_next_element(End, '#else, #elseif or #end') 357 369 358 370 def evaluate(self, namespace, stream): … … 369 381 class Assignment(_Element): 370 382 START = re.compile(r'\s*\(\s*\$([a-z_][a-z0-9_]*)\s*=\s*(.*)$', re.S) 371 CLOSING_PATTERN = re.compile(r'\s*\)(?:[ \t]*\r?\n)?(.*)$', re.S + re.M) 383 END = re.compile(r'\s*\)(?:[ \t]*\r?\n)?(.*)$', re.S + re.M) 384 372 385 def parse(self): 373 386 self.var_name, = self.identity_match(self.START) 374 387 self.value = self.next_element(Value) 375 self.require_match(self. CLOSING_PATTERN, ')')388 self.require_match(self.END, ')') 376 389 377 390 def calculate(self, namespace): … … 381 394 class SetDirective(_Element): 382 395 START = re.compile(r'#set\b(.*)', re.S + re.I) 396 383 397 def parse(self): 384 398 self.identity_match(self.START) … … 391 405 class ForeachDirective(_Element): 392 406 START = re.compile(r'#foreach\s*\(\s*\$([a-z_][a-z0-9_]*)\s*in\s*(.*)$', re.S + re.I) 393 CLOSING_PATTERN = re.compile(r'\s*\)(.*)$', re.S) 407 END = re.compile(r'\s*\)(.*)$', re.S) 408 394 409 def parse(self): 395 410 ## Could be cleaner b/c syntax error if no '(' 396 411 self.loop_var_name, = self.identity_match(self.START) 397 412 self.value = self.next_element(Value) 398 self.require_match(self. CLOSING_PATTERN, ')')413 self.require_match(self.END, ')') 399 414 self.block = self.next_element(Block) 400 415 self.require_next_element(End, '#end') … … 434 449 for child in self.children: 435 450 child.evaluate(namespace, stream) 436
