Expressions: Simpified parser, fixed precedence (parentheses)
This commit is contained in:
parent
909727ade8
commit
c506881614
|
@ -452,19 +452,33 @@ Expression *OperatorExpression::simplify() const
|
||||||
std::string OperatorExpression::toString() const
|
std::string OperatorExpression::toString() const
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
bool needsParens;
|
||||||
|
Operator leftOperator(NONE), rightOperator(NONE);
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NEG:
|
case NEG:
|
||||||
s << "-";
|
s << "-" << left->toString();
|
||||||
break;
|
return s.str();
|
||||||
case POS:
|
case POS:
|
||||||
s << "+";
|
s << "+" << left->toString();
|
||||||
break;
|
return s.str();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left->priority() < priority())
|
needsParens = false;
|
||||||
|
if (freecad_dynamic_cast<OperatorExpression>(left))
|
||||||
|
leftOperator = static_cast<OperatorExpression*>(left)->op;
|
||||||
|
if (left->priority() < priority()) // Check on operator priority first
|
||||||
|
needsParens = true;
|
||||||
|
else if (leftOperator == op) { // Equal priority?
|
||||||
|
if (!isLeftAssociative())
|
||||||
|
needsParens = true;
|
||||||
|
//else if (!isCommutative())
|
||||||
|
// needsParens = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsParens)
|
||||||
s << "(" << left->toString() << ")";
|
s << "(" << left->toString() << ")";
|
||||||
else
|
else
|
||||||
s << left->toString();
|
s << left->toString();
|
||||||
|
@ -505,14 +519,23 @@ std::string OperatorExpression::toString() const
|
||||||
break;
|
break;
|
||||||
case UNIT:
|
case UNIT:
|
||||||
break;
|
break;
|
||||||
case POS:
|
|
||||||
case NEG:
|
|
||||||
return s.str();
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right->priority() < priority())
|
needsParens = false;
|
||||||
|
if (freecad_dynamic_cast<OperatorExpression>(right))
|
||||||
|
rightOperator = static_cast<OperatorExpression*>(right)->op;
|
||||||
|
if (right->priority() < priority()) // Check on operator priority first
|
||||||
|
needsParens = true;
|
||||||
|
else if (rightOperator == op) { // Equal priority?
|
||||||
|
if (!isRightAssociative())
|
||||||
|
needsParens = true;
|
||||||
|
else if (!isCommutative())
|
||||||
|
needsParens = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsParens)
|
||||||
s << "(" << right->toString() << ")";
|
s << "(" << right->toString() << ")";
|
||||||
else
|
else
|
||||||
s << right->toString();
|
s << right->toString();
|
||||||
|
@ -585,6 +608,35 @@ void OperatorExpression::visit(ExpressionVisitor &v)
|
||||||
v.visit(this);
|
v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OperatorExpression::isCommutative() const
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case EQ:
|
||||||
|
case NEQ:
|
||||||
|
case ADD:
|
||||||
|
case MUL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OperatorExpression::isLeftAssociative() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OperatorExpression::isRightAssociative() const
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case ADD:
|
||||||
|
case MUL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FunctionExpression class. This class handles functions with one or two parameters.
|
// FunctionExpression class. This class handles functions with one or two parameters.
|
||||||
//
|
//
|
||||||
|
|
|
@ -253,6 +253,13 @@ public:
|
||||||
Expression * getRight() const { return right; }
|
Expression * getRight() const { return right; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
virtual bool isCommutative() const;
|
||||||
|
|
||||||
|
virtual bool isLeftAssociative() const;
|
||||||
|
|
||||||
|
virtual bool isRightAssociative() const;
|
||||||
|
|
||||||
Operator op; /**< Operator working on left and right */
|
Operator op; /**< Operator working on left and right */
|
||||||
Expression * left; /**< Left operand */
|
Expression * left; /**< Left operand */
|
||||||
Expression * right; /**< Right operand */
|
Expression * right; /**< Right operand */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,7 +38,6 @@ std::stack<FunctionExpression::Function> functions; /**< Function
|
||||||
%type <fvalue> NUM
|
%type <fvalue> NUM
|
||||||
%type <constant> CONSTANT
|
%type <constant> CONSTANT
|
||||||
%type <expr> num
|
%type <expr> num
|
||||||
%type <expr> basic_num
|
|
||||||
%type <expr> range
|
%type <expr> range
|
||||||
%type <path> identifier
|
%type <path> identifier
|
||||||
%type <components> path subpath
|
%type <components> path subpath
|
||||||
|
@ -46,18 +45,16 @@ std::stack<FunctionExpression::Function> functions; /**< Function
|
||||||
%type <string_or_identifier> document
|
%type <string_or_identifier> document
|
||||||
%type <string_or_identifier> object
|
%type <string_or_identifier> object
|
||||||
%type <ivalue> integer
|
%type <ivalue> integer
|
||||||
%left ONE
|
%left ONE NUM INTEGER CONSTANT
|
||||||
%left NUM
|
|
||||||
%left INTEGER
|
|
||||||
%left CONSTANT
|
|
||||||
%left EQ NEQ LT GT GTE LTE
|
%left EQ NEQ LT GT GTE LTE
|
||||||
%left '?' ':'
|
%left '?' ':'
|
||||||
%left MINUSSIGN '+'
|
%left MINUSSIGN '+'
|
||||||
%left '*' '/'
|
%left '*' '/'
|
||||||
|
%precedence NUM_AND_UNIT
|
||||||
|
%left '^' /* exponentiation */
|
||||||
|
%left EXPONENT
|
||||||
%left NEG /* negation--unary minus */
|
%left NEG /* negation--unary minus */
|
||||||
%left POS /* unary plus */
|
%left POS /* unary plus */
|
||||||
%right '^' /* exponentiation */
|
|
||||||
%right EXPONENT
|
|
||||||
|
|
||||||
%destructor { delete $$; } exp cond unit_exp
|
%destructor { delete $$; } exp cond unit_exp
|
||||||
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
|
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
|
||||||
|
@ -71,6 +68,7 @@ input: exp { ScanResult = $1; valueExpression = true;
|
||||||
;
|
;
|
||||||
|
|
||||||
exp: num { $$ = $1; }
|
exp: num { $$ = $1; }
|
||||||
|
| num unit_exp %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); }
|
||||||
| STRING { $$ = new StringExpression(DocumentObject, $1); }
|
| STRING { $$ = new StringExpression(DocumentObject, $1); }
|
||||||
| identifier { $$ = new VariableExpression(DocumentObject, $1); }
|
| identifier { $$ = new VariableExpression(DocumentObject, $1); }
|
||||||
| MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, -1)); }
|
| MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, -1)); }
|
||||||
|
@ -80,22 +78,16 @@ exp: num { $$ = $1;
|
||||||
| exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
|
| exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
|
||||||
| exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
| exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
||||||
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
||||||
| exp '^' exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
|
| exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
|
||||||
| '(' exp ')' { $$ = $2; }
|
| '(' exp ')' { $$ = $2; }
|
||||||
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); }
|
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); }
|
||||||
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
|
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
basic_num: ONE { $$ = new NumberExpression(DocumentObject, $1); }
|
num: ONE { $$ = new NumberExpression(DocumentObject, $1); }
|
||||||
| NUM { $$ = new NumberExpression(DocumentObject, $1); }
|
| NUM { $$ = new NumberExpression(DocumentObject, $1); }
|
||||||
| INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); }
|
| INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); }
|
||||||
;
|
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); }
|
||||||
|
|
||||||
num: basic_num { $$ = $1; }
|
|
||||||
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); }
|
|
||||||
| basic_num unit_exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); }
|
|
||||||
| CONSTANT unit_exp { $$ = new OperatorExpression(DocumentObject, new ConstantExpression(DocumentObject, $1.name, $1.fvalue), OperatorExpression::UNIT, $2); }
|
|
||||||
;
|
|
||||||
|
|
||||||
args: exp { $$.push_back($1); }
|
args: exp { $$.push_back($1); }
|
||||||
| range { $$.push_back($1); }
|
| range { $$.push_back($1); }
|
||||||
|
@ -119,13 +111,12 @@ cond: exp EQ exp { $$ = new OperatorExpression(Do
|
||||||
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
|
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
|
unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
|
||||||
| ONE '/' unit_exp { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, $1), OperatorExpression::DIV, $3); }
|
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
||||||
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
| unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
|
||||||
| unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
|
| unit_exp '^' integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, (double)$3)); }
|
||||||
| unit_exp '^' basic_num %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
|
| unit_exp '^' MINUSSIGN integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)$4), OperatorExpression::NEG, new NumberExpression(DocumentObject, -1))); }
|
||||||
| unit_exp '^' MINUSSIGN basic_num %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, $4, OperatorExpression::NEG, new NumberExpression(DocumentObject, -1))); }
|
| '(' unit_exp ')' { $$ = $2; }
|
||||||
| '(' unit_exp ')' { $$ = $2; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
identifier: path { /* Path to property within document object */
|
identifier: path { /* Path to property within document object */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user