diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index 3965dd7c98..66c4435957 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -61,6 +61,7 @@ extern int column; %option noyywrap nounput /* UTF-8 unicode regular expressions. */ +/* http://www.unicode.org/reports/tr44/#General_Category_Values */ Cc ([\x00-\x1f\x7f]|\xc2[\x80-\x9f]) Cf (\xc2\xad|\xd8[\x80-\x85\x9c]|\xdb\x9d|\xdc\x8f|\xe1(\xa0\x8e)|\xe2(\x80[\x8b-\x8f\xaa-\xae]|\x81[\xa0-\xa4\xa6-\xaf])|\xef(\xbb\xbf|\xbf[\xb9-\xbb])|\xf0(\x91(\x82\xbd))|\xf3(\xa0(\x80\x81))) diff --git a/src/App/ExpressionParser.sh b/src/App/ExpressionParser.sh index ba14525792..bb12396b7a 100755 --- a/src/App/ExpressionParser.sh +++ b/src/App/ExpressionParser.sh @@ -1,3 +1,6 @@ -# Description for bash script -flex -olex.ExpressionParser.c < ExpressionParser.l -bison -oExpressionParser.tab.c ExpressionParser.y +#!/usr/bin/env sh + +cd "$(dirname "$0")" + +flex -v -olex.ExpressionParser.c ExpressionParser.l +bison -d -v -Wall -oExpressionParser.tab.c ExpressionParser.y diff --git a/src/App/ExpressionParser.y b/src/App/ExpressionParser.y index e49d9a34e5..0a3a1f25e9 100644 --- a/src/App/ExpressionParser.y +++ b/src/App/ExpressionParser.y @@ -36,7 +36,6 @@ std::stack functions; /**< Function #define yyerror ExpressionParser_yyerror %} - /* Bison declarations. */ %token FUNC %token ONE %token NUM @@ -66,16 +65,14 @@ std::stack functions; /**< Function %type document %type object %type integer - %left ONE NUM INTEGER CONSTANT - %left EQ NEQ LT GT GTE LTE - %left '?' ':' + %precedence EQ NEQ LT GT GTE LTE + %precedence ':' %left MINUSSIGN '+' %left '*' '/' '%' %precedence NUM_AND_UNIT - %left '^' /* exponentiation */ - %left EXPONENT - %left NEG /* negation--unary minus */ - %left POS /* unary plus */ + %left '^' + %precedence NEG + %precedence POS %destructor { delete $$; } num range exp cond unit_exp indexable %destructor { delete $$; } @@ -105,6 +102,7 @@ exp: num { $$ = $1; | indexable { $$ = $1; } | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2); } | cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); } + | '(' exp ')' { $$ = $2; } ; num: ONE { $$ = new NumberExpression(DocumentObject, Quantity($1)); } @@ -129,6 +127,7 @@ cond: exp EQ exp { $$ = new OperatorExpression(Do | exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); } | exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); } | exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); } + | '(' cond ')' { $$ = $2; } ; unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); } @@ -206,8 +205,7 @@ indexer ; indexable - : '(' exp ')' { $$ = $2; } - | identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); } + : identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); } | indexable indexer { $1->addComponent(std::move($2)); $$ = $1; } | indexable '.' IDENTIFIER { $1->addComponent(Expression::createComponent($3)); $$ = $1; } ; diff --git a/src/Mod/Spreadsheet/TestSpreadsheet.py b/src/Mod/Spreadsheet/TestSpreadsheet.py index c81d4cc6f3..727309d3e1 100644 --- a/src/Mod/Spreadsheet/TestSpreadsheet.py +++ b/src/Mod/Spreadsheet/TestSpreadsheet.py @@ -46,7 +46,6 @@ class SpreadsheetCases(unittest.TestCase): def testAggregates(self): """ Test all aggregate functions """ sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet') - sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet') sheet.set('B13', '4') sheet.set('B14', '5') sheet.set('B15', '6') @@ -165,7 +164,6 @@ class SpreadsheetCases(unittest.TestCase): def testFunctions(self): """ Test all built-in simple functions """ - doc = FreeCAD.newDocument() sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet') sheet.set('A1', '=cos(60)') # Cos sheet.set('B1', '=cos(60deg)') @@ -366,7 +364,6 @@ class SpreadsheetCases(unittest.TestCase): self.assertMostlyEqual(sheet.B27, l) self.assertTrue(sheet.C27.startswith(u'ERR: Units must be equal')) self.assertMostlyEqual(sheet.D27, Units.Quantity("3 mm")) - FreeCAD.closeDocument(doc.Name) def testRelationalOperators(self): """ Test relational operators """ @@ -1442,6 +1439,15 @@ class SpreadsheetCases(unittest.TestCase): sheet.setAlias('A1', 'aliasOfEmptyCell') self.assertEqual(sheet.getCellFromAlias("aliasOfEmptyCell"),"A1") + def testParensAroundCondition(self): + """ Parens around a condition should be accepted """ + sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet') + + sheet.set('A1', '=(1 == 1) ? 1 : 0') + self.doc.recompute() + self.assertEqual(sheet.getContents('A1'), '=1 == 1 ? 1 : 0') + self.assertEqual(sheet.A1, 1) + def tearDown(self): #closing doc FreeCAD.closeDocument(self.doc.Name)