Reputation: 934
In most examples that I can find precedence uses grouped (oneOf) literals to set the same level. With this approach I would have to look up which of the 2 (or more) it is and then continue with evaluation. What I would like to do is split the operators to directly know which one it is and evaluate it.
This is what I would like to implement, but the precedence levels are now wrong
arith_prec = [
(subtract_op, 2, opAssoc.LEFT, ast.Substraction),
(add_op, 2, opAssoc.LEFT, ast.Addition),
(divide_op, 2, opAssoc.LEFT, ast.Division),
(multiplication_op, 2, opAssoc.LEFT, ast.Multiplication),
]
This is what I had before but had to match which of the two (or more) it was
plusop = oneOf(['+', '-'])
multop = oneOf(['*', '/'])
arith_prec = [
(plusop, 2, opAssoc.LEFT,),
(multop, 2, opAssoc.LEFT,),
]
Is there a way of doing this? I have tested with using oneOf and Or inside of the arith_prec but to no use.
Upvotes: 1
Views: 337
Reputation: 63747
You will have to match the operators within your parse action/class. Note that you will potentially get several operations, not just one with two operands. For instance, parsing "1 - 3 + 2" will give you [1, '-', 3, '+', 2]
, so you really can't have this create an Addition or Subtraction class.
Perhaps combine them to classes like AddSub and MultDiv, which will iterate left-to-right through the parsed values to evaluate the value:
class BinOp:
operator_map = {}
def __init__(self, tokens):
self.tokens = tokens
def eval(self):
seq = self.tokens
ret = seq[0]
for operator, operand in zip(seq[1::2], seq[2::2]):
ret = self.operator_map[operator](ret, operand)
return ret
class AddSub(BinOp):
operator_map = {'+': operator.add, '-': operator.sub}
class MultDiv(BinOp):
operator_map = {'*': operator.mul, '/': operator.truediv}
plusop = oneOf(AddSub.operator_map.keys())
multop = oneOf(MultDiv.operator_map.keys())
arith_prec = [
(multop, 2, opAssoc.LEFT, MultDiv),
(plusop, 2, opAssoc.LEFT, AddSub),
]
Or broaden your concept of "addition" to include '+' and '-' operations. (As in engineering school, we had to generalize the concept of "acceleration" to include any change in velocity, either up or down.)
In any event, if you are using the infixNotation
method, you will have to have each level of precedence include all the operators at that level.
Upvotes: 1