Re: [Pyparsing] operatorPrecedence: Problems with Power and Unary Minus
Brought to you by:
ptmcg
From: Paul M. <pt...@au...> - 2008-09-07 15:15:47
|
Eike - Well, this came together a bit faster than I'd thought. The solution begins with an understanding of operatorPrecedence. Here is the expression that is published in the online example simpleArith.py: integer = Word(nums).setParseAction(lambda t:int(t[0])) variable = Word(alphas,exact=1) operand = integer | variable expop = Literal('**') signop = oneOf('+ -') multop = oneOf('* /') plusop = oneOf('+ -') factop = Literal('!') expr = operatorPrecedence( operand, [(factop, 1, opAssoc.LEFT), (expop, 2, opAssoc.RIGHT), (signop, 1, opAssoc.RIGHT), (multop, 2, opAssoc.LEFT), (plusop, 2, opAssoc.LEFT),] ) As I mentioned earlier, this will only recognize "-a**-b" if given as "-a**(-b)". The reason for this is that operator precedence cannot look "down" the precedence chain unless the next term is enclosed in parentheses. My first attempt at fixing this was to change the definition of operand to include an optional leading sign, and this parsed successfully. But then it dawned on me that this same thing can be accomplished by inserting another signop operator *above* expop, as in: expr = operatorPrecedence( operand, [(factop, 1, opAssoc.LEFT), (signop, 1, opAssoc.RIGHT), (expop, 2, opAssoc.RIGHT), (signop, 1, opAssoc.RIGHT), (multop, 2, opAssoc.LEFT), (plusop, 2, opAssoc.LEFT),] ) I think this is the correct solution, rather than mucking about with operatorPrecedence, or requiring strange embellishments to one's operand expression. I don't think this is a general issue with unary operators or right-associated operations, I think this is just a special case borne out of the definition of exponentiation with respect to leading sign operators. I'll fix simpleArith.py to correctly include the extra unary sign operator precedence level, and also include some examples. I'll also include simpleArith2.py, which actually evaluates the parsed expression. -- Paul |