App: extend Expression syntax

* Support sub-object reference syntax using the following syntax,
    Part.<<Box.>>.Placement
  or, with sub-object label referencing
    Part.<<$Cube.>>.Placement

* Extend indexing support, including range based indexing, e.g.
    A1[B2+1][C3][D4:-1]

* Add new constants, None, True, true, False, false.
This commit is contained in:
Zheng, Lei
2019-08-29 18:53:51 +08:00
committed by wmayer
parent 22fede14d8
commit a1417c5ffa
10 changed files with 7670 additions and 7381 deletions

View File

@@ -1750,7 +1750,6 @@ void Application::initTypes(void)
App ::ConditionalExpression ::init();
App ::StringExpression ::init();
App ::FunctionExpression ::init();
App ::BooleanExpression ::init();
App ::RangeExpression ::init();
App ::PyObjectExpression ::init();

File diff suppressed because it is too large Load Diff

View File

@@ -124,15 +124,16 @@ public:
virtual bool isTouched() const { return false; }
virtual Expression * eval() const = 0;
Expression * eval() const;
virtual std::string toString(bool persistent=false) const = 0;
std::string toString(bool persistent=false, bool checkPriority=false, int indent=0) const;
void toString(std::ostream &os, bool persistent=false, bool checkPriority=false, int indent=0) const;
static Expression * parse(const App::DocumentObject * owner, const std::string& buffer);
Expression * copy() const;
virtual int priority() const { return 0; }
virtual int priority() const;
void getIdentifiers(std::set<App::ObjectIdentifier> &) const;
std::set<App::ObjectIdentifier> getIdentifiers() const;
@@ -163,17 +164,30 @@ public:
};
App::DocumentObject * getOwner() const { return owner; }
struct Component;
virtual boost::any getValueAsAny() const = 0;
virtual void addComponent(Component* component);
virtual Py::Object getPyValue() const = 0;
typedef std::vector<Component*> ComponentList;
static Component *createComponent(const std::string &n);
static Component *createComponent(Expression *e1, Expression *e2=0,
Expression *e3=0, bool isRange=false);
bool hasComponent() const {return !components.empty();}
boost::any getValueAsAny() const;
Py::Object getPyValue() const;
bool isSame(const Expression &other) const;
friend ExpressionVisitor;
protected:
virtual bool _isIndexable() const {return false;}
virtual Expression *_copy() const = 0;
virtual void _toString(std::ostream &ss, bool persistent, int indent=0) const = 0;
virtual void _getDeps(ExpressionDeps &) const {}
virtual void _getDepObjects(std::set<App::DocumentObject*> &, std::vector<std::string> *) const {}
virtual void _getIdentifiers(std::set<App::ObjectIdentifier> &) const {}
@@ -193,11 +207,14 @@ protected:
}
virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) {}
virtual void _offsetCells(int, int, ExpressionVisitor &) {}
virtual Py::Object _getPyValue() const = 0;
virtual void _visit(ExpressionVisitor &) {}
protected:
App::DocumentObject * owner; /**< The document object used to access unqualified variables (i.e local scope) */
ComponentList components;
public:
std::string comment;
};

View File

