From ea7eee8061b93858616c1f0829ff2f2373450f0b Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Mon, 26 Aug 2019 12:09:09 +0800 Subject: [PATCH] Expression: split Expression.h to ExpressionParser.h Split Expression details into a separate header to reduce recompilation time on changes. --- src/App/Application.cpp | 2 +- src/App/CMakeLists.txt | 1 + src/App/Document.cpp | 1 + src/App/DocumentObjectPyImp.cpp | 2 +- src/App/Expression.cpp | 6 +- src/App/Expression.h | 485 ---------------- src/App/ExpressionParser.h | 527 ++++++++++++++++++ src/App/ObjectIdentifier.cpp | 2 +- src/Gui/DlgExpressionInput.cpp | 2 +- src/Gui/ExpressionCompleter.cpp | 2 +- src/Gui/InputField.cpp | 1 + src/Gui/QuantitySpinBox.cpp | 2 +- src/Gui/SpinBox.cpp | 2 +- src/Gui/Widgets.cpp | 2 +- .../Sketcher/App/PropertyConstraintList.cpp | 1 + src/Mod/Spreadsheet/App/Cell.cpp | 2 +- src/Mod/Spreadsheet/App/PropertySheet.cpp | 1 + src/Mod/Spreadsheet/App/Sheet.cpp | 1 + src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp | 1 + 19 files changed, 546 insertions(+), 497 deletions(-) create mode 100644 src/App/ExpressionParser.h diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 105c2961d2..f9be6d13b1 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -108,7 +108,7 @@ #include "Origin.h" #include "MaterialObject.h" #include "TextDocument.h" -#include "Expression.h" +#include "ExpressionParser.h" #include "Transactions.h" #include #include diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt index 9ed3a7c1e5..bd275302ab 100644 --- a/src/App/CMakeLists.txt +++ b/src/App/CMakeLists.txt @@ -184,6 +184,7 @@ SET(Document_HPP_SRCS DocumentObserver.h DocumentObserverPython.h Expression.h + ExpressionParser.h ExpressionVisitors.h FeatureCustom.h FeaturePython.h diff --git a/src/App/Document.cpp b/src/App/Document.cpp index fa8b662c1c..97c4a1b7df 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -95,6 +95,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include "Application.h" #include "DocumentObject.h" #include "MergeDocuments.h" +#include "ExpressionParser.h" #include #include diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp index 8ea504a01e..182d6bc520 100644 --- a/src/App/DocumentObjectPyImp.cpp +++ b/src/App/DocumentObjectPyImp.cpp @@ -26,7 +26,7 @@ #include #include "DocumentObject.h" #include "Document.h" -#include "Expression.h" +#include "ExpressionParser.h" #include "GeoFeature.h" #include "GroupExtension.h" #include "GeoFeatureGroupExtension.h" diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index 4ca75f5cf3..0c041cbf66 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -47,7 +47,7 @@ #include #include #include -#include "Expression.h" +#include "ExpressionParser.h" #include #include #include @@ -2385,13 +2385,13 @@ Py::Object PyObjectExpression::getPyValue() const { return Py::Object(pyObj); } -void PyObjectExpression::setPyObject(Py::Object obj) { +void PyObjectExpression::setPyValue(Py::Object obj) { Py::_XDECREF(pyObj); pyObj = obj.ptr(); Py::_XINCREF(pyObj); } -void PyObjectExpression::setPyObject(PyObject *obj, bool owned) { +void PyObjectExpression::setPyValue(PyObject *obj, bool owned) { if(pyObj == obj) return; Py::_XDECREF(pyObj); diff --git a/src/App/Expression.h b/src/App/Expression.h index aad5c365a7..8083ec4ad0 100644 --- a/src/App/Expression.h +++ b/src/App/Expression.h @@ -35,7 +35,6 @@ #include #include -//FIXME: PyObjectExpression hides overloaded virtual functions #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Woverloaded-virtual" @@ -203,490 +202,6 @@ public: std::string comment; }; -/** - * Part of an expressions that contains a unit. - * - */ - -class AppExport UnitExpression : public Expression { - TYPESYSTEM_HEADER(); -public: - UnitExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string()); - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString(bool persistent=false) const; - - virtual Expression * _copy() const; - - virtual int priority() const; - - void setUnit(const Base::Quantity &_quantity); - - double getValue() const { return quantity.getValue(); } - - const Base::Unit & getUnit() const { return quantity.getUnit(); } - - const Base::Quantity & getQuantity() const { return quantity; } - - const std::string getUnitString() const { return unitStr; } - - double getScaler() const { return quantity.getValue(); } - - boost::any getValueAsAny() const { return quantity.getUnit().isEmpty() ? boost::any(quantity.getValue()) : boost::any(quantity); } - - virtual Py::Object getPyValue() const; - -protected: - Base::Quantity quantity; - std::string unitStr; /**< The unit string from the original parsed string */ -}; - -/** - * Class implementing a number with an optional unit - */ - -class AppExport NumberExpression : public UnitExpression { - TYPESYSTEM_HEADER(); -public: - NumberExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & quantity = Base::Quantity()); - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual Expression * _copy() const; - - virtual int priority() const; - - void negate(); - - virtual std::string toString(bool persistent=false) const; - - bool isInteger(long *v=0) const; - -protected: -}; - -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; - - virtual Expression * _copy() const; - - virtual int priority() const; - - 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); - - virtual Expression * _copy() const; - -}; - - -/** - * Class implementing an infix expression. - * - */ - -class AppExport OperatorExpression : public UnitExpression { - TYPESYSTEM_HEADER(); -public: - enum Operator { - NONE, - ADD, - SUB, - MUL, - DIV, - MOD, - POW, - EQ, - NEQ, - LT, - GT, - LTE, - GTE, - UNIT, - NEG, - POS - }; - OperatorExpression(const App::DocumentObject *_owner = 0, Expression * _left = 0, Operator _op = NONE, Expression * _right = 0); - - virtual ~OperatorExpression(); - - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString(bool persistent=false) const; - - virtual Expression * _copy() const; - - virtual int priority() const; - - virtual void _visit(ExpressionVisitor & v); - - Operator getOperator() const { return op; } - - Expression * getLeft() const { return left; } - - Expression * getRight() const { return right; } - - virtual boost::any getValueAsAny() const; - - virtual Py::Object getPyValue() const; - -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 */ -}; - -class AppExport ConditionalExpression : public Expression { - TYPESYSTEM_HEADER(); -public: - ConditionalExpression(const App::DocumentObject *_owner = 0, Expression * _condition = 0,Expression * _trueExpr = 0, Expression * _falseExpr = 0); - - virtual ~ConditionalExpression(); - - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString(bool persistent=false) const; - - virtual int priority() const; - - virtual boost::any getValueAsAny() const; - - virtual Py::Object getPyValue() const; - -protected: - virtual Expression * _copy() const; - virtual void _visit(ExpressionVisitor & v); - bool evalCond() const; - -protected: - - Expression * condition; /**< Condition */ - Expression * trueExpr; /**< Expression if abs(condition) is > 0.5 */ - Expression * falseExpr; /**< Expression if abs(condition) is < 0.5 */ -}; - -/** - * Class implementing various functions, e.g sin, cos, etc. - * - */ - -class AppExport FunctionExpression : public UnitExpression { - TYPESYSTEM_HEADER(); -public: - enum Function { - NONE, - - // Normal functions taking one or two arguments - ACOS, - ASIN, - ATAN, - ABS, - EXP, - LOG, - LOG10, - SIN, - SINH, - TAN, - TANH, - SQRT, - COS, - COSH, - ATAN2, - MOD, - POW, - ROUND, - TRUNC, - CEIL, - FLOOR, - HYPOT, - CATH, - - // Aggregates - AGGREGATES, - - SUM, - AVERAGE, - STDDEV, - COUNT, - MIN, - MAX, - - // Last one - LAST, - }; - - FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, std::vector _args = std::vector()); - - virtual ~FunctionExpression(); - - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString(bool persistent=false) const; - - virtual Expression * _copy() const; - - virtual int priority() const; - - virtual void _visit(ExpressionVisitor & v); - - virtual boost::any getValueAsAny() const; - - virtual Py::Object getPyValue() const; - - -protected: - Expression *evalAggregate() const; - - Function f; /**< Function to execute */ - std::vector args; /** Arguments to function*/ -}; - -/** - * Class implementing a reference to a property. If the name is unqualified, - * the owner of the expression is searched. If it is qualified, the document - * that contains the owning document object is searched for other document - * objects to search. Both labels and internal document names are searched. - * - */ - -class AppExport VariableExpression : public UnitExpression { - TYPESYSTEM_HEADER(); -public: - VariableExpression(const App::DocumentObject *_owner = 0, ObjectIdentifier _var = ObjectIdentifier()); - - ~VariableExpression(); - - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString(bool persistent=false) const; - - virtual Expression * _copy() const; - - virtual int priority() const; - - std::string name() const { return var.getPropertyName(); } - - ObjectIdentifier getPath() const { return var; } - - void setPath(const ObjectIdentifier & path); - - const App::Property *getProperty() const; - - virtual boost::any getValueAsAny() const; - - virtual Py::Object getPyValue() const; - -protected: - virtual void _getDeps(ExpressionDeps &) const; - virtual void _getDepObjects(std::set &, std::vector *) const; - virtual void _getIdentifiers(std::set &) const; - virtual bool _adjustLinks(const std::set &, ExpressionVisitor &); - virtual void _importSubNames(const ObjectIdentifier::SubNameMap &); - virtual void _updateLabelReference(App::DocumentObject *, const std::string &, const char *); - virtual bool _updateElementReference(App::DocumentObject *,bool,ExpressionVisitor &); - virtual bool _relabeledDocument(const std::string &, const std::string &, ExpressionVisitor &); - virtual bool _renameObjectIdentifier(const std::map &, - const ObjectIdentifier &, ExpressionVisitor &); - virtual void _collectReplacement(std::map &, - const App::DocumentObject *parent, App::DocumentObject *oldObj, - App::DocumentObject *newObj) const; - virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &); - virtual void _offsetCells(int, int, ExpressionVisitor &); - -protected: - - ObjectIdentifier var; /**< Variable name */ -}; - -////////////////////////////////////////////////////////////////////// - -class AppExport PyObjectExpression : public Expression { - TYPESYSTEM_HEADER(); - -public: - PyObjectExpression(const App::DocumentObject *_owner=0, PyObject *pyobj=0, bool owned=false) - :Expression(_owner) - { - setPyObject(pyobj,owned); - } - - virtual ~PyObjectExpression(); - - void setPyObject(Py::Object pyobj); - void setPyObject(PyObject *pyobj, bool owned=false); - - virtual std::string toString(bool) const; - virtual boost::any getValueAsAny() const; - virtual Py::Object getPyValue() const; - - virtual Expression * eval() const { return copy(); } - virtual Expression * simplify() const { return copy(); } - -protected: - virtual Expression* _copy() const; - -protected: - PyObject *pyObj = 0; -}; - -/** - * Class implementing a string. Used to signal either a genuine string or - * a failed evaluation of an expression. - */ - -class AppExport StringExpression : public Expression { - TYPESYSTEM_HEADER(); -public: - StringExpression(const App::DocumentObject *_owner = 0, const std::string & _text = std::string()); - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString(bool persistent=false) const; - - virtual std::string getText() const { return text; } - - virtual int priority() const; - - virtual boost::any getValueAsAny() const; - - virtual Py::Object getPyValue() const; - -protected: - virtual Expression * _copy() const; - - std::string text; /**< Text string */ -}; - -class AppExport RangeExpression : public App::Expression { - TYPESYSTEM_HEADER(); -public: - RangeExpression(const App::DocumentObject * _owner = 0, const std::string & begin = std::string(), const std::string & end = std::string()); - - virtual ~RangeExpression() { } - - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual std::string toString(bool persistent=false) const; - - virtual int priority() const; - - virtual App::Expression * simplify() const; - - Range getRange() const; - - virtual boost::any getValueAsAny() const { return boost::any(); } - - virtual Py::Object getPyValue() const; - -protected: - virtual Expression * _copy() const; - virtual void _getDeps(ExpressionDeps &) const; - virtual bool _renameObjectIdentifier(const std::map &, - const ObjectIdentifier &, ExpressionVisitor &); - virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &); - virtual void _offsetCells(int, int, ExpressionVisitor &); - -protected: - std::string begin; - std::string end; -}; - -namespace ExpressionParser { -AppExport Expression * parse(const App::DocumentObject *owner, const char *buffer); -AppExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer); -AppExport ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer); -AppExport bool isTokenAnIndentifier(const std::string & str); -AppExport bool isTokenAUnit(const std::string & str); -AppExport std::vector > tokenize(const std::string & str); - -/// Convenient class to mark begin of importing -class AppExport ExpressionImporter { -public: - ExpressionImporter(Base::XMLReader &reader); - ~ExpressionImporter(); - static Base::XMLReader *reader(); -}; - -AppExport bool isModuleImported(PyObject *); - -/** - * @brief The semantic_type class encapsulates the value in the parse tree during parsing. - */ - -class semantic_type { -public: - struct { - Base::Quantity scaler; - std::string unitStr; - } quantity; - Expression * expr; - ObjectIdentifier path; - std::deque components; - long long int ivalue; - double fvalue; - struct { - std::string name; - double fvalue = 0; - } constant; - std::vector arguments; - std::vector list; - std::string string; - FunctionExpression::Function func; - ObjectIdentifier::String string_or_identifier; - semantic_type() : expr(0), ivalue(0), fvalue(0), func(FunctionExpression::NONE) {} -}; - -#define YYSTYPE semantic_type -#include "ExpressionParser.tab.h" -#undef YYTOKENTYPE -#undef YYSTYPE -#undef YYSTYPE_ISDECLARED -} - } #if defined(__clang__) diff --git a/src/App/ExpressionParser.h b/src/App/ExpressionParser.h new file mode 100644 index 0000000000..2862fbebf9 --- /dev/null +++ b/src/App/ExpressionParser.h @@ -0,0 +1,527 @@ +/**************************************************************************** + * Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) * + * Copyright (c) 2019 Zheng, Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + + +#ifndef EXPRESSION_PARSER_H +#define EXPRESSION_PARSER_H + +#include +#include "Expression.h" + +namespace App { + +//////////////////////////////////////////////////////////////////////////////////// +// Expecting the extended expression is going to be constantly amended (to +// conform to Python), we move most of the class declarations here to avoid +// constant recompiling of the whole FC code base, as the expression header is +// included by everyone +/////////////////////////////////////////////////////////////////////////////////// + +/** + * Part of an expressions that contains a unit. + * + */ + +class AppExport UnitExpression : public Expression { + TYPESYSTEM_HEADER(); +public: + UnitExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string()); + + virtual Expression * eval() const override; + + 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); + + double getValue() const { return quantity.getValue(); } + + const Base::Unit & getUnit() const { return quantity.getUnit(); } + + const Base::Quantity & getQuantity() const { return quantity; } + + const std::string getUnitString() const { return unitStr; } + + 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; + +protected: + Base::Quantity quantity; + std::string unitStr; /**< The unit string from the original parsed string */ +}; + +/** + * Class implementing a number with an optional unit + */ + +class AppExport NumberExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +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; + +}; + +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; + + 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); + +protected: + virtual Expression * _copy() const override; + +}; + + +/** + * Class implementing an infix expression. + * + */ + +class AppExport OperatorExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + enum Operator { + NONE, + ADD, + SUB, + MUL, + DIV, + MOD, + POW, + EQ, + NEQ, + LT, + GT, + LTE, + GTE, + UNIT, + NEG, + POS + }; + OperatorExpression(const App::DocumentObject *_owner = 0, Expression * _left = 0, Operator _op = NONE, Expression * _right = 0); + + virtual ~OperatorExpression(); + + 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; } + + Expression * getLeft() const { return left; } + + Expression * getRight() const { return right; } + + virtual boost::any getValueAsAny() const override; + + virtual Py::Object getPyValue() const override; + +protected: + virtual Expression * _copy() const override; + + virtual void _visit(ExpressionVisitor & v) override; + + 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 */ +}; + +class AppExport ConditionalExpression : public Expression { + TYPESYSTEM_HEADER(); +public: + ConditionalExpression(const App::DocumentObject *_owner = 0, Expression * _condition = 0,Expression * _trueExpr = 0, Expression * _falseExpr = 0); + + virtual ~ConditionalExpression(); + + 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; + +protected: + + Expression * condition; /**< Condition */ + Expression * trueExpr; /**< Expression if abs(condition) is > 0.5 */ + Expression * falseExpr; /**< Expression if abs(condition) is < 0.5 */ +}; + +/** + * Class implementing various functions, e.g sin, cos, etc. + * + */ + +class AppExport FunctionExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + enum Function { + NONE, + + // Normal functions taking one or two arguments + ACOS, + ASIN, + ATAN, + ABS, + EXP, + LOG, + LOG10, + SIN, + SINH, + TAN, + TANH, + SQRT, + COS, + COSH, + ATAN2, + MOD, + POW, + ROUND, + TRUNC, + CEIL, + FLOOR, + HYPOT, + CATH, + + // Aggregates + AGGREGATES, + + SUM, + AVERAGE, + STDDEV, + COUNT, + MIN, + MAX, + + // Last one + LAST, + }; + + FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, std::vector _args = std::vector()); + + virtual ~FunctionExpression(); + + 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; + + +protected: + Expression *evalAggregate() const; + + Function f; /**< Function to execute */ + std::vector args; /** Arguments to function*/ +}; + +/** + * Class implementing a reference to a property. If the name is unqualified, + * the owner of the expression is searched. If it is qualified, the document + * that contains the owning document object is searched for other document + * objects to search. Both labels and internal document names are searched. + * + */ + +class AppExport VariableExpression : public UnitExpression { + TYPESYSTEM_HEADER(); +public: + VariableExpression(const App::DocumentObject *_owner = 0, ObjectIdentifier _var = ObjectIdentifier()); + + ~VariableExpression(); + + 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; } + + void setPath(const ObjectIdentifier & path); + + const App::Property *getProperty() const; + + virtual boost::any getValueAsAny() const override; + + virtual Py::Object getPyValue() const override; + +protected: + virtual void _getDeps(ExpressionDeps &) const override; + virtual void _getDepObjects(std::set &, std::vector *) const override; + virtual void _getIdentifiers(std::set &) const override; + virtual bool _adjustLinks(const std::set &, ExpressionVisitor &) override; + virtual void _importSubNames(const ObjectIdentifier::SubNameMap &) override; + virtual void _updateLabelReference(App::DocumentObject *, const std::string &, const char *) override; + virtual bool _updateElementReference(App::DocumentObject *,bool,ExpressionVisitor &) override; + virtual bool _relabeledDocument(const std::string &, const std::string &, ExpressionVisitor &) override; + virtual bool _renameObjectIdentifier(const std::map &, + const ObjectIdentifier &, ExpressionVisitor &) override; + virtual void _collectReplacement(std::map &, + const App::DocumentObject *parent, App::DocumentObject *oldObj, + App::DocumentObject *newObj) const override; + virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override; + virtual void _offsetCells(int, int, ExpressionVisitor &) override; + +protected: + + ObjectIdentifier var; /**< Variable name */ +}; + +////////////////////////////////////////////////////////////////////// + +class AppExport PyObjectExpression : public Expression { + TYPESYSTEM_HEADER(); + +public: + PyObjectExpression(const App::DocumentObject *_owner=0, PyObject *pyobj=0, bool owned=false) + :Expression(_owner) + { + setPyValue(pyobj,owned); + } + + virtual ~PyObjectExpression(); + + 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; + +protected: + PyObject *pyObj = 0; +}; + +/** + * Class implementing a string. Used to signal either a genuine string or + * a failed evaluation of an expression. + */ + +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; + + 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; + + std::string text; /**< Text string */ +}; + +class AppExport RangeExpression : public App::Expression { + TYPESYSTEM_HEADER(); +public: + RangeExpression(const App::DocumentObject * _owner = 0, const std::string & begin = std::string(), const std::string & end = std::string()); + + virtual ~RangeExpression() { } + + 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 { return boost::any(); } + + virtual Py::Object getPyValue() const override; + +protected: + virtual Expression * _copy() const override; + virtual void _getDeps(ExpressionDeps &) const override; + virtual bool _renameObjectIdentifier(const std::map &, + const ObjectIdentifier &, ExpressionVisitor &) override; + virtual void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override; + virtual void _offsetCells(int, int, ExpressionVisitor &) override; + +protected: + std::string begin; + std::string end; +}; + +namespace ExpressionParser { +AppExport Expression * parse(const App::DocumentObject *owner, const char *buffer); +AppExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer); +AppExport ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer); +AppExport bool isTokenAnIndentifier(const std::string & str); +AppExport bool isTokenAUnit(const std::string & str); +AppExport std::vector > tokenize(const std::string & str); + +/// Convenient class to mark begin of importing +class AppExport ExpressionImporter { +public: + ExpressionImporter(Base::XMLReader &reader); + ~ExpressionImporter(); + static Base::XMLReader *reader(); +}; + +AppExport bool isModuleImported(PyObject *); + +/** + * @brief The semantic_type class encapsulates the value in the parse tree during parsing. + */ + +class semantic_type { +public: + struct { + Base::Quantity scaler; + std::string unitStr; + } quantity; + Expression * expr; + ObjectIdentifier path; + std::deque components; + long long int ivalue; + double fvalue; + struct { + std::string name; + double fvalue = 0; + } constant; + std::vector arguments; + std::vector list; + std::string string; + FunctionExpression::Function func; + ObjectIdentifier::String string_or_identifier; + semantic_type() : expr(0), ivalue(0), fvalue(0), func(FunctionExpression::NONE) {} +}; + +#define YYSTYPE semantic_type +#include "ExpressionParser.tab.h" +#undef YYTOKENTYPE +#undef YYSTYPE +#undef YYSTYPE_ISDECLARED +} + +} + +#endif //EXPRESSION_PARSER_H diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index 37c09ec337..253a4bf6cb 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -39,7 +39,7 @@ #include "Document.h" #include "DocumentObject.h" #include "ObjectIdentifier.h" -#include "Expression.h" +#include "ExpressionParser.h" #include #include #include diff --git a/src/Gui/DlgExpressionInput.cpp b/src/Gui/DlgExpressionInput.cpp index 990cc471cb..55426e0f80 100644 --- a/src/Gui/DlgExpressionInput.cpp +++ b/src/Gui/DlgExpressionInput.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include using namespace App; diff --git a/src/Gui/ExpressionCompleter.cpp b/src/Gui/ExpressionCompleter.cpp index ba0267bce9..8de8c6cae2 100644 --- a/src/Gui/ExpressionCompleter.cpp +++ b/src/Gui/ExpressionCompleter.cpp @@ -18,7 +18,7 @@ #include #include #include "ExpressionCompleter.h" -#include +#include #include FC_LOG_LEVEL_INIT("Completer",true,true) diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index 2df0ffde51..a88ec371b3 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "ExpressionCompleter.h" #include "Command.h" diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index 06ac949878..825d9d3fb0 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index a0c0acecab..0a0470cda0 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -35,7 +35,7 @@ #include "DlgExpressionInput.h" #include "Command.h" #include -#include +#include #include #include "QuantitySpinBox_p.h" #include diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 0ae0be28a2..0326aeaa8f 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include "Command.h" #include "Widgets.h" diff --git a/src/Mod/Sketcher/App/PropertyConstraintList.cpp b/src/Mod/Sketcher/App/PropertyConstraintList.cpp index 0061b28744..9706a650a9 100644 --- a/src/Mod/Sketcher/App/PropertyConstraintList.cpp +++ b/src/Mod/Sketcher/App/PropertyConstraintList.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include "PropertyConstraintList.h" #include "ConstraintPy.h" diff --git a/src/Mod/Spreadsheet/App/Cell.cpp b/src/Mod/Spreadsheet/App/Cell.cpp index 500b01a5c2..c3e1e6c543 100644 --- a/src/Mod/Spreadsheet/App/Cell.cpp +++ b/src/Mod/Spreadsheet/App/Cell.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "Sheet.h" #include diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index ac3c6afe62..4ae6d4d09d 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -43,6 +43,7 @@ #include "Utils.h" #include #include +#include FC_LOG_LEVEL_INIT("Spreadsheet", true, true) using namespace App; diff --git a/src/Mod/Spreadsheet/App/Sheet.cpp b/src/Mod/Spreadsheet/App/Sheet.cpp index 355071e918..5cda74acf0 100644 --- a/src/Mod/Spreadsheet/App/Sheet.cpp +++ b/src/Mod/Spreadsheet/App/Sheet.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp b/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp index 9006004304..9db4623ae3 100644 --- a/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp +++ b/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "ui_PropertiesDialog.h"