From kde-commits Sat May 31 22:38:28 2008 From: Michael Pyne Date: Sat, 31 May 2008 22:38:28 +0000 To: kde-commits Subject: playground/utils/abakus/src Message-Id: <1212273508.701398.20520.nullmailer () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=121227352212249 SVN commit 815013 by mpyne: Fix exponentiation and unary minus precedence in abakus (I haven't looked at this stuff in ages, I'm glad I remembered to comment it.) Now -2^2 gives a result of -4 as expected. 2^3^2 still gives the right answer, all other expressions I've tested still work. I haven't developed a testsuite yet and I saw no online testsuite for math parsers so this may need more testing. Noted on a bug report by Vincent Lefevre. I don't intend to backport to the the KDE 3.5 version of abakus (but because I don't feel like trying to find out where I left it, not because I'm opposed). M +13 -11 parser.yy --- trunk/playground/utils/abakus/src/parser.yy #815012:815013 @@ -1,6 +1,6 @@ /* * parser.yy - part of abakus - * Copyright (C) 2004, 2005 Michael Pyne + * Copyright (C) 2004, 2005, 2008 Michael Pyne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,7 +53,7 @@ } %token NUM -%type EXP FACTOR TERM S EXPONENT NUMBER VALUE FINAL +%type EXP FACTOR TERM S NUMBER VALUE FINAL %type FUNC %token FN %token ID @@ -303,17 +303,19 @@ EXP: EXP '-' FACTOR { $$ = new BinaryOperator(BinaryOperator::Subtraction, $1, $3); } EXP: FACTOR { $$ = $1; } -FACTOR: FACTOR '*' EXPONENT { $$ = new BinaryOperator(BinaryOperator::Multiplication, $1, $3); } -FACTOR: FACTOR '/' EXPONENT { $$ = new BinaryOperator(BinaryOperator::Division, $1, $3); } -FACTOR: EXPONENT { $$ = $1; } +FACTOR: FACTOR '*' TERM { $$ = new BinaryOperator(BinaryOperator::Multiplication, $1, $3); } +FACTOR: FACTOR '/' TERM { $$ = new BinaryOperator(BinaryOperator::Division, $1, $3); } +FACTOR: TERM { $$ = $1; } -EXPONENT: TERM POWER EXPONENT { $$ = new BinaryOperator(BinaryOperator::Exponentiation, $1, $3); } -EXPONENT: TERM { $$ = $1; } - -TERM: '+' VALUE { $$ = $2; } -TERM: '-' VALUE { $$ = new UnaryOperator(UnaryOperator::Negation, $2); } +/* + * Handle exponentiation by making them TERMs, which makes the POWER operator bind very + * tightly. Make unary negation a lower precendence so that -2^2 == -4, as 2^2 will be + * reduced to a TERM before the -TERM reduction is applied. + */ +TERM: VALUE POWER TERM { $$ = new BinaryOperator(BinaryOperator::Exponentiation, $1, $3); } +TERM: '+' TERM { $$ = $2; } +TERM: '-' TERM { $$ = new UnaryOperator(UnaryOperator::Negation, $2); } TERM: '(' EXP ')' { $$ = $2; } -TERM: '-' '(' EXP ')' { $$ = new UnaryOperator(UnaryOperator::Negation, $3); } TERM: VALUE { $$ = $1; }