update expression grammar to handle parens around cond

This commit is contained in:
CarlOlson
2021-04-12 00:27:40 +09:00
committed by wwmayer
parent 991a7c1a4b
commit b778a28b8a
4 changed files with 24 additions and 16 deletions

View File

@@ -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)))

View File

@@ -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

View File

@@ -36,7 +36,6 @@ std::stack<FunctionExpression::Function> functions; /**< Function
#define yyerror ExpressionParser_yyerror
%}
/* Bison declarations. */
%token FUNC
%token ONE
%token NUM
@@ -66,16 +65,14 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%type <string_or_identifier> document
%type <string_or_identifier> object
%type <ivalue> 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 $$; } <component>
@@ -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; }
;

View File

@@ -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)