__file__ = 'ky_operator.py' __usage__ = ''' = operator( operator symbol, operator opcode, [precedence], [associativity] ) operator symbol - eg. +, -, *, /, etc. operator opcode - eg. ADD, SUB, MUL, DIV, etc. precedence - eg. {'+':operator.PREC_YIELD_LEFT, '-':operator.PREC_YIELD_RIGHT, ...} etc associativity = eg. operator.ASSOC_LEFT, operator.ASSOC_RIGHT''' __description__ = '''This class is used to store data for operator tokens, and more specificially operator-operator precedence relationships. It allows operator associativity to be set by the coder, and thus a level of control required to allow compile time operator definitions in code.''' __author__ = 'Timothy Wakeham (timmeh)' __contact__ = 'timmeh@hiddenworlds.org' __updated__ = '28-03-2008 @ 13:00:55' __todo__ = None #start class Operator: operators = {} ASSOC_LEFT = 0 ASSOC_RIGHT = 1 PREC_YIELD_LEFT = 0 PREC_YIELD_RIGHT = 1 PREC_EQUAL = 2 YIELD = 0 PREC = 1 EQUAL = 2 def __init__(self, operator, opcode, precedence={}, associativity=0, unary=False): self.operator = operator self.op = opcode self.precedence = precedence self.assign = None #set self precedence as determined by associativity if associativity == Operator.ASSOC_LEFT: self.precedence[operator] = Operator.PREC_YIELD_RIGHT else: self.precedence[operator] = Operator.PREC_YIELD_LEFT Operator.operators[operator] = self def get_opcode(self): if self.operator == '=' and self.assign: return 'POP %s' % self.assign else: return self.op opcode = property(get_opcode) def __str__(self): return '' % self.operator # check if this operator yields to the other def __lt__(self, other): if not isinstance(other, Operator): raise TypeError, 'Operator precedence testing requires two(2) operators' if self.precedence.has_key(other.operator): if self.precedence[other.operator] == Operator.PREC_YIELD_LEFT: return True else: return False else: raise AttributeError, 'Operator %s has no precedence relationship with: %s' % (self.operator, other.operator) # check if this operator has precedence over the other def __gt__(self, other): if not isinstance(other, Operator): raise TypeError, 'Operator precedence testing requires two(2) operators' if self.precedence.has_key(other.operator): if self.precedence[other.operator] == Operator.PREC_YIELD_RIGHT: return True else: return False else: raise AttributeError, 'Operator %s has no precedence relationship with: %s' % (self.operator, other.operator) # check if this operator yields or has equal precedence to the other def __le__(self, other): if not isinstance(other, Operator): raise TypeError, 'Operator precedence testing requires two(2) operators' if self.precedence.has_key(other.operator): if self.precedence[other.operator] == Operator.PREC_YIELD_LEFT or self.precedence[other.operator] == Operator.PREC_EQUAL: return True else: return False else: raise AttributeError, 'Operator %s has no precedence relationship with: %s' % (self.operator, other.operator) # check if this operator has precedence or equal precedence to the other def __ge__(self, other): if not isinstance(other, Operator): raise TypeError, 'Operator precedence testing requires two(2) operators' if self.precedence.has_key(other.operator): if self.precedence[other.operator] == Operator.PREC_YIELD_RIGHT or self.precedence[other.operator] == Operator.PREC_EQUAL: return True else: return False else: raise AttributeError, 'Operator %s has no precedence relationship with: %s' % (self.operator, other.operator) class UnaryOperator(Operator): PREFIX = 0 POSTFIX = 1 unary_operators = {} def __init__(self, operator, opcode, operator_type=0): self.operator = operator self.opcode = opcode self.op_type = operator_type self.precedence = {operator:Operator.PREC_EQUAL} for op, op_obj in Operator.operators.iteritems(): if operator_type == UnaryOperator.PREFIX: op_obj.precedence[operator] = Operator.PREC_YIELD_RIGHT self.precedence[op] = Operator.PREC_YIELD_LEFT else: op_obj.precedence[operator] = Operator.PREC_YIELD_LEFT self.precedence[op] = Operator.PREC_YIELD_RIGHT UnaryOperator.unary_operators[operator] = self Operator.operators[operator] = self