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::stringstream s;
|
||||
bool needsParens;
|
||||
Operator leftOperator(NONE), rightOperator(NONE);
|
||||
|
||||
switch (op) {
|
||||
case NEG:
|
||||
s << "-";
|
||||
break;
|
||||
s << "-" << left->toString();
|
||||
return s.str();
|
||||
case POS:
|
||||
s << "+";
|
||||
break;
|
||||
s << "+" << left->toString();
|
||||
return s.str();
|
||||
default:
|
||||
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() << ")";
|
||||
else
|
||||
s << left->toString();
|
||||
|
@ -505,14 +519,23 @@ std::string OperatorExpression::toString() const
|
|||
break;
|
||||
case UNIT:
|
||||
break;
|
||||
case POS:
|
||||
case NEG:
|
||||
return s.str();
|
||||
default:
|
||||
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() << ")";
|
||||
else
|
||||
s << right->toString();
|
||||
|
@ -585,6 +608,35 @@ void OperatorExpression::visit(ExpressionVisitor &v)
|
|||
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.
|
||||
//
|
||||
|
|
|
@ -253,6 +253,13 @@ public:
|
|||
Expression * getRight() const { return right; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool isCommutative() const;
|
||||
|
||||
virtual bool isLeftAssociative() const;
|
||||
|
||||
virtual bool isRightAssociative() const;
|
||||
|
||||
Operator op; /**< Operator working on left and right */
|
||||
Expression * left; /**< Left 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 <constant> CONSTANT
|
||||
%type <expr> num
|
||||
%type <expr> basic_num
|
||||
%type <expr> range
|
||||
%type <path> identifier
|
||||
%type <components> path subpath
|
||||
|
@ -46,18 +45,16 @@ std::stack<FunctionExpression::Function> functions; /**< Function
|
|||
%type <string_or_identifier> document
|
||||
%type <string_or_identifier> object
|
||||
%type <ivalue> integer
|
||||
%left ONE
|
||||
%left NUM
|
||||
%left INTEGER
|
||||
%left CONSTANT
|
||||
%left ONE NUM INTEGER CONSTANT
|
||||
%left EQ NEQ LT GT GTE LTE
|
||||
%left '?' ':'
|
||||
%left MINUSSIGN '+'
|
||||
%left '*' '/'
|
||||
%precedence NUM_AND_UNIT
|
||||
%left '^' /* exponentiation */
|
||||
%left EXPONENT
|
||||
%left NEG /* negation--unary minus */
|
||||
%left POS /* unary plus */
|
||||
%right '^' /* exponentiation */
|
||||
%right EXPONENT
|
||||
|
||||
%destructor { delete $$; } exp cond unit_exp
|
||||
%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; }
|
||||
| num unit_exp %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); }
|
||||
| STRING { $$ = new StringExpression(DocumentObject, $1); }
|
||||
| identifier { $$ = new VariableExpression(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::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; }
|
||||
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); }
|
||||
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
|
||||
;
|
||||
|
||||
basic_num: ONE { $$ = new NumberExpression(DocumentObject, $1); }
|
||||
| NUM { $$ = new NumberExpression(DocumentObject, $1); }
|
||||
| INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); }
|
||||
;
|
||||
|
||||
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); }
|
||||
;
|
||||
num: ONE { $$ = new NumberExpression(DocumentObject, $1); }
|
||||
| NUM { $$ = new NumberExpression(DocumentObject, $1); }
|
||||
| INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); }
|
||||
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); }
|
||||
|
||||
args: exp { $$.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); }
|
||||
;
|
||||
|
||||
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::MUL, $3); }
|
||||
| unit_exp '^' basic_num %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
|
||||
| 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: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
|
||||
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $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 '^' MINUSSIGN integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)$4), OperatorExpression::NEG, new NumberExpression(DocumentObject, -1))); }
|
||||
| '(' unit_exp ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
identifier: path { /* Path to property within document object */
|
||||
|
|
Loading…
Reference in New Issue
Block a user