Changeset 23

Show
Ignore:
Timestamp:
18/08/04 19:28:30 (4 years ago)
Author:
steve
Message:

subexpressions, renamings and reformatting

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/airspeed.py

    r22 r23  
    66 
    77__all__ = ['TemplateSyntaxError', 'Template'] 
     8 
    89 
    910############################################################################### 
     
    2829 
    2930class TemplateSyntaxError(Exception): 
    30     line = 0 
    3131    def __init__(self, element, expected): 
    3232        self.element = element 
     
    139139 
    140140class 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) 
    142142    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) 
    145146        def unescape(match): 
    146147            return match.group(1) 
     
    152153 
    153154class 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) 
    157159        self.value = int(self.value) 
    158160 
     
    162164 
    163165class StringLiteral(_Element): 
    164     MY_PATTERN = re.compile(r'"((?:\\["nrbt\\\\]|[^"\n\r"\\])+)"(.*)', re.S) 
     166    STRING = re.compile(r'"((?:\\["nrbt\\\\]|[^"\n\r"\\])+)"(.*)', re.S) 
    165167    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) 
    168171        def unescape(match): 
    169172            return {'n': '\n', 'r': '\r', 'b': '\b', 't': '\t', '"': '"', '\\': '\\'}[match.group(1)] 
     
    183186 
    184187class 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) 
    186189    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) 
    189193        try: self.parameters = self.next_element(ParameterList) 
    190194        except NoMatch: pass 
    191195 
    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) 
    194198        except AttributeError: 
    195             try: result = namespace[self.name] 
     199            try: result = current_object[self.name] 
    196200            except KeyError: result = None 
    197201        if result is None: 
     
    203207 
    204208 
     209class 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 
    205220class 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) 
    222234        return value 
    223235 
    224236 
    225237class 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) 
    229241 
    230242    def parse(self): 
    231243        self.values = [] 
    232         self.identity_match(self.OPENING_PATTERN
     244        self.identity_match(self.START
    233245        try: value = self.next_element(Value) 
    234246        except NoMatch: 
     
    236248        else: 
    237249            self.values.append(value) 
    238             while self.optional_match(self.COMMA_PATTERN): 
     250            while self.optional_match(self.COMMA): 
    239251                value = self.require_next_element(Value, 'value') 
    240252                self.values.append(value) 
    241         self.require_match(self.CLOSING_PATTERN, ')') 
     253        self.require_match(self.END, ')') 
    242254 
    243255 
    244256class 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) 
    249262        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, '}') 
    251264 
    252265    def evaluate(self, namespace, stream): 
     
    260273class SimpleReference(_Element): 
    261274    LEADING_DOLLAR = re.compile('\$(.*)', re.S) 
     275 
    262276    def parse(self): 
    263277        self.identity_match(self.LEADING_DOLLAR) 
     
    271285 
    272286class 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) 
    276291 
    277292 
    278293class 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] 
    289301 
    290302 
    291303class 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) 
    294306    binary_operator = None 
    295307    value2 = None 
    296     def parse(self): 
    297         self.require_match(self.OPENING_PATTERN, '(') 
     308 
     309    def parse(self): 
     310        self.identity_match(self.START) 
    298311        self.value = self.next_element(Value) 
    299312        try: 
     
    302315        except NoMatch: 
    303316            pass 
    304         self.require_match(self.CLOSING_PATTERN, ') or >') 
     317        self.require_match(self.END, ') or >') 
    305318 
    306319    def calculate(self, namespace): 
     
    314327class End(_Element): 
    315328    END = re.compile(r'#end(.*)', re.I + re.S) 
     329 
    316330    def parse(self): 
    317331        self.identity_match(self.END) 
     
    320334class ElseBlock(_Element): 
    321335    START = re.compile(r'#else(.*)$', re.S + re.I) 
     336 
    322337    def parse(self): 
    323338        self.identity_match(self.START) 
     
    328343class ElseifBlock(_Element): 
    329344    START = re.compile(r'#elseif\b\s*(.*)$', re.S + re.I) 
     345 
    330346    def parse(self): 
    331347        self.identity_match(self.START) 
     
    338354class IfDirective(_Element): 
    339355    START = re.compile(r'#if\b\s*(.*)$', re.S + re.I) 
    340     START_ELSEIF = re.compile(r'#elseif\b\s*(.*)$', re.S + re.I) 
    341356    else_block = Null() 
    342357 
     
    347362        self.elseifs = [] 
    348363        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 
    354366        try: self.else_block = self.next_element(ElseBlock) 
    355367        except NoMatch: pass 
    356         end = self.require_next_element(End, '#else, #elseif or #end') 
     368        self.require_next_element(End, '#else, #elseif or #end') 
    357369 
    358370    def evaluate(self, namespace, stream): 
     
    369381class Assignment(_Element): 
    370382    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 
    372385    def parse(self): 
    373386        self.var_name, = self.identity_match(self.START) 
    374387        self.value = self.next_element(Value) 
    375         self.require_match(self.CLOSING_PATTERN, ')') 
     388        self.require_match(self.END, ')') 
    376389 
    377390    def calculate(self, namespace): 
     
    381394class SetDirective(_Element): 
    382395    START = re.compile(r'#set\b(.*)', re.S + re.I) 
     396 
    383397    def parse(self): 
    384398        self.identity_match(self.START) 
     
    391405class ForeachDirective(_Element): 
    392406    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 
    394409    def parse(self): 
    395410        ## Could be cleaner b/c syntax error if no '(' 
    396411        self.loop_var_name, = self.identity_match(self.START) 
    397412        self.value = self.next_element(Value) 
    398         self.require_match(self.CLOSING_PATTERN, ')') 
     413        self.require_match(self.END, ')') 
    399414        self.block = self.next_element(Block) 
    400415        self.require_next_element(End, '#end') 
     
    434449        for child in self.children: 
    435450            child.evaluate(namespace, stream) 
    436