@@ -37,6 +37,32 @@ namespace App {
// included by everyone
///////////////////////////////////////////////////////////////////////////////////
struct AppExport Expression::Component {
ObjectIdentifier::Component comp;
Expression* e1;
Expression* e2;
Expression* e3;
Component(const std::string &n);
Component(Expression *e1, Expression *e2, Expression *e3, bool isRange=false);
Component(const ObjectIdentifier::Component &comp);
Component(const Component &other);
~Component();
Component &operator=(const Component &)=delete;
void visit(ExpressionVisitor &v);
bool isTouched() const;
void toString(std::ostream &ss, bool persistent) const;
Component *copy() const;
Component *eval() const;
Py::Object get(const Expression *owner, const Py::Object &pyobj) const;
void set(const Expression *owner, Py::Object &pyobj, const Py::Object &value) const;
void del(const Expression *owner, Py::Object &pyobj) const;
};
////////////////////////////////////////////////////////////////////////////////////
/**
* Part of an expressions that contains a unit.
*
@@ -47,16 +73,14 @@ class AppExport UnitExpression : public Expression {
public:
UnitExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string());
virtual Expression * eval() const override;
~UnitExpression();
virtual Expression * simplify() const override;
virtual std::string toString(bool persistent=false) const override;
virtual int priority() const override;
void setUnit(const Base::Quantity &_quantity);
void setQuantity(const Base::Quantity &_quantity);
double getValue() const { return quantity.getValue(); }
const Base::Unit & getUnit() const { return quantity.getUnit(); }
@@ -67,14 +91,15 @@ public:
double getScaler() const { return quantity.getValue(); }
boost::any getValueAsAny() const override { return quantity.getUnit().isEmpty() ? boost::any(quantity.getValue()) : boost::any(quantity); }
virtual Py::Object getPyValue() const override;
protected:
virtual Expression * _copy() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual Py::Object _getPyValue() const override;
protected:
mutable PyObject *cache = 0;
private:
Base::Quantity quantity;
std::string unitStr; /**< The unit string from the original parsed string */
};
@@ -88,51 +113,37 @@ class AppExport NumberExpression : public UnitExpression {
public:
NumberExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & quantity = Base::Quantity());
virtual Expression * eval() const override;
virtual Expression * simplify() const override;
virtual int priority() const override;
void negate();
virtual std::string toString(bool persistent=false) const;
bool isInteger(long *v=0) const;
protected:
virtual Expression * _copy() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
};
class AppExport ConstantExpression : public NumberExpression {
TYPESYSTEM_HEADER();
public:
ConstantExpression(const App::DocumentObject *_owner = 0, std::string _name = "", const Base::Quantity &_quantity = Base::Quantity());
virtual std::string toString(bool persistent=false) const override;
virtual Expression * _copy() const override;
virtual int priority() const override;
ConstantExpression(const App::DocumentObject *_owner = 0,
const char *_name = "",
const Base::Quantity &_quantity = Base::Quantity());
std::string getName() const { return name; }
protected:
std::string name; /**< Constant's name */
};
class AppExport BooleanExpression : public NumberExpression {
TYPESYSTEM_HEADER();
public:
BooleanExpression(const App::DocumentObject *_owner = 0, bool _value = false);
bool isNumber() const;
protected:
virtual Expression * _copy() const override;
virtual Py::Object _getPyValue() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual Expression* _copy() const override;
protected:
const char *name;
};
/**
* Class implementing an infix expression.
*
@@ -165,12 +176,8 @@ public:
virtual bool isTouched() const override;
virtual Expression * eval() const override;
virtual Expression * simplify() const override;
virtual std::string toString(bool persistent=false) const override;
virtual int priority() const override;
Operator getOperator() const { return op; }
@@ -179,13 +186,13 @@ public:
Expression * getRight() const { return right; }
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
protected:
virtual Expression * _copy() const override;
virtual Py::Object _getPyValue() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual void _visit(ExpressionVisitor & v) override;
virtual bool isCommutative() const;
@@ -208,22 +215,15 @@ public:
virtual bool isTouched() const override;
virtual Expression * eval() const override;
virtual Expression * simplify() const override;
virtual std::string toString(bool persistent=false) const override;
virtual int priority() const override;
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
protected:
virtual Expression * _copy() const;
virtual void _visit(ExpressionVisitor & v) override;
bool evalCond() const;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual Py::Object _getPyValue() const override;
protected:
@@ -290,25 +290,16 @@ public:
virtual bool isTouched() const override;
virtual Expression * eval() const override;
virtual Expression * simplify() const override;
virtual std::string toString(bool persistent=false) const override;
virtual Expression * _copy() const override;
virtual int priority() const override;
virtual void _visit(ExpressionVisitor & v) override;
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
static Py::Object evaluate(const Expression *owner, int type, const std::vector<Expression*> &args);
protected:
Expression *evalAggregate() const;
static Py::Object evalAggregate(const Expression *owner, int type, const std::vector<Expression*> &args);
virtual Py::Object _getPyValue() const override;
virtual Expression * _copy() const override;
virtual void _visit(ExpressionVisitor & v) override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
Function f; /**< Function to execute */
std::vector<Expression *> args; /** Arguments to function*/
@@ -331,16 +322,8 @@ public:
virtual bool isTouched() const override;
virtual Expression * eval() const override;
virtual Expression * simplify() const override;
virtual std::string toString(bool persistent=false) const override;
virtual Expression * _copy() const override;
virtual int priority() const override;
std::string name() const { return var.getPropertyName(); }
ObjectIdentifier getPath() const { return var; }
@@ -349,11 +332,13 @@ public:
const App::Property *getProperty() const;
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
virtual void addComponent(Component* component) override;
protected:
virtual Expression * _copy() const override;
virtual Py::Object _getPyValue() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual bool _isIndexable() const override;
virtual void _getDeps(ExpressionDeps &) const override;
virtual void _getDepObjects(std::set<App::DocumentObject*> &, std::vector<std::string> *) const override;
virtual void _getIdentifiers(std::set<App::ObjectIdentifier> &) const override;
@@ -391,16 +376,12 @@ public:
void setPyValue(Py::Object pyobj);
void setPyValue(PyObject *pyobj, bool owned=false);
virtual std::string toString(bool) const override;
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
virtual Expression * eval() const override { return copy(); }
virtual Expression * simplify() const override { return copy(); }
protected:
virtual Expression* _copy() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual Py::Object _getPyValue() const override;
protected:
PyObject *pyObj = 0;
@@ -415,25 +396,20 @@ class AppExport StringExpression : public Expression {
TYPESYSTEM_HEADER();
public:
StringExpression(const App::DocumentObject *_owner = 0, const std::string & _text = std::string());
virtual Expression * eval() const override;
~StringExpression();
virtual Expression * simplify() const override;
virtual std::string toString(bool persistent=false) const override;
virtual std::string getText() const { return text; }
virtual int priority() const override;
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
protected:
virtual Expression * _copy() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual Py::Object _getPyValue() const override;
virtual bool _isIndexable() const override { return true; }
private:
std::string text; /**< Text string */
mutable PyObject *cache = 0;
};
class AppExport RangeExpression : public App::Expression {
@@ -445,22 +421,14 @@ public:
virtual bool isTouched() const override;
virtual Expression * eval() const override;
virtual std::string toString(bool persistent=false) const override;
virtual int priority() const override;
virtual App::Expression * simplify() const override;
Range getRange() const;
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;
protected:
virtual Expression * _copy() const override;
virtual void _toString(std::ostream &ss, bool persistent, int indent) const override;
virtual Py::Object _getPyValue() const override;
virtual void _getDeps(ExpressionDeps &) const override;
virtual bool _renameObjectIdentifier(const std::map<ObjectIdentifier,ObjectIdentifier> &,
const ObjectIdentifier &, ExpressionVisitor &) override;
@@ -500,13 +468,14 @@ public:
Base::Quantity scaler;
std::string unitStr;
} quantity;
Expression::Component *component;
Expression * expr;
ObjectIdentifier path;
std::deque<ObjectIdentifier::Component> components;
long long int ivalue;
double fvalue;
struct {
std::string name;
const char *name = "";
double fvalue = 0;
} constant;
std::vector<Expression*> arguments;

