Thank you for that. In fact, I already implemented it in very much the
same way as you suggested  with levels of operations of the same
precedence Or'd, and that I did see how higher ordered operations
preside over lower ordered ones. However, I did stick with
operatorPrecedence rather than the "oldfashioned" way as the former is
much more readable. It's good that you posted what you did, as it now
confirms that my understanding is (near) correct.
> You can then validate this expression with some asserts, using the
new '=='
> operator defined in 1.4.11:
>
> assert "(3+6)/5" == calcexpr
> assert "((3+6)/5)" == calcexpr
This is a very useful technique. Thanks for pointing that out.
By the way, your library is a Godsend. Thank you and very very much
appreciated. There's a helluva lot of problems we can solve very neatly
with this at our company.
Paul McGuire wrote:
> To begin with, just for readability, I would convert your operatorPrecedence
> call to:
>
> calcexpr = operatorPrecedence( w_operand,[
> (op_sign, 1, opAssoc.RIGHT),
> (op_mult, 2, opAssoc.LEFT),
> (op_div, 2, opAssoc.LEFT),
> (op_plus, 2, opAssoc.LEFT),
> (op_minus, 2, opAssoc.LEFT),
> ])
>
> Then, since one of the main purposes of opPrec is to manage levels of
> precedence of operations, I would combine operators of the same precedence
> to the same level:
>
> calcexpr = operatorPrecedence( w_operand,[
> (op_sign, 1, opAssoc.RIGHT),
> (op_mult  op_div, 2, opAssoc.LEFT),
> (op_plus  op_minus, 2, opAssoc.LEFT),
> ])
>
> (There is also value in minimizing the number of levels in a call to opPrec
>  performance can get pretty bad if the number of levels gets too deep.)
>
> You can then validate this expression with some asserts, using the new '=='
> operator defined in 1.4.11:
>
> assert "(3+6)/5" == calcexpr
> assert "((3+6)/5)" == calcexpr
>
> boolexpr is really just another set of operators with precedence:
>
> op_comparison = oneOf("= > < <= >= !=")
> comparison = calcexpr + op_comparison + calcexpr
> boolexpr = operatorPrecedence( comparison, [
> ("NOT", 1, opAssoc.RIGHT),
> ("AND", 2, opAssoc.LEFT),
> ("OR", 2, opAssoc.LEFT),
> ])
>
> But for this simple a set of operators, you can also do things the
> oldfashioned, byhand way:
>
> boolexpr = Forward()
> boolTerm = Optional("NOT") + (comparison  Group("(" + boolexpr + ")"))
> boolAnd = boolTerm + ZeroOrMore("AND" + boolTerm)
> boolOr = boolAnd + ZeroOrMore("OR" + boolAnd)
> boolexpr << ( boolOr )
>
> This also bypasses some of the overhead cruft in opPrec, and so will perform
> better.
>
> Check it out:
> assert "(3+6)/5 > 1 AND 2 < 9" == boolexpr
> assert "((3+6)/5 > 1) AND (2 < 9)" == boolexpr
> assert "((3+6)/5 > 1) AND ( (2 < 9) OR ( (2+5/12 < 1) AND ( 3 < 4) ) )" ==
> boolexpr
>
> You can see how the precedence of operations automatically groups the
> operands, so that higherorder operations get evaluated ahead of lower
> order, that is "A AND B OR C" correctly evaluates to "(A AND B) OR C":
>
> def test(s):
> from pprint import pprint
> print s
> try:
> pprint (boolexpr.parseString(s).asList())
> except ParseException, pe:
> print "Exception:", pe.msg
> print
>
> test("(3+6)/5 > 1 AND 2 < 9")
> test("((3+6)/5 > 1) AND (2 < 9)")
> test("((3+6)/5 > 1) AND ( (2 < 9) OR ( (2+5/12 < 1) AND ( 3 < 4) ) )")
>
> prints:
>
> (3+6)/5 > 1 AND 2 < 9
> [[['3', '+', '6'], '/', '5'], '>', '1', 'AND', '2', '<', '9']
>
> ((3+6)/5 > 1) AND (2 < 9)
> [['(', [['3', '+', '6'], '/', '5'], '>', '1', ')'],
> 'AND',
> ['(', '2', '<', '9', ')']]
>
> ((3+6)/5 > 1) AND ( (2 < 9) OR ( (2+5/12 < 1) AND ( 3 < 4) ) )
> [['(', [['3', '+', '6'], '/', '5'], '>', '1', ')'],
> 'AND',
> ['(',
> ['(', '2', '<', '9', ')'],
> 'OR',
> ['(',
> ['(', ['2', '+', ['5', '/', '12']], '<', '1', ')'],
> 'AND',
> ['(', '3', '<', '4', ')'],
> ')'],
> ')']]
>
> Lastly, you can do the evaluation of these various terms in parse actions
> attached to individual expressions in the grammar:
>
> calcexpr.setParseAction(evaluateCalc)
> comparison.setParseAction(evaluateComparison)
> boolexpr.setParseAction(evaluateBool)
>
> (I'll leave the implementation of these parse actions as an exercise  plus
> I'm late for work!)
>
>  Paul
>
>
> 
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2008.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