View File

@@ -264,6 +264,12 @@ EXPO [eE][-+]?[0-9]+
"pi" COUNTCHARS; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi
"e" COUNTCHARS; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e
"None" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "None"; return CONSTANT;
"True" COUNTCHARS; yylval.constant.fvalue = 1; yylval.constant.name = "True"; return CONSTANT;
"true" COUNTCHARS; yylval.constant.fvalue = 1; yylval.constant.name = "True"; return CONSTANT;
"False" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "False"; return CONSTANT;
"false" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "False"; return CONSTANT;
$[A-Za-z]{1,2}+${DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDRESS;
[A-Za-z]{1,2}${DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDRESS;
$[A-Za-z]{1,2}{DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDRESS;

File diff suppressed because it is too large Load Diff

View File

@@ -29,9 +29,9 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%token DOCUMENT OBJECT
%token EXPONENT
%type <arguments> args
%type <expr> input exp unit_exp cond
%type <expr> input exp unit_exp cond indexable
%type <quantity> UNIT
%type <string> STRING IDENTIFIER CELLADDRESS
%type <string> id_or_cell STRING IDENTIFIER CELLADDRESS
%type <ivalue> INTEGER
%type <string> PROPERTY_REF
%type <fvalue> ONE
@@ -39,8 +39,8 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%type <constant> CONSTANT
%type <expr> num
%type <expr> range
%type <path> identifier
%type <components> path subpath
%type <path> identifier iden
%type <component> indexer
%type <func> FUNC
%type <string_or_identifier> document
%type <string_or_identifier> object
@@ -56,7 +56,8 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%left NEG /* negation--unary minus */
%left POS /* unary plus */
%destructor { delete $$; } exp cond unit_exp
%destructor { delete $$; } num range exp cond unit_exp indexable
%destructor { delete $$; } <component>
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
%start input
@@ -64,7 +65,7 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%%
input: exp { ScanResult = $1; valueExpression = true; }
| unit_exp { ScanResult = $1; unitExpression = true; }
| unit_exp { ScanResult = $1; unitExpression = true; }
;
exp: num { $$ = $1; }
@@ -80,7 +81,7 @@ exp: num { $$ = $1;
| exp '%' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MOD, $3); }
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
| exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
| '(' exp ')' { $$ = $2; }
| indexable { $$ = $1; }
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); }
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
;
@@ -98,10 +99,7 @@ args: exp { $$.push_back($1);
| args ';' range { $1.push_back($3); $$ = $1; }
;
range: CELLADDRESS ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
| CELLADDRESS ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
| IDENTIFIER ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
| IDENTIFIER ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
range: id_or_cell ':' id_or_cell { $$ = new RangeExpression(DocumentObject, $1, $3); }
;
cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }
@@ -120,72 +118,87 @@ unit_exp: UNIT { $$ = new UnitExpression(Docume
| '(' unit_exp ')' { $$ = $2; }
;
identifier: path { /* Path to property within document object */
$$ = ObjectIdentifier(DocumentObject);
$$.addComponents($1);
$$.resolveAmbiguity();
}
| '.' path { /* Path to property of the current document object */
$$ = ObjectIdentifier(DocumentObject,true);
$$.setDocumentObjectName(DocumentObject);
$$.addComponents($2);
}
| object '.' path { /* Path to property within document object */
$$ = ObjectIdentifier(DocumentObject);
$1.checkImport(DocumentObject);
$$.addComponent(ObjectIdentifier::SimpleComponent($1));
$$.addComponents($3);
$$.resolveAmbiguity();
}
| document '#' path { /* Path to property from an external document, within a named document object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentName(std::move($1), true);
$$.addComponents($3);
$$.resolveAmbiguity();
}
| document '#' object '.' path { /* Path to property from an external document, within a named document object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentName(std::move($1), true);
$$.setDocumentObjectName(std::move($3), true);
$$.addComponents($5);
$$.resolveAmbiguity();
}
;
integer: INTEGER { $$ = $1; }
| ONE { $$ = $1; }
;
path: IDENTIFIER { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| CELLADDRESS { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $6; }
| IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); }
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); $$.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $6; }
| IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $6; }
| IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $3; }
id_or_cell
: IDENTIFIER { $$ = std::move($1); }
| CELLADDRESS { $$ = std::move($1); }
;
subpath: IDENTIFIER { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| STRING { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| CELLADDRESS { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1));$$ = $6; }
| IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
| IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); $$.push_front(ObjectIdentifier::SimpleComponent($1));$$ = $6; }
| IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1));$$ = $6; }
| IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $3; }
identifier
: id_or_cell { $$ = ObjectIdentifier(DocumentObject); $$ << ObjectIdentifier::SimpleComponent($1); }
| iden { $$ = std::move($1); }
;
document: STRING { $$ = ObjectIdentifier::String($1, true); }
| IDENTIFIER { $$ = ObjectIdentifier::String($1); }
;
iden
: '.' STRING '.' id_or_cell { /* Path to property of a sub-object of the current object*/
$$ = ObjectIdentifier(DocumentObject,true);
$$.setDocumentObjectName(DocumentObject,false,ObjectIdentifier::String(std::move($2),true),true);
$$.addComponent(ObjectIdentifier::SimpleComponent($4));
}
| '.' id_or_cell { /* Path to property of the current document object */
$$ = ObjectIdentifier(DocumentObject,true);
$$.setDocumentObjectName(DocumentObject);
$$.addComponent(ObjectIdentifier::SimpleComponent($2));
}
| object '.' STRING '.' id_or_cell { /* Path to property of a sub-object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentObjectName(std::move($1), true, ObjectIdentifier::String(std::move($3),true),true);
$$.addComponent(ObjectIdentifier::SimpleComponent($5));
$$.resolveAmbiguity();
}
| object '.' id_or_cell { /* Path to property of a given document object */
$$ = ObjectIdentifier(DocumentObject);
$1.checkImport(DocumentObject);
$$.addComponent(ObjectIdentifier::SimpleComponent($1));
$$.addComponent(ObjectIdentifier::SimpleComponent($3));
$$.resolveAmbiguity();
}
| document '#' object '.' id_or_cell { /* Path to property from an external document, within a named document object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentName(std::move($1), true);
$$.setDocumentObjectName(std::move($3), true);
$$.addComponent(ObjectIdentifier::SimpleComponent($5));
$$.resolveAmbiguity();
}
| document '#' object '.' STRING '.' id_or_cell
{ $$ = ObjectIdentifier(DocumentObject);
$$.setDocumentName(std::move($1), true);
$$.setDocumentObjectName(std::move($3), true, ObjectIdentifier::String(std::move($5),true));
$$.addComponent(ObjectIdentifier::SimpleComponent($7));
$$.resolveAmbiguity();
}
| iden '.' IDENTIFIER { $$= std::move($1); $$.addComponent(ObjectIdentifier::SimpleComponent($3)); }
;
object: STRING { $$ = ObjectIdentifier::String($1, true); }
| CELLADDRESS { $$ = ObjectIdentifier::String($1, true); }
;
indexer
: '[' exp ']' { $$ = Expression::createComponent($2); }
| '[' exp ':' ']' { $$ = Expression::createComponent($2,0,0,true); }
| '[' ':' exp ']' { $$ = Expression::createComponent(0,$3); }
| '[' ':' ':' exp ']' { $$ = Expression::createComponent(0,0,$4); }
| '[' exp ':' exp ']' { $$ = Expression::createComponent($2,$4);}
| '[' exp ':' ':' exp ']' { $$ = Expression::createComponent($2,0,$5); }
| '[' ':' exp ':' exp ']' { $$ = Expression::createComponent(0,$3,$5); }
| '[' exp ':' exp ':' exp ']' { $$ = Expression::createComponent($2,$4,$6);}
;
indexable
: '(' exp ')' { $$ = $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; }
;
document
: STRING { $$ = ObjectIdentifier::String(std::move($1), true); }
| IDENTIFIER { $$ = ObjectIdentifier::String(std::move($1), false, true);}
;
object
: STRING { $$ = ObjectIdentifier::String(std::move($1), true); }
| id_or_cell { $$ = ObjectIdentifier::String(std::move($1), false);}
;
%%

View File

@@ -553,8 +553,7 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o
App::any value;
try {
// Evaluate expression
std::unique_ptr<Expression> e(expressions[*it].expression->eval());
value = e->getValueAsAny();
value = expressions[*it].expression->getValueAsAny();
if(option == ExecuteOnRestore && prop->testStatus(Property::EvalOnRestore)) {
if(isAnyEqual(value, prop->getPathValue(*it)))
continue;

File diff suppressed because it is too large Load Diff

View File

@@ -692,7 +692,11 @@ void Sheet::updateProperty(CellAddress key)
auto number = freecad_dynamic_cast<NumberExpression>(output.get());
if(number) {
long l;
if (!number->getUnit().isEmpty())
auto constant = freecad_dynamic_cast<ConstantExpression>(output.get());
if(constant && !constant->isNumber()) {
Base::PyGILStateLocker lock;
setObjectProperty(key, constant->getPyValue());
} else if (!number->getUnit().isEmpty())
setQuantityProperty(key, number->getValue(), number->getUnit());
else if(number->isInteger(&l))
setIntegerProperty(key,l);