diff --git a/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp b/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp index 6c2d12434..a8bdd4ff2 100644 --- a/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp +++ b/src/Mod/Spreadsheet/App/AppSpreadsheet.cpp @@ -37,15 +37,7 @@ void SpreadsheetExport initSpreadsheet() { Spreadsheet::PropertySheet::init(); Spreadsheet::Sheet::init(); - Spreadsheet::Expression::init(); - Spreadsheet::UnitExpression::init(); - Spreadsheet::NumberExpression::init(); - Spreadsheet::ConstantExpression::init(); - Spreadsheet::FunctionExpression::init(); - Spreadsheet::OperatorExpression::init(); - Spreadsheet::VariableExpression::init(); - Spreadsheet::ConditionalExpression::init(); - Spreadsheet::StringExpression::init(); + Spreadsheet::AggregateFunctionExpression::init(); Spreadsheet::RangeExpression::init(); return; diff --git a/src/Mod/Spreadsheet/App/Cell.cpp b/src/Mod/Spreadsheet/App/Cell.cpp index 65b1474fb..62f2dfbab 100644 --- a/src/Mod/Spreadsheet/App/Cell.cpp +++ b/src/Mod/Spreadsheet/App/Cell.cpp @@ -147,7 +147,7 @@ Cell::~Cell() * */ -void Cell::setExpression(Expression *expr) +void Cell::setExpression(App::Expression *expr) { PropertySheet::Signaller signaller(*owner); @@ -170,7 +170,7 @@ void Cell::setExpression(Expression *expr) * */ -const Expression *Cell::getExpression() const +const App::Expression *Cell::getExpression() const { return expression; } @@ -183,8 +183,8 @@ const Expression *Cell::getExpression() const bool Cell::getStringContent(std::string & s) const { if (expression) { - if (freecad_dynamic_cast(expression)) { - s = static_cast(expression)->getText(); + if (freecad_dynamic_cast(expression)) { + s = static_cast(expression)->getText(); char * end; errno = 0; double d = strtod(s.c_str(), &end); @@ -192,9 +192,9 @@ bool Cell::getStringContent(std::string & s) const if (!*end && errno == 0) s = "'" + s; } - else if (freecad_dynamic_cast(expression)) + else if (freecad_dynamic_cast(expression)) s = "=" + expression->toString(); - else if (freecad_dynamic_cast(expression)) + else if (freecad_dynamic_cast(expression)) s = expression->toString(); else s = "=" + expression->toString(); @@ -210,28 +210,28 @@ bool Cell::getStringContent(std::string & s) const void Cell::setContent(const char * value) { PropertySheet::Signaller signaller(*owner); - Expression * expr = 0; + App::Expression * expr = 0; setUsed(PARSE_EXCEPTION_SET, false); if (value != 0) { if (*value == '=') { try { - expr = ExpressionParser::parse(owner->sheet(), value + 1); + expr = Spreadsheet::ExpressionParser::parse(owner->sheet(), value + 1); } catch (Base::Exception & e) { QString msg = QString::fromUtf8("ERR: %1").arg(QString::fromUtf8(e.what())); - expr = new StringExpression(owner->sheet(), value); + expr = new App::StringExpression(owner->sheet(), value); setUsed(PARSE_EXCEPTION_SET); } } else if (*value == '\'') - expr = new StringExpression(owner->sheet(), value + 1); + expr = new App::StringExpression(owner->sheet(), value + 1); else if (*value != '\0') { char * end; errno = 0; double float_value = strtod(value, &end); if (!*end && errno == 0) - expr = new NumberExpression(owner->sheet(), float_value); + expr = new App::NumberExpression(owner->sheet(), float_value); else { try { expr = ExpressionParser::parse(owner->sheet(), value); @@ -239,7 +239,7 @@ void Cell::setContent(const char * value) delete expr->eval(); } catch (Base::Exception &) { - expr = new StringExpression(owner->sheet(), value); + expr = new App::StringExpression(owner->sheet(), value); } } } @@ -365,7 +365,7 @@ void Cell::setDisplayUnit(const std::string &unit) { DisplayUnit newDisplayUnit; if (unit.size() > 0) { - std::auto_ptr e(ExpressionParser::parseUnit(owner->sheet(), unit.c_str())); + std::auto_ptr e(ExpressionParser::parseUnit(owner->sheet(), unit.c_str())); newDisplayUnit = DisplayUnit(unit, e->getUnit(), e->getScaler()); } @@ -673,7 +673,7 @@ bool Cell::isUsed() const return used != 0; } -void Cell::visit(ExpressionVisitor &v) +void Cell::visit(App::ExpressionVisitor &v) { if (expression) expression->visit(v); diff --git a/src/Mod/Spreadsheet/App/Cell.h b/src/Mod/Spreadsheet/App/Cell.h index 1ce6eeefb..c620370b2 100644 --- a/src/Mod/Spreadsheet/App/Cell.h +++ b/src/Mod/Spreadsheet/App/Cell.h @@ -35,12 +35,15 @@ class XMLReader; class Writer; } +namespace App { +class Expression; +class ExpressionVisitor; +} + namespace Spreadsheet { class PropertySheet; -class Expression; class DisplayUnit; -class ExpressionVisitor; class SpreadsheetExport Cell { @@ -54,7 +57,7 @@ public: ~Cell(); - const Expression * getExpression() const; + const App::Expression * getExpression() const; bool getStringContent(std::string & s) const; @@ -114,7 +117,7 @@ public: bool spansChanged() const { return isUsed(SPANS_UPDATED); } - void visit(ExpressionVisitor & v); + void visit(App::ExpressionVisitor & v); CellAddress getAddress() const { return address; } @@ -143,7 +146,7 @@ private: //void setExpression(const Expression * expr); - void setExpression(Expression *expr); + void setExpression(App::Expression *expr); void setUsed(int mask, bool state = true); @@ -173,7 +176,7 @@ private: PropertySheet * owner; int used; - Expression * expression; + App::Expression * expression; int alignment; std::set style; App::Color foregroundColor; diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.l b/src/Mod/Spreadsheet/App/ExpressionParser.l index 8611f67fa..1a9cfcafd 100644 --- a/src/Mod/Spreadsheet/App/ExpressionParser.l +++ b/src/Mod/Spreadsheet/App/ExpressionParser.l @@ -12,7 +12,7 @@ #define strdup _strdup #endif -extern std::stack functions; /**< Function identifier */ +extern std::stack functions; /**< Function identifier */ %} @@ -239,9 +239,9 @@ EXPO [eE][-+]?[0-9]+ "rad" yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = yytext; return UNIT; // radian "gon" yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = yytext; return UNIT; // gon -{DIGIT}*"."{DIGIT}+{EXPO}? yylval.fvalue = num_change(yytext,'.',','); return NUM; -{DIGIT}*","{DIGIT}+{EXPO}? yylval.fvalue = num_change(yytext,',','.'); return NUM; -{DIGIT}+ yylval.ivalue = strtoll( yytext, NULL, 0 ); return INTEGER; +{DIGIT}*"."{DIGIT}+{EXPO}? yylval.fvalue = num_change(yytext,'.',','); return yylval.fvalue == 1 ? ONE : NUM; +{DIGIT}*","{DIGIT}+{EXPO}? yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; +{DIGIT}+ yylval.ivalue = strtoll( yytext, NULL, 0 ); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; "pi" yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi "e" yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e @@ -256,7 +256,7 @@ $[A-Za-z]{1,2}{DIGIT}+ yylval.string = yytext; return CELLADDRESS; while (isspace(s[i])) --i; s.erase(i + 1); - std::map::const_iterator j = registered_functions.find(s); + std::map::const_iterator j = registered_functions.find(s); if (j != registered_functions.end()) yylval.func = j->second; else diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.tab.c b/src/Mod/Spreadsheet/App/ExpressionParser.tab.c index 68f5f3acf..afe5387d8 100644 --- a/src/Mod/Spreadsheet/App/ExpressionParser.tab.c +++ b/src/Mod/Spreadsheet/App/ExpressionParser.tab.c @@ -69,29 +69,7 @@ #line 7 "ExpressionParser.y" -class semantic_type { -public: - struct { - Quantity scaler; - std::string unitStr; - } quantity; - Expression * expr; - Path path; - std::deque components; - int ivalue; - double fvalue; - struct { - std::string name; - double fvalue; - } constant; - std::vector arguments; - std::string string; - FunctionExpression::Function func; - Path::String string_or_identifier; - semantic_type() {} -}; - -#define YYSTYPE semantic_type +#define YYSTYPE App::ExpressionParser::semantic_type std::stack functions; /**< Function identifier */ @@ -101,7 +79,7 @@ std::stack functions; /**< Function /* Line 268 of yacc.c */ -#line 105 "ExpressionParser.tab.c" +#line 83 "ExpressionParser.tab.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -129,26 +107,27 @@ std::stack functions; /**< Function know about them. */ enum yytokentype { FUNC = 258, - NUM = 259, - IDENTIFIER = 260, - UNIT = 261, - INTEGER = 262, - CONSTANT = 263, - CELLADDRESS = 264, - EQ = 265, - NEQ = 266, - LT = 267, - GT = 268, - GTE = 269, - LTE = 270, - STRING = 271, - MINUSSIGN = 272, - PROPERTY_REF = 273, - DOCUMENT = 274, - OBJECT = 275, - EXPONENT = 276, - NEG = 277, - POS = 278 + ONE = 259, + NUM = 260, + IDENTIFIER = 261, + UNIT = 262, + INTEGER = 263, + CONSTANT = 264, + CELLADDRESS = 265, + EQ = 266, + NEQ = 267, + LT = 268, + GT = 269, + GTE = 270, + LTE = 271, + STRING = 272, + MINUSSIGN = 273, + PROPERTY_REF = 274, + DOCUMENT = 275, + OBJECT = 276, + EXPONENT = 277, + NEG = 278, + POS = 279 }; #endif @@ -165,7 +144,7 @@ std::stack functions; /**< Function /* Line 343 of yacc.c */ -#line 169 "ExpressionParser.tab.c" +#line 148 "ExpressionParser.tab.c" #ifdef short # undef short @@ -382,22 +361,22 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 37 +#define YYFINAL 40 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 186 +#define YYLAST 214 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 38 +#define YYNTOKENS 39 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 12 +#define YYNNTS 15 /* YYNRULES -- Number of rules. */ -#define YYNRULES 59 +#define YYNRULES 74 /* YYNRULES -- Number of states. */ -#define YYNSTATES 107 +#define YYNSTATES 134 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 278 +#define YYMAXUTOK 279 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -408,13 +387,13 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 35, 2, 2, 2, 2, - 30, 31, 23, 22, 32, 2, 34, 24, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 26, 33, - 2, 2, 2, 25, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 36, 2, 2, 2, 2, + 31, 32, 24, 23, 33, 2, 35, 25, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 27, 34, + 2, 2, 2, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 36, 2, 37, 29, 2, 2, 2, 2, 2, + 2, 37, 2, 38, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -432,57 +411,67 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 27, 28 + 15, 16, 17, 18, 19, 20, 21, 22, 28, 29 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ -static const yytype_uint8 yyprhs[] = +static const yytype_uint16 yyprhs[] = { 0, 0, 3, 5, 7, 9, 11, 13, 16, 19, 23, 27, 31, 35, 39, 43, 47, 51, 57, 59, - 61, 63, 66, 69, 72, 74, 76, 80, 84, 88, - 92, 96, 100, 104, 108, 112, 116, 120, 124, 126, - 130, 134, 138, 142, 144, 148, 152, 158, 160, 162, - 167, 174, 179, 184, 191, 198, 202, 204, 206, 208 + 61, 63, 65, 67, 70, 73, 75, 77, 81, 85, + 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, + 127, 131, 135, 139, 143, 148, 152, 154, 158, 162, + 168, 170, 172, 174, 176, 181, 188, 193, 198, 205, + 212, 216, 218, 220, 222, 227, 234, 239, 244, 251, + 258, 262, 264, 266, 268 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 39, 0, -1, 40, -1, 45, -1, 41, -1, 16, - -1, 46, -1, 17, 40, -1, 22, 40, -1, 40, - 22, 40, -1, 40, 17, 40, -1, 40, 23, 40, - -1, 40, 24, 40, -1, 40, 24, 45, -1, 40, - 29, 40, -1, 30, 40, 31, -1, 3, 42, 31, - -1, 44, 25, 40, 26, 40, -1, 4, -1, 7, - -1, 8, -1, 4, 45, -1, 7, 45, -1, 8, - 45, -1, 40, -1, 43, -1, 42, 32, 40, -1, - 42, 33, 40, -1, 9, 26, 9, -1, 9, 26, - 5, -1, 5, 26, 9, -1, 5, 26, 5, -1, - 40, 10, 40, -1, 40, 11, 40, -1, 40, 12, - 40, -1, 40, 13, 40, -1, 40, 14, 40, -1, - 40, 15, 40, -1, 6, -1, 45, 24, 45, -1, - 45, 23, 45, -1, 45, 29, 40, -1, 30, 45, - 31, -1, 47, -1, 49, 34, 47, -1, 48, 35, - 47, -1, 48, 35, 49, 34, 47, -1, 5, -1, - 9, -1, 5, 36, 7, 37, -1, 5, 36, 7, - 37, 34, 47, -1, 5, 36, 16, 37, -1, 5, - 36, 5, 37, -1, 5, 36, 16, 37, 34, 47, - -1, 5, 36, 5, 37, 34, 47, -1, 5, 34, - 47, -1, 16, -1, 5, -1, 16, -1, 9, -1 + 40, 0, -1, 41, -1, 47, -1, 43, -1, 17, + -1, 48, -1, 18, 41, -1, 23, 41, -1, 41, + 23, 41, -1, 41, 18, 41, -1, 41, 24, 41, + -1, 41, 25, 41, -1, 41, 25, 47, -1, 41, + 30, 41, -1, 31, 41, 32, -1, 3, 44, 32, + -1, 46, 26, 41, 27, 41, -1, 4, -1, 5, + -1, 8, -1, 42, -1, 9, -1, 42, 47, -1, + 9, 47, -1, 41, -1, 45, -1, 44, 33, 41, + -1, 44, 34, 41, -1, 10, 27, 10, -1, 10, + 27, 6, -1, 6, 27, 10, -1, 6, 27, 6, + -1, 41, 11, 41, -1, 41, 12, 41, -1, 41, + 13, 41, -1, 41, 14, 41, -1, 41, 15, 41, + -1, 41, 16, 41, -1, 7, -1, 4, 25, 47, + -1, 47, 25, 47, -1, 47, 24, 47, -1, 47, + 30, 42, -1, 47, 30, 18, 42, -1, 31, 47, + 32, -1, 50, -1, 53, 35, 50, -1, 52, 36, + 50, -1, 52, 36, 53, 35, 50, -1, 8, -1, + 4, -1, 6, -1, 10, -1, 6, 37, 49, 38, + -1, 6, 37, 49, 38, 35, 51, -1, 6, 37, + 17, 38, -1, 6, 37, 6, 38, -1, 6, 37, + 17, 38, 35, 51, -1, 6, 37, 6, 38, 35, + 51, -1, 6, 35, 51, -1, 6, -1, 17, -1, + 10, -1, 6, 37, 49, 38, -1, 6, 37, 49, + 38, 35, 51, -1, 6, 37, 17, 38, -1, 6, + 37, 6, 38, -1, 6, 37, 17, 38, 35, 51, + -1, 6, 37, 6, 38, 35, 51, -1, 6, 35, + 51, -1, 17, -1, 6, -1, 17, -1, 10, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 85, 85, 86, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 105, 106, - 107, 108, 109, 110, 113, 114, 115, 116, 119, 120, - 121, 122, 125, 126, 127, 128, 129, 130, 133, 134, - 135, 136, 137, 140, 144, 149, 154, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 173, 174, 177, 178 + 0, 68, 68, 69, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 88, 89, + 90, 93, 94, 95, 96, 99, 100, 101, 102, 105, + 106, 107, 108, 111, 112, 113, 114, 115, 116, 119, + 120, 121, 122, 123, 124, 125, 128, 132, 137, 142, + 150, 151, 155, 156, 157, 158, 159, 160, 161, 162, + 163, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 178, 179, 182, 183 }; #endif @@ -491,13 +480,13 @@ static const yytype_uint8 yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "FUNC", "NUM", "IDENTIFIER", "UNIT", - "INTEGER", "CONSTANT", "CELLADDRESS", "EQ", "NEQ", "LT", "GT", "GTE", - "LTE", "STRING", "MINUSSIGN", "PROPERTY_REF", "DOCUMENT", "OBJECT", - "EXPONENT", "'+'", "'*'", "'/'", "'?'", "':'", "NEG", "POS", "'^'", - "'('", "')'", "','", "';'", "'.'", "'#'", "'['", "']'", "$accept", - "input", "exp", "num", "args", "range", "cond", "unit_exp", "identifier", - "path", "document", "object", 0 + "$end", "error", "$undefined", "FUNC", "ONE", "NUM", "IDENTIFIER", + "UNIT", "INTEGER", "CONSTANT", "CELLADDRESS", "EQ", "NEQ", "LT", "GT", + "GTE", "LTE", "STRING", "MINUSSIGN", "PROPERTY_REF", "DOCUMENT", + "OBJECT", "EXPONENT", "'+'", "'*'", "'/'", "'?'", "':'", "NEG", "POS", + "'^'", "'('", "')'", "','", "';'", "'.'", "'#'", "'['", "']'", "$accept", + "input", "exp", "basic_num", "num", "args", "range", "cond", "unit_exp", + "identifier", "integer", "path", "subpath", "document", "object", 0 }; #endif @@ -508,20 +497,22 @@ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 43, 42, 47, 63, 58, 277, 278, 94, - 40, 41, 44, 59, 46, 35, 91, 93 + 275, 276, 277, 43, 42, 47, 63, 58, 278, 279, + 94, 40, 41, 44, 59, 46, 35, 91, 93 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 38, 39, 39, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, - 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, - 43, 43, 44, 44, 44, 44, 44, 44, 45, 45, - 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 48, 48, 49, 49 + 0, 39, 40, 40, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, + 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, + 45, 45, 45, 46, 46, 46, 46, 46, 46, 47, + 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, + 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 52, 52, 53, 53 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -529,10 +520,12 @@ static const yytype_uint8 yyr2[] = { 0, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 1, 1, - 1, 2, 2, 2, 1, 1, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, - 3, 3, 3, 1, 3, 3, 5, 1, 1, 4, - 6, 4, 4, 6, 6, 3, 1, 1, 1, 1 + 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 3, 3, 3, 3, 4, 3, 1, 3, 3, 5, + 1, 1, 1, 1, 4, 6, 4, 4, 6, 6, + 3, 1, 1, 1, 4, 6, 4, 4, 6, 6, + 3, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. @@ -540,122 +533,137 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 18, 47, 38, 19, 20, 48, 5, 0, - 0, 0, 0, 2, 4, 0, 3, 6, 43, 0, - 0, 47, 48, 0, 24, 0, 25, 0, 21, 0, - 0, 22, 23, 7, 8, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, - 47, 48, 55, 0, 0, 0, 15, 42, 32, 33, - 34, 35, 36, 37, 10, 9, 11, 12, 13, 14, - 0, 40, 39, 41, 58, 45, 0, 44, 31, 30, - 29, 28, 26, 27, 52, 49, 51, 0, 0, 0, - 0, 0, 17, 46, 54, 50, 53 + 0, 0, 18, 19, 52, 39, 20, 22, 53, 5, + 0, 0, 0, 0, 2, 21, 4, 0, 3, 6, + 46, 0, 0, 18, 52, 53, 0, 25, 0, 26, + 0, 0, 0, 0, 0, 24, 7, 8, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 40, 61, 63, 62, 60, 51, + 0, 50, 0, 0, 15, 45, 33, 34, 35, 36, + 37, 38, 10, 9, 11, 12, 13, 14, 0, 42, + 41, 0, 43, 52, 73, 48, 0, 53, 47, 32, + 31, 30, 29, 27, 28, 0, 0, 57, 56, 54, + 0, 44, 0, 70, 0, 0, 0, 0, 0, 0, + 17, 49, 67, 66, 64, 59, 58, 55, 0, 0, + 0, 69, 68, 65 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 12, 35, 14, 25, 26, 15, 36, 17, 18, - 19, 20 + -1, 13, 38, 15, 16, 28, 29, 17, 39, 19, + 73, 20, 68, 21, 22 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -32 +#define YYPACT_NINF -100 static const yytype_int16 yypact[] = { - 59, 79, -2, 57, -32, -2, -2, -31, 115, 95, - 95, 59, 15, 131, -32, -18, 105, -32, -32, -12, - 26, 43, -21, 95, 131, 104, -32, -2, -32, 46, - 9, 105, 105, 3, 3, 109, 84, -32, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 59, 95, 95, - -2, -2, 95, 45, 46, 85, 101, -32, 95, 95, - 1, -32, -32, -3, 33, 48, -32, -32, 131, 131, - 131, 131, 131, 131, 151, 151, 157, 157, 51, -32, - 7, 51, 51, -32, -32, -32, 71, -32, -32, -32, - -32, -32, 131, 131, 80, 82, 93, 95, 46, 46, - 46, 46, 3, -32, -32, -32, -32 + 61, 77, -18, -100, 92, -100, -100, 8, -12, -22, + 108, 108, 61, 27, 164, 8, -100, 7, 30, -100, + -100, 38, 1, -100, 62, -19, 108, 164, 169, -100, + 8, 155, 20, -18, 8, 30, 58, 58, 122, 118, + -100, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 61, 108, -100, 108, 8, 8, 17, 175, 28, 143, + 160, -100, 108, 108, 60, 24, -100, -100, -100, -100, + 53, -100, 55, 69, -100, -100, 164, 164, 164, 164, + 164, 164, 184, 184, 90, 90, 60, -100, 144, 60, + 60, 68, -100, 40, -100, -100, 74, -100, -100, -100, + -100, -100, -100, 164, 164, 155, 115, 80, 87, 89, + 108, -100, 28, -100, 103, 106, 113, 155, 155, 155, + 58, -100, 95, 128, 129, -100, -100, -100, 155, 155, + 155, -100, -100, -100 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -32, -32, 0, -32, -32, -32, -32, 6, -32, -27, - -32, 65 + -100, -100, 0, -51, -100, -100, -100, -100, 2, -100, + -10, -54, -99, -100, 116 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -60 -static const yytype_int8 yytable[] = +#define YYTABLE_NINF -75 +static const yytype_int16 yytable[] = { - 13, 24, 62, -59, 4, 56, 16, 49, 28, 33, - 34, 31, 32, -59, 63, 37, 64, 38, 39, 40, - 41, 42, 43, 53, 44, 65, 85, 87, 27, 45, - 46, 47, 48, 97, 94, 29, 48, 30, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, - 60, 60, 83, 78, 7, 61, 81, 82, 92, 93, - 54, 84, 1, 2, 3, 4, 5, 6, 7, 55, - 95, 103, 104, 105, 106, 8, 9, 29, -57, 30, - 52, 10, 1, 2, 21, 96, 5, 6, 22, 11, - 88, 29, -57, 30, 89, 8, 9, 102, 1, 2, - 3, 10, 5, 6, 7, 98, 90, 50, 51, 23, - 91, 8, 9, 52, 99, 67, 100, 10, 86, 38, - 39, 40, 41, 42, 43, 23, 44, 101, 50, 51, - 0, 45, 46, 47, 52, 57, 58, 59, 48, 0, - 66, 38, 39, 40, 41, 42, 43, 0, 44, -58, - -56, 0, 0, 45, 46, 47, 0, 0, 0, 0, - 48, 38, 39, 40, 41, 42, 43, 38, 39, 40, - 41, 42, 43, 0, 46, 47, 0, 0, 0, 0, - 48, 0, 0, 0, 0, 0, 48 + 14, 27, 18, 95, 98, 92, 113, 30, 60, 35, + 36, 37, 33, -73, -71, 5, -74, 52, 125, 126, + 127, 23, 3, -74, 69, 6, 70, 40, 71, 131, + 132, 133, 64, 53, 93, 91, 58, 72, 97, 34, + 111, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 87, 86, 88, 54, 55, 89, 90, 121, 105, + 56, 106, 103, 104, 1, 2, 3, 4, 5, 6, + 7, 8, 23, 3, 57, 31, 6, 32, 9, 10, + 1, 23, 3, 24, 11, 6, 7, 25, 51, 59, + 56, 107, 12, 108, 9, 10, 116, 31, -72, 32, + 11, 41, 42, 43, 44, 45, 46, 109, 26, 112, + 120, 1, 23, 3, 4, 117, 6, 7, 8, 69, + 51, 114, 118, 71, 119, 9, 10, 31, -72, 32, + 128, 11, 115, 41, 42, 43, 44, 45, 46, 26, + 47, 122, 54, 55, 123, 48, 49, 50, 56, 99, + 75, 124, 51, 100, 74, 41, 42, 43, 44, 45, + 46, 65, 47, 129, 130, 66, 101, 48, 49, 50, + 102, 110, 67, 96, 51, 41, 42, 43, 44, 45, + 46, 93, 47, 0, 0, 8, 0, 48, 49, 50, + 0, 0, 94, 0, 51, 41, 42, 43, 44, 45, + 46, 61, 62, 63, 0, 0, 0, 0, 49, 50, + 0, 0, 0, 0, 51 }; #define yypact_value_is_default(yystate) \ - ((yystate) == (-32)) + ((yystate) == (-100)) #define yytable_value_is_error(yytable_value) \ YYID (0) -static const yytype_int8 yycheck[] = +static const yytype_int16 yycheck[] = { - 0, 1, 29, 34, 6, 26, 0, 25, 2, 9, - 10, 5, 6, 34, 5, 0, 7, 10, 11, 12, - 13, 14, 15, 35, 17, 16, 53, 54, 30, 22, - 23, 24, 29, 26, 37, 34, 29, 36, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 5, 5, 52, 47, 9, 9, 50, 51, 58, 59, - 34, 16, 3, 4, 5, 6, 7, 8, 9, 26, - 37, 98, 99, 100, 101, 16, 17, 34, 35, 36, - 29, 22, 3, 4, 5, 37, 7, 8, 9, 30, - 5, 34, 35, 36, 9, 16, 17, 97, 3, 4, - 5, 22, 7, 8, 9, 34, 5, 23, 24, 30, - 9, 16, 17, 29, 34, 31, 34, 22, 53, 10, - 11, 12, 13, 14, 15, 30, 17, 34, 23, 24, - -1, 22, 23, 24, 29, 31, 32, 33, 29, -1, - 31, 10, 11, 12, 13, 14, 15, -1, 17, 34, - 35, -1, -1, 22, 23, 24, -1, -1, -1, -1, - 29, 10, 11, 12, 13, 14, 15, 10, 11, 12, - 13, 14, 15, -1, 23, 24, -1, -1, -1, -1, - 29, -1, -1, -1, -1, -1, 29 + 0, 1, 0, 57, 58, 56, 105, 25, 27, 7, + 10, 11, 4, 35, 36, 7, 35, 15, 117, 118, + 119, 4, 5, 35, 4, 8, 6, 0, 8, 128, + 129, 130, 30, 26, 6, 18, 35, 17, 10, 31, + 91, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 50, 53, 24, 25, 54, 55, 112, 35, + 30, 37, 62, 63, 3, 4, 5, 6, 7, 8, + 9, 10, 4, 5, 36, 35, 8, 37, 17, 18, + 3, 4, 5, 6, 23, 8, 9, 10, 30, 27, + 30, 38, 31, 38, 17, 18, 106, 35, 36, 37, + 23, 11, 12, 13, 14, 15, 16, 38, 31, 35, + 110, 3, 4, 5, 6, 35, 8, 9, 10, 4, + 30, 6, 35, 8, 35, 17, 18, 35, 36, 37, + 35, 23, 17, 11, 12, 13, 14, 15, 16, 31, + 18, 38, 24, 25, 38, 23, 24, 25, 30, 6, + 32, 38, 30, 10, 32, 11, 12, 13, 14, 15, + 16, 6, 18, 35, 35, 10, 6, 23, 24, 25, + 10, 27, 17, 57, 30, 11, 12, 13, 14, 15, + 16, 6, 18, -1, -1, 10, -1, 23, 24, 25, + -1, -1, 17, -1, 30, 11, 12, 13, 14, 15, + 16, 32, 33, 34, -1, -1, -1, -1, 24, 25, + -1, -1, -1, -1, 30 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 4, 5, 6, 7, 8, 9, 16, 17, - 22, 30, 39, 40, 41, 44, 45, 46, 47, 48, - 49, 5, 9, 30, 40, 42, 43, 30, 45, 34, - 36, 45, 45, 40, 40, 40, 45, 0, 10, 11, - 12, 13, 14, 15, 17, 22, 23, 24, 29, 25, - 23, 24, 29, 35, 34, 26, 26, 31, 32, 33, - 5, 9, 47, 5, 7, 16, 31, 31, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 45, 40, - 40, 45, 45, 40, 16, 47, 49, 47, 5, 9, - 5, 9, 40, 40, 37, 37, 37, 26, 34, 34, - 34, 34, 40, 47, 47, 47, 47 + 0, 3, 4, 5, 6, 7, 8, 9, 10, 17, + 18, 23, 31, 40, 41, 42, 43, 46, 47, 48, + 50, 52, 53, 4, 6, 10, 31, 41, 44, 45, + 25, 35, 37, 4, 31, 47, 41, 41, 41, 47, + 0, 11, 12, 13, 14, 15, 16, 18, 23, 24, + 25, 30, 47, 26, 24, 25, 30, 36, 35, 27, + 27, 32, 33, 34, 47, 6, 10, 17, 51, 4, + 6, 8, 17, 49, 32, 32, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 47, 41, 41, 47, + 47, 18, 42, 6, 17, 50, 53, 10, 50, 6, + 10, 6, 10, 41, 41, 35, 37, 38, 38, 38, + 27, 42, 35, 51, 6, 17, 49, 35, 35, 35, + 41, 50, 38, 38, 38, 51, 51, 51, 35, 35, + 35, 51, 51, 51 }; #define yyerrok (yyerrstatus = 0) @@ -1191,41 +1199,41 @@ yydestruct (yymsg, yytype, yyvaluep) switch (yytype) { - case 40: /* "exp" */ + case 41: /* "exp" */ /* Line 1391 of yacc.c */ -#line 78 "ExpressionParser.y" +#line 61 "ExpressionParser.y" { delete (yyvaluep->expr); }; /* Line 1391 of yacc.c */ -#line 1202 "ExpressionParser.tab.c" +#line 1210 "ExpressionParser.tab.c" break; - case 42: /* "args" */ + case 44: /* "args" */ /* Line 1391 of yacc.c */ -#line 79 "ExpressionParser.y" +#line 62 "ExpressionParser.y" { std::vector::const_iterator i = (yyvaluep->arguments).begin(); while (i != (yyvaluep->arguments).end()) { delete *i; ++i; } }; /* Line 1391 of yacc.c */ -#line 1211 "ExpressionParser.tab.c" +#line 1219 "ExpressionParser.tab.c" break; - case 44: /* "cond" */ + case 46: /* "cond" */ /* Line 1391 of yacc.c */ -#line 78 "ExpressionParser.y" +#line 61 "ExpressionParser.y" { delete (yyvaluep->expr); }; /* Line 1391 of yacc.c */ -#line 1220 "ExpressionParser.tab.c" +#line 1228 "ExpressionParser.tab.c" break; - case 45: /* "unit_exp" */ + case 47: /* "unit_exp" */ /* Line 1391 of yacc.c */ -#line 78 "ExpressionParser.y" +#line 61 "ExpressionParser.y" { delete (yyvaluep->expr); }; /* Line 1391 of yacc.c */ -#line 1229 "ExpressionParser.tab.c" +#line 1237 "ExpressionParser.tab.c" break; default: @@ -1528,429 +1536,534 @@ yyreduce: case 2: /* Line 1806 of yacc.c */ -#line 85 "ExpressionParser.y" +#line 68 "ExpressionParser.y" { ScanResult = (yyvsp[(1) - (1)].expr); valueExpression = true; } break; case 3: /* Line 1806 of yacc.c */ -#line 86 "ExpressionParser.y" +#line 69 "ExpressionParser.y" { ScanResult = (yyvsp[(1) - (1)].expr); unitExpression = true; } break; case 4: /* Line 1806 of yacc.c */ -#line 89 "ExpressionParser.y" +#line 72 "ExpressionParser.y" { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 5: /* Line 1806 of yacc.c */ -#line 90 "ExpressionParser.y" +#line 73 "ExpressionParser.y" { (yyval.expr) = new StringExpression(DocumentObject, (yyvsp[(1) - (1)].string)); } break; case 6: /* Line 1806 of yacc.c */ -#line 91 "ExpressionParser.y" +#line 74 "ExpressionParser.y" { (yyval.expr) = new VariableExpression(DocumentObject, (yyvsp[(1) - (1)].path)); } break; case 7: /* Line 1806 of yacc.c */ -#line 92 "ExpressionParser.y" +#line 75 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(2) - (2)].expr), OperatorExpression::NEG, new NumberExpression(DocumentObject, -1)); } break; case 8: /* Line 1806 of yacc.c */ -#line 93 "ExpressionParser.y" +#line 76 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(2) - (2)].expr), OperatorExpression::POS, new NumberExpression(DocumentObject, 1)); } break; case 9: /* Line 1806 of yacc.c */ -#line 94 "ExpressionParser.y" +#line 77 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::ADD, (yyvsp[(3) - (3)].expr)); } break; case 10: /* Line 1806 of yacc.c */ -#line 95 "ExpressionParser.y" +#line 78 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::SUB, (yyvsp[(3) - (3)].expr)); } break; case 11: /* Line 1806 of yacc.c */ -#line 96 "ExpressionParser.y" +#line 79 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::MUL, (yyvsp[(3) - (3)].expr)); } break; case 12: /* Line 1806 of yacc.c */ -#line 97 "ExpressionParser.y" +#line 80 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } break; case 13: /* Line 1806 of yacc.c */ -#line 98 "ExpressionParser.y" +#line 81 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } break; case 14: /* Line 1806 of yacc.c */ -#line 99 "ExpressionParser.y" +#line 82 "ExpressionParser.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::POW, (yyvsp[(3) - (3)].expr)); } break; case 15: /* Line 1806 of yacc.c */ -#line 100 "ExpressionParser.y" +#line 83 "ExpressionParser.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 16: /* Line 1806 of yacc.c */ -#line 101 "ExpressionParser.y" - { (yyval.expr) = new FunctionExpression(DocumentObject, (yyvsp[(1) - (3)].func), (yyvsp[(2) - (3)].arguments)); } +#line 84 "ExpressionParser.y" + { (yyval.expr) = new AggregateFunctionExpression(DocumentObject, (yyvsp[(1) - (3)].func), (yyvsp[(2) - (3)].arguments)); } break; case 17: /* Line 1806 of yacc.c */ -#line 102 "ExpressionParser.y" +#line 85 "ExpressionParser.y" { (yyval.expr) = new ConditionalExpression(DocumentObject, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); } break; case 18: /* Line 1806 of yacc.c */ -#line 105 "ExpressionParser.y" - { (yyval.expr) = new NumberExpression(DocumentObject, (yyvsp[(1) - (1)].fvalue)); } +#line 88 "ExpressionParser.y" + { (yyval.expr) = new NumberExpression(DocumentObject, (yyvsp[(1) - (1)].fvalue)); } break; case 19: /* Line 1806 of yacc.c */ -#line 106 "ExpressionParser.y" - { (yyval.expr) = new NumberExpression(DocumentObject, (double)(yyvsp[(1) - (1)].ivalue)); } +#line 89 "ExpressionParser.y" + { (yyval.expr) = new NumberExpression(DocumentObject, (yyvsp[(1) - (1)].fvalue)); } break; case 20: /* Line 1806 of yacc.c */ -#line 107 "ExpressionParser.y" - { (yyval.expr) = new ConstantExpression(DocumentObject, (yyvsp[(1) - (1)].constant).name, (yyvsp[(1) - (1)].constant).fvalue); } +#line 90 "ExpressionParser.y" + { (yyval.expr) = new NumberExpression(DocumentObject, (double)(yyvsp[(1) - (1)].ivalue)); } break; case 21: /* Line 1806 of yacc.c */ -#line 108 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (yyvsp[(1) - (2)].fvalue)), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } +#line 93 "ExpressionParser.y" + { (yyval.expr) = (yyvsp[(1) - (1)].expr); } break; case 22: /* Line 1806 of yacc.c */ -#line 109 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)(yyvsp[(1) - (2)].ivalue)), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } +#line 94 "ExpressionParser.y" + { (yyval.expr) = new ConstantExpression(DocumentObject, (yyvsp[(1) - (1)].constant).name, (yyvsp[(1) - (1)].constant).fvalue); } break; case 23: /* Line 1806 of yacc.c */ -#line 110 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, new ConstantExpression(DocumentObject, (yyvsp[(1) - (2)].constant).name, (yyvsp[(1) - (2)].constant).fvalue), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } +#line 95 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (2)].expr), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } break; case 24: /* Line 1806 of yacc.c */ -#line 113 "ExpressionParser.y" - { (yyval.arguments).push_back((yyvsp[(1) - (1)].expr)); } +#line 96 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, new ConstantExpression(DocumentObject, (yyvsp[(1) - (2)].constant).name, (yyvsp[(1) - (2)].constant).fvalue), OperatorExpression::UNIT, (yyvsp[(2) - (2)].expr)); } break; case 25: /* Line 1806 of yacc.c */ -#line 114 "ExpressionParser.y" +#line 99 "ExpressionParser.y" { (yyval.arguments).push_back((yyvsp[(1) - (1)].expr)); } break; case 26: /* Line 1806 of yacc.c */ -#line 115 "ExpressionParser.y" - { (yyvsp[(1) - (3)].arguments).push_back((yyvsp[(3) - (3)].expr)); (yyval.arguments) = (yyvsp[(1) - (3)].arguments); } +#line 100 "ExpressionParser.y" + { (yyval.arguments).push_back((yyvsp[(1) - (1)].expr)); } break; case 27: /* Line 1806 of yacc.c */ -#line 116 "ExpressionParser.y" +#line 101 "ExpressionParser.y" { (yyvsp[(1) - (3)].arguments).push_back((yyvsp[(3) - (3)].expr)); (yyval.arguments) = (yyvsp[(1) - (3)].arguments); } break; case 28: /* Line 1806 of yacc.c */ -#line 119 "ExpressionParser.y" - { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } +#line 102 "ExpressionParser.y" + { (yyvsp[(1) - (3)].arguments).push_back((yyvsp[(3) - (3)].expr)); (yyval.arguments) = (yyvsp[(1) - (3)].arguments); } break; case 29: /* Line 1806 of yacc.c */ -#line 120 "ExpressionParser.y" +#line 105 "ExpressionParser.y" { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } break; case 30: /* Line 1806 of yacc.c */ -#line 121 "ExpressionParser.y" +#line 106 "ExpressionParser.y" { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } break; case 31: /* Line 1806 of yacc.c */ -#line 122 "ExpressionParser.y" +#line 107 "ExpressionParser.y" { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } break; case 32: /* Line 1806 of yacc.c */ -#line 125 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::EQ, (yyvsp[(3) - (3)].expr)); } +#line 108 "ExpressionParser.y" + { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string)); } break; case 33: /* Line 1806 of yacc.c */ -#line 126 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::NEQ, (yyvsp[(3) - (3)].expr)); } +#line 111 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::EQ, (yyvsp[(3) - (3)].expr)); } break; case 34: /* Line 1806 of yacc.c */ -#line 127 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::LT, (yyvsp[(3) - (3)].expr)); } +#line 112 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::NEQ, (yyvsp[(3) - (3)].expr)); } break; case 35: /* Line 1806 of yacc.c */ -#line 128 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::GT, (yyvsp[(3) - (3)].expr)); } +#line 113 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::LT, (yyvsp[(3) - (3)].expr)); } break; case 36: /* Line 1806 of yacc.c */ -#line 129 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::GTE, (yyvsp[(3) - (3)].expr)); } +#line 114 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::GT, (yyvsp[(3) - (3)].expr)); } break; case 37: /* Line 1806 of yacc.c */ -#line 130 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::LTE, (yyvsp[(3) - (3)].expr)); } +#line 115 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::GTE, (yyvsp[(3) - (3)].expr)); } break; case 38: /* Line 1806 of yacc.c */ -#line 133 "ExpressionParser.y" - { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[(1) - (1)].quantity).scaler, (yyvsp[(1) - (1)].quantity).unitStr ); } +#line 116 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::LTE, (yyvsp[(3) - (3)].expr)); } break; case 39: /* Line 1806 of yacc.c */ -#line 134 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } +#line 119 "ExpressionParser.y" + { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[(1) - (1)].quantity).scaler, (yyvsp[(1) - (1)].quantity).unitStr ); } break; case 40: /* Line 1806 of yacc.c */ -#line 135 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::MUL, (yyvsp[(3) - (3)].expr)); } +#line 120 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (yyvsp[(1) - (3)].fvalue)), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } break; case 41: /* Line 1806 of yacc.c */ -#line 136 "ExpressionParser.y" - { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::POW, (yyvsp[(3) - (3)].expr)); } +#line 121 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::DIV, (yyvsp[(3) - (3)].expr)); } break; case 42: /* Line 1806 of yacc.c */ -#line 137 "ExpressionParser.y" - { (yyval.expr) = (yyvsp[(2) - (3)].expr); } +#line 122 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::MUL, (yyvsp[(3) - (3)].expr)); } break; case 43: /* Line 1806 of yacc.c */ -#line 140 "ExpressionParser.y" - { /* Path to property within document object */ - (yyval.path) = Path(DocumentObject); - (yyval.path).addComponents((yyvsp[(1) - (1)].components)); - } +#line 123 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (3)].expr), OperatorExpression::POW, (yyvsp[(3) - (3)].expr)); } break; case 44: /* Line 1806 of yacc.c */ -#line 144 "ExpressionParser.y" - { /* Path to property within document object */ - (yyval.path) = Path(DocumentObject); - (yyval.path).setDocumentObjectName((yyvsp[(1) - (3)].string_or_identifier), true); - (yyval.path).addComponents((yyvsp[(3) - (3)].components)); - } +#line 124 "ExpressionParser.y" + { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[(1) - (4)].expr), OperatorExpression::POW, new OperatorExpression(DocumentObject, (yyvsp[(4) - (4)].expr), OperatorExpression::NEG, new NumberExpression(DocumentObject, -1))); } break; case 45: /* Line 1806 of yacc.c */ -#line 149 "ExpressionParser.y" - { /* Path to property from an external document, within a named document object */ - (yyval.path) = Path(DocumentObject); - (yyval.path).setDocumentName((yyvsp[(1) - (3)].string_or_identifier), true); - (yyval.path).addComponents((yyvsp[(3) - (3)].components)); - } +#line 125 "ExpressionParser.y" + { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 46: /* Line 1806 of yacc.c */ -#line 154 "ExpressionParser.y" - { /* Path to property from an external document, within a named document object */ - (yyval.path) = Path(DocumentObject); - (yyval.path).setDocumentName((yyvsp[(1) - (5)].string_or_identifier), true); - (yyval.path).setDocumentObjectName((yyvsp[(3) - (5)].string_or_identifier), true); - (yyval.path).addComponents((yyvsp[(5) - (5)].components)); +#line 128 "ExpressionParser.y" + { /* Path to property within document object */ + (yyval.path) = ObjectIdentifier(DocumentObject); + (yyval.path).addComponents((yyvsp[(1) - (1)].components)); } break; case 47: /* Line 1806 of yacc.c */ -#line 162 "ExpressionParser.y" - { (yyval.components).push_front(Path::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } +#line 132 "ExpressionParser.y" + { /* Path to property within document object */ + (yyval.path) = ObjectIdentifier(DocumentObject); + (yyval.path).setDocumentObjectName((yyvsp[(1) - (3)].string_or_identifier), true); + (yyval.path).addComponents((yyvsp[(3) - (3)].components)); + } break; case 48: /* Line 1806 of yacc.c */ -#line 163 "ExpressionParser.y" - { (yyval.components).push_front(Path::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } +#line 137 "ExpressionParser.y" + { /* Path to property from an external document, within a named document object */ + (yyval.path) = ObjectIdentifier(DocumentObject); + (yyval.path).setDocumentName((yyvsp[(1) - (3)].string_or_identifier), true); + (yyval.path).addComponents((yyvsp[(3) - (3)].components)); + } break; case 49: /* Line 1806 of yacc.c */ -#line 164 "ExpressionParser.y" - { (yyval.components).push_front(Path::Component::ArrayComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].ivalue))); } +#line 142 "ExpressionParser.y" + { /* Path to property from an external document, within a named document object */ + (yyval.path) = ObjectIdentifier(DocumentObject); + (yyval.path).setDocumentName((yyvsp[(1) - (5)].string_or_identifier), true); + (yyval.path).setDocumentObjectName((yyvsp[(3) - (5)].string_or_identifier), true); + (yyval.path).addComponents((yyvsp[(5) - (5)].components)); + } break; case 50: /* Line 1806 of yacc.c */ -#line 165 "ExpressionParser.y" - { (yyvsp[(6) - (6)].components).push_front(Path::Component::ArrayComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].ivalue))); (yyval.components) = (yyvsp[(6) - (6)].components); } +#line 150 "ExpressionParser.y" + { (yyval.ivalue) = (yyvsp[(1) - (1)].ivalue); } break; case 51: /* Line 1806 of yacc.c */ -#line 166 "ExpressionParser.y" - { (yyval.components).push_front(Path::Component::MapComponent((yyvsp[(1) - (4)].string), Path::String((yyvsp[(3) - (4)].string), true))); } +#line 151 "ExpressionParser.y" + { (yyval.ivalue) = (yyvsp[(1) - (1)].fvalue); } break; case 52: /* Line 1806 of yacc.c */ -#line 167 "ExpressionParser.y" - { (yyval.components).push_front(Path::Component::MapComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].string))); } +#line 155 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } break; case 53: /* Line 1806 of yacc.c */ -#line 168 "ExpressionParser.y" - { (yyvsp[(6) - (6)].components).push_front(Path::Component::MapComponent((yyvsp[(1) - (6)].string), Path::String((yyvsp[(3) - (6)].string), true))); (yyval.components) = (yyvsp[(6) - (6)].components); } +#line 156 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } break; case 54: /* Line 1806 of yacc.c */ -#line 169 "ExpressionParser.y" - { (yyvsp[(6) - (6)].components).push_front(Path::Component::MapComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].string))); (yyval.components) = (yyvsp[(6) - (6)].components); } +#line 157 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::ArrayComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].ivalue))); } break; case 55: /* Line 1806 of yacc.c */ -#line 170 "ExpressionParser.y" - { (yyvsp[(3) - (3)].components).push_front(Path::Component::SimpleComponent((yyvsp[(1) - (3)].string))); (yyval.components) = (yyvsp[(3) - (3)].components); } +#line 158 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(ObjectIdentifier::Component::ArrayComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].ivalue))); (yyval.components) = (yyvsp[(6) - (6)].components); } break; case 56: /* Line 1806 of yacc.c */ -#line 173 "ExpressionParser.y" - { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string), true); } +#line 159 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (4)].string), ObjectIdentifier::String((yyvsp[(3) - (4)].string), true))); } break; case 57: /* Line 1806 of yacc.c */ -#line 174 "ExpressionParser.y" - { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string)); } +#line 160 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].string))); } break; case 58: /* Line 1806 of yacc.c */ -#line 177 "ExpressionParser.y" - { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string), true); } +#line 161 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (6)].string), ObjectIdentifier::String((yyvsp[(3) - (6)].string), true))); (yyval.components) = (yyvsp[(6) - (6)].components); } break; case 59: +/* Line 1806 of yacc.c */ +#line 162 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].string))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 60: + +/* Line 1806 of yacc.c */ +#line 163 "ExpressionParser.y" + { (yyvsp[(3) - (3)].components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (3)].string))); (yyval.components) = (yyvsp[(3) - (3)].components); } + break; + + case 61: + +/* Line 1806 of yacc.c */ +#line 166 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } + break; + + case 62: + +/* Line 1806 of yacc.c */ +#line 167 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } + break; + + case 63: + +/* Line 1806 of yacc.c */ +#line 168 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (1)].string))); } + break; + + case 64: + +/* Line 1806 of yacc.c */ +#line 169 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::ArrayComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].ivalue))); } + break; + + case 65: + +/* Line 1806 of yacc.c */ +#line 170 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(ObjectIdentifier::Component::ArrayComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].ivalue))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 66: + +/* Line 1806 of yacc.c */ +#line 171 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (4)].string), ObjectIdentifier::String((yyvsp[(3) - (4)].string), true))); } + break; + + case 67: + +/* Line 1806 of yacc.c */ +#line 172 "ExpressionParser.y" + { (yyval.components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].string))); } + break; + + case 68: + +/* Line 1806 of yacc.c */ +#line 173 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (6)].string), ObjectIdentifier::String((yyvsp[(3) - (6)].string), true))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 69: + +/* Line 1806 of yacc.c */ +#line 174 "ExpressionParser.y" + { (yyvsp[(6) - (6)].components).push_front(ObjectIdentifier::Component::MapComponent((yyvsp[(1) - (6)].string), (yyvsp[(3) - (6)].string))); (yyval.components) = (yyvsp[(6) - (6)].components); } + break; + + case 70: + +/* Line 1806 of yacc.c */ +#line 175 "ExpressionParser.y" + { (yyvsp[(3) - (3)].components).push_front(ObjectIdentifier::Component::SimpleComponent((yyvsp[(1) - (3)].string))); (yyval.components) = (yyvsp[(3) - (3)].components); } + break; + + case 71: + /* Line 1806 of yacc.c */ #line 178 "ExpressionParser.y" - { (yyval.string_or_identifier) = Path::String((yyvsp[(1) - (1)].string), true); } + { (yyval.string_or_identifier) = ObjectIdentifier::String((yyvsp[(1) - (1)].string), true); } + break; + + case 72: + +/* Line 1806 of yacc.c */ +#line 179 "ExpressionParser.y" + { (yyval.string_or_identifier) = ObjectIdentifier::String((yyvsp[(1) - (1)].string)); } + break; + + case 73: + +/* Line 1806 of yacc.c */ +#line 182 "ExpressionParser.y" + { (yyval.string_or_identifier) = ObjectIdentifier::String((yyvsp[(1) - (1)].string), true); } + break; + + case 74: + +/* Line 1806 of yacc.c */ +#line 183 "ExpressionParser.y" + { (yyval.string_or_identifier) = ObjectIdentifier::String((yyvsp[(1) - (1)].string), true); } break; /* Line 1806 of yacc.c */ -#line 1954 "ExpressionParser.tab.c" +#line 2067 "ExpressionParser.tab.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2181,6 +2294,6 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 181 "ExpressionParser.y" +#line 186 "ExpressionParser.y" diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.tab.h b/src/Mod/Spreadsheet/App/ExpressionParser.tab.h index f671e8df6..806b15850 100644 --- a/src/Mod/Spreadsheet/App/ExpressionParser.tab.h +++ b/src/Mod/Spreadsheet/App/ExpressionParser.tab.h @@ -38,26 +38,27 @@ know about them. */ enum yytokentype { FUNC = 258, - NUM = 259, - IDENTIFIER = 260, - UNIT = 261, - INTEGER = 262, - CONSTANT = 263, - CELLADDRESS = 264, - EQ = 265, - NEQ = 266, - LT = 267, - GT = 268, - GTE = 269, - LTE = 270, - STRING = 271, - MINUSSIGN = 272, - PROPERTY_REF = 273, - DOCUMENT = 274, - OBJECT = 275, - EXPONENT = 276, - NEG = 277, - POS = 278 + ONE = 259, + NUM = 260, + IDENTIFIER = 261, + UNIT = 262, + INTEGER = 263, + CONSTANT = 264, + CELLADDRESS = 265, + EQ = 266, + NEQ = 267, + LT = 268, + GT = 269, + GTE = 270, + LTE = 271, + STRING = 272, + MINUSSIGN = 273, + PROPERTY_REF = 274, + DOCUMENT = 275, + OBJECT = 276, + EXPONENT = 277, + NEG = 278, + POS = 279 }; #endif diff --git a/src/Mod/Spreadsheet/App/ExpressionParser.y b/src/Mod/Spreadsheet/App/ExpressionParser.y index 0ee702755..750a14101 100644 --- a/src/Mod/Spreadsheet/App/ExpressionParser.y +++ b/src/Mod/Spreadsheet/App/ExpressionParser.y @@ -6,29 +6,7 @@ %{ -class semantic_type { -public: - struct { - Quantity scaler; - std::string unitStr; - } quantity; - Expression * expr; - Path path; - std::deque components; - int ivalue; - double fvalue; - struct { - std::string name; - double fvalue; - } constant; - std::vector arguments; - std::string string; - FunctionExpression::Function func; - Path::String string_or_identifier; - semantic_type() {} -}; - -#define YYSTYPE semantic_type +#define YYSTYPE App::ExpressionParser::semantic_type std::stack functions; /**< Function identifier */ @@ -39,6 +17,7 @@ std::stack functions; /**< Function /* Bison declarations. */ %token FUNC + %token ONE %token NUM %token IDENTIFIER %token UNIT @@ -55,15 +34,19 @@ std::stack functions; /**< Function %type STRING IDENTIFIER CELLADDRESS %type INTEGER %type PROPERTY_REF + %type ONE %type NUM %type CONSTANT %type num + %type basic_num %type range %type identifier - %type path + %type path subpath %type FUNC %type document %type object + %type integer + %left ONE %left NUM %left INTEGER %left CONSTANT @@ -98,15 +81,18 @@ exp: num { $$ = $1; | exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } | exp '^' exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); } | '(' exp ')' { $$ = $2; } - | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); } + | FUNC args ')' { $$ = new AggregateFunctionExpression(DocumentObject, $1, $2); } | cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); } ; -num: NUM { $$ = new NumberExpression(DocumentObject, $1); } - | INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); } - | CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); } - | NUM unit_exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, $1), OperatorExpression::UNIT, $2); } - | INTEGER unit_exp { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)$1), OperatorExpression::UNIT, $2); } +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); } ; @@ -130,52 +116,71 @@ 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 ); } - | unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } - | unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } - | unit_exp '^' exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); } - | '(' unit_exp ')' { $$ = $2; } +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; } ; identifier: path { /* Path to property within document object */ - $$ = Path(DocumentObject); + $$ = ObjectIdentifier(DocumentObject); $$.addComponents($1); } | object '.' path { /* Path to property within document object */ - $$ = Path(DocumentObject); + $$ = ObjectIdentifier(DocumentObject); $$.setDocumentObjectName($1, true); $$.addComponents($3); } | document '#' path { /* Path to property from an external document, within a named document object */ - $$ = Path(DocumentObject); + $$ = ObjectIdentifier(DocumentObject); $$.setDocumentName($1, true); $$.addComponents($3); } | document '#' object '.' path { /* Path to property from an external document, within a named document object */ - $$ = Path(DocumentObject); + $$ = ObjectIdentifier(DocumentObject); $$.setDocumentName($1, true); $$.setDocumentObjectName($3, true); $$.addComponents($5); } ; -path: IDENTIFIER { $$.push_front(Path::Component::SimpleComponent($1)); } - | CELLADDRESS { $$.push_front(Path::Component::SimpleComponent($1)); } - | IDENTIFIER '[' INTEGER ']' { $$.push_front(Path::Component::ArrayComponent($1, $3)); } - | IDENTIFIER '[' INTEGER ']' '.' path { $6.push_front(Path::Component::ArrayComponent($1, $3)); $$ = $6; } - | IDENTIFIER '[' STRING ']' { $$.push_front(Path::Component::MapComponent($1, Path::String($3, true))); } - | IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(Path::Component::MapComponent($1, $3)); } - | IDENTIFIER '[' STRING ']' '.' path { $6.push_front(Path::Component::MapComponent($1, Path::String($3, true))); $$ = $6; } - | IDENTIFIER '[' IDENTIFIER ']' '.' path { $6.push_front(Path::Component::MapComponent($1, $3)); $$ = $6; } - | IDENTIFIER '.' path { $3.push_front(Path::Component::SimpleComponent($1)); $$ = $3; } +integer: INTEGER { $$ = $1; } + | ONE { $$ = $1; } + ; + + +path: IDENTIFIER { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); } + | CELLADDRESS { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); } + | IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); } + | IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); $$ = $6; } + | IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); } + | IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); } + | IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); $$ = $6; } + | IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); $$ = $6; } + | IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::Component::SimpleComponent($1)); $$ = $3; } ; -document: STRING { $$ = Path::String($1, true); } - | IDENTIFIER { $$ = Path::String($1); } +subpath: IDENTIFIER { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); } + | STRING { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); } + | CELLADDRESS { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); } + | IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); } + | IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); $$ = $6; } + | IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); } + | IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); } + | IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); $$ = $6; } + | IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); $$ = $6; } + | IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::Component::SimpleComponent($1)); $$ = $3; } + ; + +document: STRING { $$ = ObjectIdentifier::String($1, true); } + | IDENTIFIER { $$ = ObjectIdentifier::String($1); } ; -object: STRING { $$ = Path::String($1, true); } - | CELLADDRESS { $$ = Path::String($1, true); } +object: STRING { $$ = ObjectIdentifier::String($1, true); } + | CELLADDRESS { $$ = ObjectIdentifier::String($1, true); } ; %% diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index dc4f751b0..5056fa5f1 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -42,22 +42,12 @@ #include "Utils.h" #include +using namespace App; using namespace Base; using namespace Spreadsheet; namespace Spreadsheet { -class ResolveExpressionVisitor : public ExpressionVisitor { -public: - - void visit(Expression * node) { - VariableExpression *expr = freecad_dynamic_cast(node); - - if (expr) - expr->resolve(); - } -}; - class RelabelDocumentObjectExpressionVisitor : public ExpressionVisitor { public: @@ -872,16 +862,12 @@ void PropertySheet::addDependencies(CellAddress key) if (expression == 0) return; - std::set expressionDeps; - - // Resolve expression, if any - ResolveExpressionVisitor v; - cell->visit(v); + std::set expressionDeps; // Get dependencies from expression expression->getDeps(expressionDeps); - std::set::const_iterator i = expressionDeps.begin(); + std::set::const_iterator i = expressionDeps.begin(); while (i != expressionDeps.end()) { const Property * prop = i->getProperty(); const App::DocumentObject * docObj = i->getDocumentObject(); diff --git a/src/Mod/Spreadsheet/App/PropertySheet.h b/src/Mod/Spreadsheet/App/PropertySheet.h index 96e723bb9..1462bfac5 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.h +++ b/src/Mod/Spreadsheet/App/PropertySheet.h @@ -167,12 +167,12 @@ private: friend class Cell; - /*! Cell data in this property */ - std::map data; - /*! Set of cells that have been marked dirty */ std::set dirty; + /*! Cell data in this property */ + std::map data; + /*! Merged cells; cell -> anchor cell */ std::map mergedCells; diff --git a/src/Mod/Spreadsheet/App/Sheet.cpp b/src/Mod/Spreadsheet/App/Sheet.cpp index f16e03158..d8329d084 100644 --- a/src/Mod/Spreadsheet/App/Sheet.cpp +++ b/src/Mod/Spreadsheet/App/Sheet.cpp @@ -53,6 +53,7 @@ #include using namespace Base; +using namespace App; using namespace Spreadsheet; PROPERTY_SOURCE(Spreadsheet::Sheet, App::DocumentObject) @@ -75,21 +76,21 @@ typedef Traits::edge_descriptor Edge; */ Sheet::Sheet() - : App::DocumentObject() + : DocumentObject() , props(this) , cells(this) { - ADD_PROPERTY_TYPE(docDeps, (0), "Spreadsheet", (App::PropertyType)(App::Prop_Transient|App::Prop_ReadOnly|App::Prop_Hidden), "Dependencies"); - ADD_PROPERTY_TYPE(cells, (), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Cell contents"); - ADD_PROPERTY_TYPE(columnWidths, (), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Column widths"); - ADD_PROPERTY_TYPE(rowHeights, (), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Row heights"); - ADD_PROPERTY_TYPE(currRow, (0), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Current row"); - ADD_PROPERTY_TYPE(currColumn, (0), "Spreadsheet", (App::PropertyType)(App::Prop_ReadOnly|App::Prop_Hidden), "Current column"); + ADD_PROPERTY_TYPE(docDeps, (0), "Spreadsheet", (PropertyType)(Prop_Transient|Prop_ReadOnly|Prop_Hidden), "Dependencies"); + ADD_PROPERTY_TYPE(cells, (), "Spreadsheet", (PropertyType)(Prop_ReadOnly|Prop_Hidden), "Cell contents"); + ADD_PROPERTY_TYPE(columnWidths, (), "Spreadsheet", (PropertyType)(Prop_ReadOnly|Prop_Hidden), "Column widths"); + ADD_PROPERTY_TYPE(rowHeights, (), "Spreadsheet", (PropertyType)(Prop_ReadOnly|Prop_Hidden), "Row heights"); + ADD_PROPERTY_TYPE(currRow, (0), "Spreadsheet", (PropertyType)(Prop_ReadOnly|Prop_Hidden), "Current row"); + ADD_PROPERTY_TYPE(currColumn, (0), "Spreadsheet", (PropertyType)(Prop_ReadOnly|Prop_Hidden), "Current column"); docDeps.setSize(0); - onRenamedDocumentConnection = App::GetApplication().signalRenameDocument.connect(boost::bind(&Spreadsheet::Sheet::onRenamedDocument, this, _1)); - onRelabledDocumentConnection = App::GetApplication().signalRelabelDocument.connect(boost::bind(&Spreadsheet::Sheet::onRelabledDocument, this, _1)); + onRenamedDocumentConnection = GetApplication().signalRenameDocument.connect(boost::bind(&Spreadsheet::Sheet::onRenamedDocument, this, _1)); + onRelabledDocumentConnection = GetApplication().signalRelabelDocument.connect(boost::bind(&Spreadsheet::Sheet::onRelabledDocument, this, _1)); } /** @@ -237,7 +238,7 @@ bool Sheet::exportToFile(const std::string &filename, char delimiter, char quote std::set::const_iterator i = usedCells.begin(); while (i != usedCells.end()) { - App::Property * prop = getProperty(*i); + Property * prop = getProperty(*i); if (prevRow != -1 && prevRow != i->row()) { for (int j = prevRow; j < i->row(); ++j) @@ -251,12 +252,12 @@ bool Sheet::exportToFile(const std::string &filename, char delimiter, char quote std::stringstream field; - if (prop->isDerivedFrom((App::PropertyQuantity::getClassTypeId()))) - field << static_cast(prop)->getValue(); - else if (prop->isDerivedFrom((App::PropertyFloat::getClassTypeId()))) - field << static_cast(prop)->getValue(); - else if (prop->isDerivedFrom((App::PropertyString::getClassTypeId()))) - field << static_cast(prop)->getValue(); + if (prop->isDerivedFrom((PropertyQuantity::getClassTypeId()))) + field << static_cast(prop)->getValue(); + else if (prop->isDerivedFrom((PropertyFloat::getClassTypeId()))) + field << static_cast(prop)->getValue(); + else if (prop->isDerivedFrom((PropertyString::getClassTypeId()))) + field << static_cast(prop)->getValue(); else assert(0); @@ -399,7 +400,7 @@ PyObject *Sheet::getPyObject(void) * */ -App::Property * Sheet::getProperty(CellAddress key) const +Property * Sheet::getProperty(CellAddress key) const { return props.getDynamicPropertyByName(key.toString().c_str()); } @@ -410,7 +411,7 @@ App::Property * Sheet::getProperty(CellAddress key) const * @return Pointer to property, or 0 if it does not exist. */ -App::Property * Sheet::getProperty(const char * addr) const +Property * Sheet::getProperty(const char * addr) const { return props.getDynamicPropertyByName(addr); } @@ -421,9 +422,9 @@ App::Property * Sheet::getProperty(const char * addr) const * */ -void Sheet::getCellAddress(const App::Property *prop, CellAddress & address) +void Sheet::getCellAddress(const Property *prop, CellAddress & address) { - std::map::const_iterator i = propAddress.find(prop); + std::map::const_iterator i = propAddress.find(prop); if (i != propAddress.end()) address = i->second; @@ -498,21 +499,21 @@ void Sheet::onSettingDocument() * */ -App::Property * Sheet::setFloatProperty(CellAddress key, double value) +Property * Sheet::setFloatProperty(CellAddress key, double value) { - App::Property * prop = props.getPropertyByName(key.toString().c_str()); - App::PropertyFloat * floatProp; + Property * prop = props.getPropertyByName(key.toString().c_str()); + PropertyFloat * floatProp; - if (!prop || prop->getTypeId() != App::PropertyFloat::getClassTypeId()) { + if (!prop || prop->getTypeId() != PropertyFloat::getClassTypeId()) { if (prop) { props.removeDynamicProperty(key.toString().c_str()); propAddress.erase(prop); } - floatProp = freecad_dynamic_cast(props.addDynamicProperty("App::PropertyFloat", key.toString().c_str(), 0, 0, App::Prop_ReadOnly | App::Prop_Transient, true, true)); + floatProp = freecad_dynamic_cast(props.addDynamicProperty("App::PropertyFloat", key.toString().c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true)); floatProp->StatusBits.set(3); } else - floatProp = static_cast(prop); + floatProp = static_cast(prop); propAddress[floatProp] = key; floatProp->setValue(value); @@ -530,9 +531,9 @@ App::Property * Sheet::setFloatProperty(CellAddress key, double value) * */ -App::Property * Sheet::setQuantityProperty(CellAddress key, double value, const Base::Unit & unit) +Property * Sheet::setQuantityProperty(CellAddress key, double value, const Base::Unit & unit) { - App::Property * prop = props.getPropertyByName(key.toString().c_str()); + Property * prop = props.getPropertyByName(key.toString().c_str()); PropertySpreadsheetQuantity * quantityProp; if (!prop || prop->getTypeId() != PropertySpreadsheetQuantity::getClassTypeId()) { @@ -540,7 +541,7 @@ App::Property * Sheet::setQuantityProperty(CellAddress key, double value, const props.removeDynamicProperty(key.toString().c_str()); propAddress.erase(prop); } - App::Property * p = props.addDynamicProperty("Spreadsheet::PropertySpreadsheetQuantity", key.toString().c_str(), 0, 0, App::Prop_ReadOnly | App::Prop_Transient, true, true); + Property * p = props.addDynamicProperty("Spreadsheet::PropertySpreadsheetQuantity", key.toString().c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true); quantityProp = freecad_dynamic_cast(p); quantityProp->StatusBits.set(3); } @@ -565,17 +566,17 @@ App::Property * Sheet::setQuantityProperty(CellAddress key, double value, const * */ -App::Property * Sheet::setStringProperty(CellAddress key, const std::string & value) +Property * Sheet::setStringProperty(CellAddress key, const std::string & value) { - App::Property * prop = props.getPropertyByName(key.toString().c_str()); - App::PropertyString * stringProp = freecad_dynamic_cast(prop); + Property * prop = props.getPropertyByName(key.toString().c_str()); + PropertyString * stringProp = freecad_dynamic_cast(prop); if (!stringProp) { if (prop) { props.removeDynamicProperty(key.toString().c_str()); propAddress.erase(prop); } - stringProp = freecad_dynamic_cast(props.addDynamicProperty("App::PropertyString", key.toString().c_str(), 0, 0, App::Prop_ReadOnly | App::Prop_Transient, true, true)); + stringProp = freecad_dynamic_cast(props.addDynamicProperty("App::PropertyString", key.toString().c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true)); stringProp->StatusBits.set(3); } @@ -593,7 +594,7 @@ App::Property * Sheet::setStringProperty(CellAddress key, const std::string & va void Sheet::updateAlias(CellAddress key) { std::string alias; - App::Property * prop = props.getDynamicPropertyByName(key.toString().c_str()); + Property * prop = props.getDynamicPropertyByName(key.toString().c_str()); if (!prop) return; @@ -601,7 +602,7 @@ void Sheet::updateAlias(CellAddress key) Cell * cell = getCell(key); if (cell && cell->getAlias(alias)) { - App::Property * aliasProp = props.getDynamicPropertyByName(alias.c_str()); + Property * aliasProp = props.getDynamicPropertyByName(alias.c_str()); /* Update or create alias? */ if (aliasProp) { @@ -613,7 +614,7 @@ void Sheet::updateAlias(CellAddress key) } if (!aliasProp) - aliasProp = props.addDynamicProperty(prop->getTypeId().getName(), alias.c_str(), 0, 0, App::Prop_ReadOnly | App::Prop_Transient, true, true); + aliasProp = props.addDynamicProperty(prop->getTypeId().getName(), alias.c_str(), 0, 0, Prop_ReadOnly | Prop_Transient, true, true); aliasProp->Paste(*prop); } @@ -674,9 +675,9 @@ void Sheet::updateProperty(CellAddress key) * */ -App::Property *Sheet::getPropertyByName(const char* name) const +Property *Sheet::getPropertyByName(const char* name) const { - App::Property * prop = getProperty(name); + Property * prop = getProperty(name); if (prop) return prop; @@ -690,7 +691,7 @@ App::Property *Sheet::getPropertyByName(const char* name) const * @return Pointer to string. */ -const char *Sheet::getPropertyName(const App::Property *prop) const +const char *Sheet::getPropertyName(const Property *prop) const { const char * name = props.getPropertyName(prop); @@ -743,7 +744,7 @@ void Sheet::recomputeCell(CellAddress p) * */ -App::DocumentObjectExecReturn *Sheet::execute(void) +DocumentObjectExecReturn *Sheet::execute(void) { // Remove all aliases first removeAliases(); @@ -852,20 +853,20 @@ App::DocumentObjectExecReturn *Sheet::execute(void) currRow.purgeTouched(); currColumn.purgeTouched(); - std::set ds(cells.getDocDeps()); + std::set ds(cells.getDocDeps()); // Make sure we don't reference ourselves ds.erase(this); - std::vector dv(ds.begin(), ds.end()); + std::vector dv(ds.begin(), ds.end()); docDeps.setValues(dv); purgeTouched(); if (cellErrors.size() == 0) - return App::DocumentObject::StdReturn; + return DocumentObject::StdReturn; else - return new App::DocumentObjectExecReturn("One or more cells failed contains errors.", this); + return new DocumentObjectExecReturn("One or more cells failed contains errors.", this); } /** @@ -899,7 +900,7 @@ void Sheet::clear(CellAddress address, bool all) { Cell * cell = getCell(address); std::string addr = address.toString(); - App::Property * prop = props.getDynamicPropertyByName(addr.c_str()); + Property * prop = props.getDynamicPropertyByName(addr.c_str()); // Remove alias, if defined std::string aliasStr; @@ -909,12 +910,12 @@ void Sheet::clear(CellAddress address, bool all) cells.clear(address); // Update dependencies - std::set ds(cells.getDocDeps()); + std::set ds(cells.getDocDeps()); // Make sure we don't reference ourselves ds.erase(this); - std::vector dv(ds.begin(), ds.end()); + std::vector dv(ds.begin(), ds.end()); docDeps.setValues(dv); propAddress.erase(prop); @@ -1105,7 +1106,7 @@ void Sheet::setStyle(CellAddress address, const std::set &style) * @param color New color */ -void Sheet::setForeground(CellAddress address, const App::Color &color) +void Sheet::setForeground(CellAddress address, const Color &color) { cells.setForeground(address, color); } @@ -1116,7 +1117,7 @@ void Sheet::setForeground(CellAddress address, const App::Color &color) * @param color New color */ -void Sheet::setBackground(CellAddress address, const App::Color &color) +void Sheet::setBackground(CellAddress address, const Color &color) { cells.setBackground(address, color); } @@ -1182,7 +1183,7 @@ void Sheet::moveCell(CellAddress currPos, CellAddress newPos) * @param docObj Renamed document object. */ -void Sheet::renamedDocumentObject(const App::DocumentObject * docObj) +void Sheet::renamedDocumentObject(const DocumentObject * docObj) { cells.renamedDocumentObject(docObj); cells.touch(); @@ -1252,7 +1253,7 @@ void Sheet::onDocumentRestored() * @param document Relabelled document. */ -void Sheet::onRelabledDocument(const App::Document &document) +void Sheet::onRelabledDocument(const Document &document) { cells.renamedDocument(&document); cells.purgeTouched(); @@ -1263,7 +1264,7 @@ void Sheet::onRelabledDocument(const App::Document &document) * @param document */ -void Sheet::onRenamedDocument(const App::Document &document) +void Sheet::onRenamedDocument(const Document &document) { } @@ -1272,7 +1273,7 @@ void Sheet::onRenamedDocument(const App::Document &document) * @param document document to observer. */ -void Sheet::observeDocument(App::Document * document) +void Sheet::observeDocument(Document * document) { ObserverMap::const_iterator it = observers.find(document->getName()); @@ -1290,7 +1291,7 @@ void Sheet::observeDocument(App::Document * document) TYPESYSTEM_SOURCE(Spreadsheet::PropertySpreadsheetQuantity, App::PropertyQuantity); -App::Property *PropertySpreadsheetQuantity::Copy() const +Property *PropertySpreadsheetQuantity::Copy() const { PropertySpreadsheetQuantity * obj = new PropertySpreadsheetQuantity(); diff --git a/src/Mod/Spreadsheet/App/Sheet.h b/src/Mod/Spreadsheet/App/Sheet.h index 60949f91e..e8a26fc89 100644 --- a/src/Mod/Spreadsheet/App/Sheet.h +++ b/src/Mod/Spreadsheet/App/Sheet.h @@ -48,7 +48,6 @@ namespace Spreadsheet class Sheet; class Cell; -class Expression; class Range; class SheetObserver; diff --git a/src/Mod/Spreadsheet/App/SheetObserver.h b/src/Mod/Spreadsheet/App/SheetObserver.h index 568d88769..c3a9dfcd7 100644 --- a/src/Mod/Spreadsheet/App/SheetObserver.h +++ b/src/Mod/Spreadsheet/App/SheetObserver.h @@ -41,7 +41,7 @@ public: App::Document* getDocument() const { return App::DocumentObserver::getDocument(); } private: std::set isUpdating; - int refCount; + unsigned int refCount; PropertySheet * sheet; }; diff --git a/src/Mod/Spreadsheet/App/SpreadsheetExpression.cpp b/src/Mod/Spreadsheet/App/SpreadsheetExpression.cpp index 8e2d4e48d..218e4c358 100644 --- a/src/Mod/Spreadsheet/App/SpreadsheetExpression.cpp +++ b/src/Mod/Spreadsheet/App/SpreadsheetExpression.cpp @@ -64,707 +64,25 @@ #define strtoll _strtoi64 #endif +using namespace App; using namespace Base; using namespace Spreadsheet; -Path::Path(const App::DocumentObject * _owner, const std::string & property) - : owner(_owner) - , propertyIndex(-1) - , documentNameSet(false) - , documentObjectNameSet(false) -{ - if (property.size() > 0) - addComponent(Component::SimpleComponent(property)); -} - -bool Path::operator ==(const Path &other) const -{ - if (owner != other.owner) - return false; - if (documentName != other.documentName) - return false; - if (documentObjectName != other.documentObjectName) - return false; - if (components != other.components) - return false; - return true; -} - -bool Path::operator <(const Path &other) const -{ - if (documentName < other.documentName) - return true; - - if (documentName > other.documentName) - return false; - - if (documentObjectName < other.documentObjectName) - return true; - - if (documentObjectName > other.documentObjectName) - return false; - - if (components.size() < other.components.size()) - return true; - - if (components.size() > other.components.size()) - return false; - - for (std::size_t i = 0; i < components.size(); ++i) { - if (components[i].component < other.components[i].component) - return true; - if (components[i].component > other.components[i].component) - return false; - if (components[i].type < other.components[i].type) - return true; - if (components[i].type > other.components[i].type) - return false; - if (components[i].type == Component::ARRAY) { - if (components[i].index < other.components[i].index) - return true; - if (components[i].index > other.components[i].index) - return false; - } - else if (components[i].type == Component::MAP) { - if (components[i].key < other.components[i].key) - return true; - if (components[i].key > other.components[i].key) - return false; - } - } - return false; -} - -int Path::numComponents() const -{ - return components.size(); -} - -Path Path::parse(const App::DocumentObject * docObj, const char *expr) -{ - return Path(); -} - -std::string Path::toString() const -{ - std::stringstream s; - - if (documentNameSet) { - if (getDocumentName().isRealString()) - s << quote(getDocumentName().getString()) << "#"; - else - s << getDocumentName().getString() << "#"; - } - - if (documentObjectNameSet) { - if (getDocumentObjectName().isRealString()) - s << quote(getDocumentObjectName().getString()) << "."; - else - s << getDocumentObjectName().getString() << "."; - } - else if (propertyIndex > 0) - s << components[0].component << "."; - - s << getPropertyName() << getSubPathStr(); - - return s.str(); -} - -std::string Path::getPythonAccessor() const -{ - const App::Property * prop = getProperty(); - - if (!prop) - throw Exception(std::string("Property '") + getPropertyName() + std::string("' not found.")); - - const App::DocumentObject * docObj = freecad_dynamic_cast(prop->getContainer()); - - if (!docObj) - throw Exception("Document object not found"); - - const App::Document * doc = docObj->getDocument(); - - return "App.getDocument('" + - std::string(doc->getName()) + "')." + - docObj->getNameInDocument() + "." + - getPropertyName() + - getSubPathStr(); -} - -void Path::renameDocumentObject(const std::string &oldName, const std::string &newName) -{ - if (documentObjectNameSet && documentObjectName == oldName) { - documentObjectName = newName; - resolve(); - } - else if (propertyIndex == 1 && documentObjectName == oldName) { - components[0].component = newName; - resolve(); - } -} - -void Path::renameDocument(const std::string &oldName, const std::string &newName) -{ - if (documentName == oldName) { - documentName = newName; - resolve(); - } -} - -std::string Path::getSubPathStr() const -{ - std::stringstream s; - - std::vector::const_iterator i = components.begin() + propertyIndex + 1; - while (i != components.end()) { - s << "." << i->toString(); - ++i; - } - - return s.str(); -} - -Path::Component::Component(const std::string &_component, Path::Component::typeEnum _type, int _index, String _key) - : component(_component) - , type(_type) - , index(_index) - , key(_key) -{ -} - -Path::Component Path::Component::SimpleComponent(const std::string &_component) -{ - return Component(_component); -} - -Path::Component Path::Component::ArrayComponent(const std::string &_component, int _index) -{ - return Component(_component, ARRAY, _index); -} - -Path::Component Path::Component::MapComponent(const std::string &_component, const String & _key) -{ - return Component(_component, MAP, -1, _key); -} - -bool Path::Component::operator ==(const Path::Component &other) const -{ - if (type != other.type) - return false; - - if (component != other.component) - return false; - - switch (type) { - case SIMPLE: - return true; - case ARRAY: - return index == other.index; - case MAP: - return key == other.key; - default: - assert(0); - return false; - } -} - -std::string Path::Component::toString() const -{ - std::stringstream s; - - s << component; - switch (type) { - case Component::SIMPLE: - break; - case Component::MAP: - s << "[" << key.toString() << "]"; - break; - case Component::ARRAY: - s << "[" << index << "]"; - break; - default: - assert(0); - } - - return s.str(); -} - -// -// Expression base-class -// - -TYPESYSTEM_SOURCE_ABSTRACT(Spreadsheet::Expression, Base::BaseClass); - -Expression::Expression(const App::DocumentObject *_owner) - : owner(_owner) -{ - -} - -Expression::~Expression() -{ -} - -Expression * Expression::parse(const App::DocumentObject *owner, const std::string &buffer) -{ - return ExpressionParser::parse(owner, buffer.c_str()); -} - -// -// UnitExpression class -// - -TYPESYSTEM_SOURCE(Spreadsheet::UnitExpression, Spreadsheet::Expression); - -UnitExpression::UnitExpression(const App::DocumentObject *_owner, const Base::Quantity & _quantity, const std::string &_unitStr) - : Expression(_owner) - , quantity(_quantity) - , unitStr(_unitStr) -{ -} - -/** - * Set unit information. - * - * @param _unit A unit object - * @param _unitstr The unit expressed as a string - * @param _scaler Scale factor to convert unit into internal unit. - */ - -void UnitExpression::setUnit(const Quantity &_quantity) -{ - quantity = _quantity; -} - -/** - * Evaulate the expression - * - * @returns A NumberExpression set to 1.0. - */ - -Expression *UnitExpression::eval() const -{ - return new NumberExpression(owner, quantity); -} - -/** - * Simplify the expression. In this case, a NumberExpression is returned, - * as it cannot be simplified any more. - */ - -Expression *UnitExpression::simplify() const -{ - return new NumberExpression(owner, quantity); -} - -/** - * Return a string representation, in this case the unit string. - */ - -/** - * Return a string representation of the expression. - */ - -std::string UnitExpression::toString() const -{ - return unitStr; -} - -/** - * Return a copy of the expression. - */ - -Expression *UnitExpression::copy() const -{ - return new UnitExpression(owner, quantity); -} - -// -// NumberExpression class -// - -TYPESYSTEM_SOURCE(Spreadsheet::NumberExpression, Spreadsheet::Expression); - -NumberExpression::NumberExpression(const App::DocumentObject *_owner, const Quantity &_quantity) - : UnitExpression(_owner, _quantity) -{ -} - -/** - * Evalute the expression. For NumberExpressions, it is a simply copy(). - */ - -Expression * NumberExpression::eval() const -{ - return copy(); -} - -/** - * Simplify the expression. For NumberExpressions, we return a copy(), as it cannot - * be simplified any more. - */ - -Expression *NumberExpression::simplify() const -{ - return copy(); -} - -/** - * Create and return a copy of the expression. - */ - -Expression *NumberExpression::copy() const -{ - return new NumberExpression(owner, quantity); -} - -/** - * Negate the stored value. - */ - -void NumberExpression::negate() -{ - quantity.setValue(-quantity.getValue()); -} - -std::string NumberExpression::toString() const -{ - std::stringstream s; - s << quantity.getValue(); - - /* Trim of any extra spaces */ - //while (s.size() > 0 && s[s.size() - 1] == ' ') -// s.erase(s.size() - 1); - - return s.str(); -} - -// -// OperatorExpression class -// - -TYPESYSTEM_SOURCE(Spreadsheet::OperatorExpression, Spreadsheet::Expression); - -OperatorExpression::OperatorExpression(const App::DocumentObject *_owner, Expression * _left, Operator _op, Expression * _right) - : UnitExpression(_owner) - , op(_op) - , left(_left) - , right(_right) -{ - -} - -OperatorExpression::~OperatorExpression() -{ - delete left; - delete right; -} - -/** - * Determine whether the expression is touched or not, i.e relies on properties that are touched. - */ - -bool OperatorExpression::isTouched() const -{ - return left->isTouched() || right->isTouched(); -} - -/** - * Evalutate the expression. Returns a new NumberExpression with the result, or throws - * an exception if something is wrong, i.e the expression cannot be evaluated. - */ - -Expression * OperatorExpression::eval() const -{ - std::auto_ptr e1(left->eval()); - NumberExpression * v1; - std::auto_ptr e2(right->eval()); - NumberExpression * v2; - NumberExpression * output = 0; - - v1 = freecad_dynamic_cast(e1.get()); - v2 = freecad_dynamic_cast(e2.get()); - - if (v1 == 0 || v2 == 0) - throw Exception("Invalid expression"); - - switch (op) { - case ADD: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, v1->getQuantity() + v2->getQuantity()); - break; - case SUB: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for - operator"); - output = new NumberExpression(owner, v1->getQuantity()- v2->getQuantity()); - break; - case MUL: - case UNIT: - output = new NumberExpression(owner, v1->getQuantity() * v2->getQuantity()); - break; - case DIV: - output = new NumberExpression(owner, v1->getQuantity() / v2->getQuantity()); - break; - case POW: - output = new NumberExpression(owner, v1->getQuantity().pow(v2->getQuantity()) ); - break; - case EQ: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, Quantity(fabs(v1->getValue() - v2->getValue()) < 1e-7)); - break; - case NEQ: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, Quantity(fabs(v1->getValue() - v2->getValue()) > 1e-7)); - break; - case LT: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, Quantity(v1->getValue() < v2->getValue())); - break; - case GT: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, Quantity(v1->getValue() > v2->getValue())); - break; - case LTE: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, Quantity(v1->getValue() - v2->getValue() < 1e-7)); - break; - case GTE: - if (v1->getUnit() != v2->getUnit()) - throw Exception("Incompatible units for + operator"); - output = new NumberExpression(owner, Quantity(v2->getValue() - v1->getValue()) < 1e-7); - break; - case NEG: - output = new NumberExpression(owner, -v1->getQuantity() ); - break; - case POS: - output = new NumberExpression(owner, v1->getQuantity() ); - break; - default: - assert(0); - } - - return output; -} - -/** - * Simplify the expression. For OperatorExpressions, we return a NumberExpression if - * both the left and right side can be simplified to NumberExpressions. In this case - * we can calculate the final value of the expression. - * - * @returns Simplified expression. - */ - -Expression *OperatorExpression::simplify() const -{ - Expression * v1 = left->simplify(); - Expression * v2 = right->simplify(); - - // Both arguments reduced to numerics? Then evaluate and return answer - if (freecad_dynamic_cast(v1) && freecad_dynamic_cast(v2)) { - delete v1; - delete v2; - return eval(); - } - else - return new OperatorExpression(owner, v1, op, v2); -} - -/** - * Create a string representation of the expression. - * - * @returns A string representing the expression. - */ - -std::string OperatorExpression::toString() const -{ - std::stringstream s; - - switch (op) { - case NEG: - s << "-"; - break; - case POS: - s << "+"; - break; - default: - break; - } - - if (left->priority() < priority()) - s << "(" << left->toString() << ")"; - else - s << left->toString(); - - switch (op) { - case ADD: - s << " + "; - break; - case SUB: - s << " - "; - break; - case MUL: - s << " * "; - break; - case DIV: - s << " / "; - break; - case POW: - s << " ^ "; - break; - case EQ: - s << " == "; - break; - case NEQ: - s << " != "; - break; - case LT: - s << " < "; - break; - case GT: - s << " > "; - break; - case LTE: - s << " <= "; - break; - case GTE: - s << " >= "; - break; - case UNIT: - break; - case POS: - case NEG: - return s.str(); - default: - assert(0); - } - - if (right->priority() < priority()) - s << "(" << right->toString() << ")"; - else - s << right->toString(); - - return s.str(); -} - -/** - * A deep copy of the expression. - */ - -Expression *OperatorExpression::copy() const -{ - return new OperatorExpression(owner, left->copy(), op, right->copy()); -} - -/** - * Return the operators priority. This is used to add parentheses where - * needed when creating a string representation of the expression. - * - * @returns The operator's priority. - */ - -int OperatorExpression::priority() const -{ - switch (op) { - case ADD: - return 5; - case SUB: - return 5; - case MUL: - case UNIT: - return 10; - case DIV: - return 10; - case POW: - return 10; - case NEG: - case POS: - return 15; - default: - return 0; - } -} - -/** - * Compute the expressions dependencies, i.e the properties it relies on. - * - * @param props A set of strings. Each string contains the name of a property that this expression depends on. - */ - -void OperatorExpression::getDeps(std::set &props) const -{ - left->getDeps(props); - right->getDeps(props); -} - -void OperatorExpression::visit(ExpressionVisitor &v) -{ - if (left) - left->visit(v); - if (right) - right->visit(v); - v.visit(this); -} - // // FunctionExpression class. This class handles functions with one or two parameters. // -TYPESYSTEM_SOURCE(Spreadsheet::FunctionExpression, Spreadsheet::UnitExpression); +TYPESYSTEM_SOURCE(Spreadsheet::AggregateFunctionExpression, App::FunctionExpression); -FunctionExpression::FunctionExpression(const App::DocumentObject *_owner, Function _f, std::vector _args) - : UnitExpression(_owner) - , f(_f) - , args(_args) +AggregateFunctionExpression::AggregateFunctionExpression(const DocumentObject *_owner, + App::FunctionExpression::Function _f, + std::vector _args) + : FunctionExpression(_owner, static_cast(_f), _args) { - switch (f) { - case NONE: - throw Exception("Unknown function"); - case MOD: - case ATAN2: - case POW: - if (args.size() != 2) - throw Exception("Invalid number of arguments."); - break; - default: - if (args.size() != 1) - throw Exception("Invalid number of arguments."); - break; - } } -FunctionExpression::~FunctionExpression() +AggregateFunctionExpression::~AggregateFunctionExpression() { - std::vector::iterator i = args.begin(); - - while (i != args.end()) { - delete *i; - ++i; - } -} - -/** - * Determinte whether the expressions is considered touched, i.e one or both of its arguments - * are touched. - * - * @return True if touched, false if not. - */ - -bool FunctionExpression::isTouched() const -{ - std::vector::const_iterator i = args.begin(); - - while (i != args.end()) { - if ((*i)->isTouched()) - return true; - ++i; - } - return false; } /** @@ -774,9 +92,9 @@ bool FunctionExpression::isTouched() const * @returns A NumberExpression with the result. */ -Expression * FunctionExpression::eval() const +Expression * AggregateFunctionExpression::eval() const { - switch (f) { + switch (static_cast(f)) { case SUM: case AVERAGE: case STDDEV: @@ -798,17 +116,17 @@ Expression * FunctionExpression::eval() const Range range(v->getRange()); do { - App::Property * p = owner->getPropertyByName(range.address().c_str()); - App::PropertyQuantity * qp; - App::PropertyFloat * fp; + Property * p = owner->getPropertyByName(range.address().c_str()); + PropertyQuantity * qp; + PropertyFloat * fp; Quantity value; if (!p) continue; - if ( (qp = freecad_dynamic_cast(p)) ) + if ((qp = freecad_dynamic_cast(p)) != 0) value = qp->getQuantityValue(); - else if ( (fp = freecad_dynamic_cast(p)) ) + else if ((fp = freecad_dynamic_cast(p)) != 0) value = fp->getValue(); else throw Exception("Invalid property type for aggregate"); @@ -819,7 +137,7 @@ Expression * FunctionExpression::eval() const M2.setUnit(value.getUnit()); } - switch (f) { + switch (static_cast(f)) { case AVERAGE: n++; case SUM: @@ -851,7 +169,7 @@ Expression * FunctionExpression::eval() const first = false; } while (range.next()); - switch (f) { + switch (static_cast(f)) { case AVERAGE: q = q / (double)n; break; @@ -868,222 +186,7 @@ Expression * FunctionExpression::eval() const return new NumberExpression(owner, q); } default: - break; - } - - - std::auto_ptr e1(args[0]->eval()); - std::auto_ptr e2(args.size() > 1 ? args[1]->eval() : 0); - NumberExpression * v1 = freecad_dynamic_cast(e1.get()); - NumberExpression * v2 = freecad_dynamic_cast(e2.get()); - double output = 0; - Unit unit; - double scaler = 1; - - if (v1 == 0) - throw Exception("Invalid argument."); - - double value = v1->getValue(); - - /* Check units and arguments */ - switch (f) { - case COS: - case SIN: - case TAN: - if (!(v1->getUnit() == Unit::Angle || v1->getUnit().isEmpty())) - throw Exception("Unit must be either empty or an angle."); - - // Convert value to radians - value *= M_PI / 180.0; - unit = Unit(); - break; - case ACOS: - case ASIN: - case ATAN: - if (!v1->getUnit().isEmpty()) - throw Exception("Unit must be empty."); - unit = Unit::Angle; - scaler = 180.0 / M_PI; - break; - case EXP: - case LOG: - case LOG10: - case SINH: - case TANH: - case COSH: - if (!v1->getUnit().isEmpty()) - throw Exception("Unit must be empty."); - unit = Unit(); - break; - case ABS: - unit = v1->getUnit(); - break; - case SQRT: { - unit = v1->getUnit(); - - // All components of unit must be either zero or dividable by 2 - UnitSignature s = unit.getSignature(); - if ( !((s.Length % 2) == 0) && - ((s.Mass % 2) == 0) && - ((s.Time % 2) == 0) && - ((s.ElectricCurrent % 2) == 0) && - ((s.ThermodynamicTemperature % 2) == 0) && - ((s.AmountOfSubstance % 2) == 0) && - ((s.LuminoseIntensity % 2) == 0) && - ((s.Angle % 2) == 0)) - throw Exception("All dimensions must be even to compute the square root."); - - unit = Unit(s.Length /2, - s.Mass / 2, - s.Time / 2, - s.ElectricCurrent / 2, - s.ThermodynamicTemperature / 2, - s.AmountOfSubstance / 2, - s.LuminoseIntensity / 2, - s.Angle); - break; - } - case ATAN2: - if (v2 == 0) - throw Exception("Invalid second argument."); - - if (v1->getUnit() != v2->getUnit()) - throw Exception("Units must be equal"); - unit = Unit::Angle; - scaler = 180.0 / M_PI; - break; - case MOD: - if (v2 == 0) - throw Exception("Invalid second argument."); - if (!v2->getUnit().isEmpty()) - throw Exception("Second argument must have empty unit."); - unit = v1->getUnit(); - break; - case POW: { - if (v2 == 0) - throw Exception("Invalid second argument."); - - if (!v2->getUnit().isEmpty()) - throw Exception("Exponent is not allowed to have a unit."); - - // Compute new unit for exponentation - double exponent = v2->getValue(); - if (!v1->getUnit().isEmpty()) { - if (exponent - boost::math::round(exponent) < 1e-9) - unit = v1->getUnit().pow(exponent); - else - throw Exception("Exponent must be an integer when used with a unit"); - } - break; - } - default: - assert(0); - } - - /* Compute result */ - switch (f) { - case ACOS: - output = acos(value); - break; - case ASIN: - output = asin(value); - break; - case ATAN: - output = atan(value); - break; - case ABS: - output = fabs(value); - break; - case EXP: - output = exp(value); - break; - case LOG: - output = log(value); - break; - case LOG10: - output = log(value) / log(10.0); - break; - case SIN: - output = sin(value); - break; - case SINH: - output = sinh(value); - break; - case TAN: - output = tan(value); - break; - case TANH: - output = tanh(value); - break; - case SQRT: - output = sqrt(value); - break; - case COS: - output = cos(value); - break; - case COSH: - output = cosh(value); - break; - case MOD: { - output = fmod(value, v2->getValue()); - break; - } - case ATAN2: { - output = atan2(value, v2->getValue()); - break; - } - case POW: { - output = pow(value, v2->getValue()); - break; - } - default: - assert(0); - } - - return new NumberExpression(owner, Quantity(scaler * output, unit)); -} - -/** - * Try to simplify the expression, i.e calculate all constant expressions. - * - * @returns A simplified expression. - */ - -Expression *FunctionExpression::simplify() const -{ - Expression * v1 = args[0]->simplify(); - - // Argument simplified to numeric expression? Then return evaluate and return - if (freecad_dynamic_cast(v1)) { - switch (f) { - case ATAN2: - case MOD: - case POW: - { - Expression * v2 = args[1]->simplify(); - - if (freecad_dynamic_cast(v2)) { - delete v1; - delete v2; - return eval(); - } - else { - std::vector a; - a.push_back(v1); - a.push_back(v2); - return new FunctionExpression(owner, f, a); - } - } - default: - break; - } - delete v1; - return eval(); - } - else { - std::vector a; - a.push_back(v1); - return new FunctionExpression(owner, f, a); + return App::FunctionExpression::eval(); } } @@ -1093,43 +196,9 @@ Expression *FunctionExpression::simplify() const * @returns A string representing the expression. */ -std::string FunctionExpression::toString() const +std::string AggregateFunctionExpression::toString() const { - switch (f) { - case ACOS: - return "acos(" + args[0]->toString() + ")"; - case ASIN: - return "asin(" + args[0]->toString() + ")"; - case ATAN: - return "atan(" + args[0]->toString() + ")"; - case ABS: - return "abs(" + args[0]->toString() + ")"; - case EXP: - return "exp(" + args[0]->toString() + ")"; - case LOG: - return "log(" + args[0]->toString() + ")"; - case LOG10: - return "log10(" + args[0]->toString() + ")"; - case SIN: - return "sin(" + args[0]->toString() + ")"; - case SINH: - return "sinh(" + args[0]->toString() + ")"; - case TAN: - return "tan(" + args[0]->toString() + ")"; - case TANH: - return "tanh(" + args[0]->toString() + ")"; - case SQRT: - return "sqrt(" + args[0]->toString() + ")"; - case COS: - return "cos(" + args[0]->toString() + ")"; - case COSH: - return "cosh(" + args[0]->toString() + ")"; - case MOD: - return "mod(" + args[0]->toString() + ", " + args[1]->toString() + ")"; - case ATAN2: - return "atan2(" + args[0]->toString() + ", " + args[1]->toString() + ")"; - case POW: - return "pow(" + args[0]->toString() + ", " + args[1]->toString() + ")"; + switch (static_cast(f)) { case SUM: return "sum(" + args[0]->toString() + ")"; case COUNT: @@ -1143,520 +212,66 @@ std::string FunctionExpression::toString() const case MAX: return "max(" + args[0]->toString() + ")"; default: - assert(0); - return std::string(); + return App::FunctionExpression::toString(); } } -/** - * Create a copy of the expression. - * - * @returns A deep copy of the expression. - */ +TYPESYSTEM_SOURCE(Spreadsheet::RangeExpression, App::Expression); -Expression *FunctionExpression::copy() const -{ - std::vector::const_iterator i = args.begin(); - std::vector a; - - while (i != args.end()) { - a.push_back((*i)->copy()); - ++i; - } - return new FunctionExpression(owner, f, a); -} - -/** - * Compute the dependecy set of the expression. The set contains the names - * of all Property objects this expression relies on. - */ - -void FunctionExpression::getDeps(std::set &props) const -{ - std::vector::const_iterator i = args.begin(); - - while (i != args.end()) { - (*i)->getDeps(props); - ++i; - } -} - -void FunctionExpression::visit(ExpressionVisitor &v) -{ - std::vector::const_iterator i = args.begin(); - - while (i != args.end()) { - (*i)->visit(v); - ++i; - } - v.visit(this); -} - -// -// VariableExpression class -// - -TYPESYSTEM_SOURCE(Spreadsheet::VariableExpression, Spreadsheet::UnitExpression); - -VariableExpression::VariableExpression(const App::DocumentObject *_owner, Path _var) - : UnitExpression(_owner) - , var(_var) -{ -} - -VariableExpression::~VariableExpression() -{ -} - -/** - * Determine if the expression is touched or not, i.e whether the Property object it - * refers to is touched(). - * - * @returns True if the Property object is touched, false if not. - */ - -bool VariableExpression::isTouched() const -{ - try { - return getProperty()->isTouched(); - } - catch (...) { - return false; - } -} - -const App::DocumentObject * Path::getDocumentObject(const App::Document * doc, const std::string & name) const -{ - App::DocumentObject * o1 = 0; - App::DocumentObject * o2 = 0; - std::vector docObjects = doc->getObjects(); - - for (std::vector::iterator j = docObjects.begin(); j != docObjects.end(); ++j) { - if (strcmp((*j)->Label.getValue(), name.c_str()) == 0) { - // Found object with matching label - if (o1 != 0) - return 0; - o1 = *j; - } - } - - // No object found with matching label, try using name directly - o2 = doc->getObject(name.c_str()); - - if (o1 == 0 && o2 == 0) // Not found at all - return 0; - else if (o1 == 0) // Found by name - return o2; - else if (o2 == 0) // Found by label - return o1; - else if (o1 == o2) // Found by both name and label, same object - return o1; - else - return 0; // Found by both name and label, two different objects -} - -void Path::resetResolve() -{ - if (!documentNameSet) - documentName = String(); - if (!documentObjectNameSet) - documentObjectName = String(); -} - -void Path::resolve() -{ - const App::Document * doc; - const App::DocumentObject * docObject; - - /* Document name specified? */ - if (getDocumentName().getString().size() > 0) - doc = getDocument(); - else { - setDocumentName(String(owner->getDocument()->Label.getValue())); - doc = owner->getDocument(); - } - - propertyName = ""; - propertyIndex = 0; - if (doc == 0) - return; - - /* Document object name specified? */ - if (getDocumentObjectName().getString().size() > 0) { - docObject = getDocumentObject(doc, getDocumentObjectName().getString()); - if (!docObject) - return; - if (components.size() > 0) { - propertyName = components[0].component; - propertyIndex = 0; - } - else - return; - } - else { - /* Document object name not specified, resolve from path */ - if (components.size() == 1) { - setDocumentObjectName(String(owner->getNameInDocument())); - propertyName = components[0].component; - propertyIndex = 0; - } - else if (components.size() >= 2) { - if (!components[0].isSimple()) - return; - - docObject = getDocumentObject(doc, components[0].component); - - if (docObject) { - setDocumentObjectName(components[0].component); - propertyName = components[1].component; - propertyIndex = 1; - } - else { - setDocumentObjectName(String(owner->getNameInDocument())); - propertyName = components[0].component; - propertyIndex = 0; - } - } - else - return; - } -} - -App::Document * Path::getDocument() const -{ - App::Document * doc = 0; - const std::vector docs = App::GetApplication().getDocuments(); - - for (std::vector::const_iterator i = docs.begin(); i != docs.end(); ++i) { - if ((*i)->Label.getValue() == getDocumentName().getString()) { - if (doc != 0) - return 0; - doc = *i; - } - } - - return doc; -} - -const App::DocumentObject *Path::getDocumentObject() const -{ - const App::Document * doc = getDocument(); - - if (!doc) - return 0; - - return getDocumentObject(doc, documentObjectName); -} - -const App::Property *Path::getProperty() const -{ - const App::Document * doc = getDocument(); - - if (!doc) - return 0; - - const App::DocumentObject * docObj = getDocumentObject(doc, documentObjectName); - - if (!docObj) - return 0; - - return docObj->getPropertyByName(propertyName.c_str()); -} - -/** - * Find the property this expression referse to. - * - * Unqualified names (i.e the name only without any dots) are resolved in the owning DocumentObjects. - * Qualified names are looked up in the owning Document. It is first looked up by its internal name. - * If not found, the DocumentObjects' labels searched. - * - * If something fails, an exception is thrown. - * - * @returns The Property object if it is derived from either PropertyInteger, PropertyFloat, or PropertyString. - */ - -const App::Property * VariableExpression::getProperty() const -{ -#ifdef FULL_EXPRESSION_SUPPORT - const Property * prop = docObject->getPropertyByPath(var); -#else - const App::Property * prop = var.getProperty(); -#endif - if (prop) - return prop; - else - throw Base::Exception(std::string("Property '") + var.getPropertyName() + std::string("' not found.")); -} - -/** - * Evalute the expression. For a VariableExpression, this means to return the - * value of the referenced Property. Quantities are converted to NumberExpression with unit, - * int and floats are converted to a NumberExpression without unit. Strings properties - * are converted to StringExpression objects. - * - * @returns The result of the evaluation, i.e a new (Number|String)Expression object. - */ - -Expression * VariableExpression::eval() const -{ -#ifdef FULL_EXPRESSION_SUPPORT - const Property * prop = getProperty(); - PropertyContainer * parent = prop->getContainer(); - - if (!parent->isDerivedFrom(App::DocumentObject::getClassTypeId())) - throw Base::Exception("Property must belong to a document object."); - - return static_cast(parent)->getValue(var); -#else - std::string s = "_spreadsheet_temp_ = " + var.getPythonAccessor(); - PyObject * pyvalue = Base::Interpreter().getValue(s.c_str(), "_spreadsheet_temp_"); - Expression * output; - - if (!pyvalue) - throw Base::Exception("Failed to get property value."); - - if (PyInt_Check(pyvalue)) - output = new NumberExpression(owner, PyInt_AsLong(pyvalue)); - else if (PyFloat_Check(pyvalue)) - output = new NumberExpression(owner, PyFloat_AsDouble(pyvalue)); - else if (PyString_Check(pyvalue)) - output = new StringExpression(owner, PyString_AsString(pyvalue)); - else if (PyUnicode_Check(pyvalue)) { - PyObject * s = PyUnicode_AsUTF8String(pyvalue); - - output = new StringExpression(owner, PyString_AsString(s)); - Py_DECREF(s); - } - else if (PyObject_TypeCheck(pyvalue, &QuantityPy::Type)) { - Base::QuantityPy * qp = static_cast(pyvalue); - Base::Quantity * q = qp->getQuantityPtr(); - - output = new NumberExpression(owner, *q); - } - else { - Py_DECREF(pyvalue); - throw Base::Exception("Invalid property type."); - } - - Py_DECREF(pyvalue); - - return output; -#if 0 - - if (prop->isDerivedFrom(PropertyQuantity::getClassTypeId())) { - const PropertyQuantity * value = static_cast(prop); - return new NumberExpression(owner, value->getValue(), value->getUnit()); - } - else if (prop->isDerivedFrom(PropertyFloat::getClassTypeId())) { - const PropertyFloat * value = static_cast(prop); - return new NumberExpression(owner, value->getValue()); - } - else if (prop->isDerivedFrom(PropertyInteger::getClassTypeId())) { - const PropertyInteger * value = static_cast(prop); - return new NumberExpression(owner, value->getValue()); - } - else if (prop->isDerivedFrom(PropertyString::getClassTypeId())) { - const PropertyString * value = static_cast(prop); - return new StringExpression(owner, value->getValue()); - } - - throw Base::Exception("Property is of invalid type (not float)."); -#endif -#endif -} - -/** - * Simplify the expression. Simplification of VariableExpression objects is - * not possible (if it is instantiated it would be an evaluation instead). - * - * @returns A copy of the expression. - */ - -Expression *VariableExpression::simplify() const -{ - return copy(); -} - -/** - * Return a copy of the expression. - */ - -Expression *VariableExpression::copy() const -{ - return new VariableExpression(owner, var); -} - -/** - * Compute the dependecy of the expression. In this case \a props - * is a set of strings, i.e the names of the Property objects, and - * the variable name this expression relies on is inserted into the set. - * Notice that the variable may be unqualified, i.e without any reference - * to the owning object. This must be taken into consideration when using - * the set. - */ - -void VariableExpression::getDeps(std::set &props) const -{ - props.insert(var); -} - -void VariableExpression::resolve() -{ - var.resetResolve(); - var.resolve(); -} - -void VariableExpression::renameDocumentObject(const std::string &oldName, const std::string &newName) -{ - var.renameDocumentObject(oldName, newName); -} - -void VariableExpression::renameDocument(const std::string &oldName, const std::string &newName) -{ - var.renameDocument(oldName, newName); -} - -// -// StringExpression class -// - -TYPESYSTEM_SOURCE(Spreadsheet::StringExpression, Spreadsheet::Expression); - -StringExpression::StringExpression(const App::DocumentObject *_owner, const std::string &_text) +RangeExpression::RangeExpression(const DocumentObject *_owner, const std::string &begin, const std::string &end) : Expression(_owner) - , text(_text) + , range((begin + ":" + end).c_str()) { } -/** - * Evalute the string. For strings, this is a simple copy of the object. - */ +bool RangeExpression::isTouched() const +{ + Range i(range); -Expression * StringExpression::eval() const + do { + Property * prop = owner->getPropertyByName(i.address().c_str()); + + if (prop && prop->isTouched()) + return true; + } while (i.next()); + + return false; +} + +Expression *RangeExpression::eval() const +{ + throw Exception("Range expression cannot be evaluated"); +} + +std::string RangeExpression::toString() const +{ + return range.rangeString(); +} + +Expression *RangeExpression::copy() const +{ + return new RangeExpression(owner, range.fromCellString(), range.toCellString()); +} + +void RangeExpression::getDeps(std::set &props) const +{ + Range i(range); + + do { + props.insert(ObjectIdentifier(owner, i.address())); + } while (i.next()); +} + +Expression *RangeExpression::simplify() const { return copy(); } -/** - * Simplify the expression. For strings, this is a simple copy of the object. - */ - -Expression *StringExpression::simplify() const +void RangeExpression::setRange(const Range &r) { - return copy(); + range = r; } -std::string StringExpression::toString() const -{ - return quote(text); -} - -/** - * Return a copy of the expression. - */ - -Expression *StringExpression::copy() const -{ - return new StringExpression(owner, text); -} - -TYPESYSTEM_SOURCE(Spreadsheet::ConditionalExpression, Spreadsheet::Expression); - -ConditionalExpression::ConditionalExpression(const App::DocumentObject *_owner, Expression *_condition, Expression *_trueExpr, Expression *_falseExpr) - : Expression(_owner) - , condition(_condition) - , trueExpr(_trueExpr) - , falseExpr(_falseExpr) -{ -} - -ConditionalExpression::~ConditionalExpression() -{ - delete condition; - delete trueExpr; - delete falseExpr; -} - -bool ConditionalExpression::isTouched() const -{ - return condition->isTouched() || trueExpr->isTouched() || falseExpr->isTouched(); -} - -Expression *ConditionalExpression::eval() const -{ - std::auto_ptr e(condition->eval()); - NumberExpression * v = freecad_dynamic_cast(e.get()); - - if (v == 0) - throw Exception("Invalid expression"); - - if (fabs(v->getValue()) > 0.5) - return trueExpr->eval(); - else - return falseExpr->eval(); -} - -Expression *ConditionalExpression::simplify() const -{ - std::auto_ptr e(condition->simplify()); - NumberExpression * v = freecad_dynamic_cast(e.get()); - - if (v == 0) - return new ConditionalExpression(owner, condition->simplify(), trueExpr->simplify(), falseExpr->simplify()); - else { - if (fabs(v->getValue()) > 0.5) - return trueExpr->simplify(); - else - return falseExpr->simplify(); - } -} - -std::string ConditionalExpression::toString() const -{ - return condition->toString() + " ? " + trueExpr->toString() + " : " + falseExpr->toString(); -} - -Expression *ConditionalExpression::copy() const -{ - return new ConditionalExpression(owner, condition->copy(), trueExpr->copy(), falseExpr->copy()); -} - -int ConditionalExpression::priority() const -{ - return 10; -} - -void ConditionalExpression::getDeps(std::set &props) const -{ - condition->getDeps(props); - trueExpr->getDeps(props); - falseExpr->getDeps(props); -} - -void ConditionalExpression::visit(ExpressionVisitor &v) -{ - condition->visit(v); - trueExpr->visit(v); - falseExpr->visit(v); -} - -TYPESYSTEM_SOURCE(Spreadsheet::ConstantExpression, Spreadsheet::NumberExpression); - -ConstantExpression::ConstantExpression(const App::DocumentObject *_owner, std::string _name, const Quantity & _quantity) - : NumberExpression(_owner, _quantity) - , name(_name) -{ -} - -std::string ConstantExpression::toString() const -{ - return name; -} - -Expression *ConstantExpression::copy() const -{ - return new ConstantExpression(owner, name.c_str(), quantity); -} namespace Spreadsheet { @@ -1694,7 +309,7 @@ double num_change(char* yytext,char dez_delim,char grp_delim) } static Expression * ScanResult = 0; /**< The resulting expression after a successful parsing */ -static const App::DocumentObject * DocumentObject = 0; /**< The DocumentObject that will own the expression */ +static const DocumentObject * DocumentObject = 0; /**< The DocumentObject that will own the expression */ static bool unitExpression = false; /**< True if the parsed string is a unit only */ static bool valueExpression = false; /**< True if the parsed string is a full expression */ static std::stack labels; /**< Label string primitive */ @@ -1756,85 +371,17 @@ static void initParser(const App::DocumentObject *owner) registered_functions["pow"] = FunctionExpression::POW; // Aggregates - registered_functions["sum"] = FunctionExpression::SUM; - registered_functions["count"] = FunctionExpression::COUNT; - registered_functions["average"] = FunctionExpression::AVERAGE; - registered_functions["stddev"] = FunctionExpression::STDDEV; - registered_functions["min"] = FunctionExpression::MIN; - registered_functions["max"] = FunctionExpression::MAX; + registered_functions["sum"] = static_cast(AggregateFunctionExpression::SUM); + registered_functions["count"] = static_cast(AggregateFunctionExpression::COUNT); + registered_functions["average"] = static_cast(AggregateFunctionExpression::AVERAGE); + registered_functions["stddev"] = static_cast(AggregateFunctionExpression::STDDEV); + registered_functions["min"] = static_cast(AggregateFunctionExpression::MIN); + registered_functions["max"] = static_cast(AggregateFunctionExpression::MAX); has_registered_functions = true; } } -} - -std::string Path::String::toString() const -{ - if (isRealString()) - return quote(str); - else - return str; -} - -TYPESYSTEM_SOURCE(Spreadsheet::RangeExpression, Spreadsheet::Expression); - -RangeExpression::RangeExpression(const App::DocumentObject *_owner, const std::string &begin, const std::string &end) - : Expression(_owner) - , range((begin + ":" + end).c_str()) -{ -} - -bool RangeExpression::isTouched() const -{ - Range i(range); - - do { - App::Property * prop = owner->getPropertyByName(i.address().c_str()); - - if (prop && prop->isTouched()) - return true; - } while (i.next()); - - return false; -} - -Expression *RangeExpression::eval() const -{ - throw Exception("Range expression cannot be evaluated"); -} - -std::string RangeExpression::toString() const -{ - return range.rangeString(); -} - -Expression *RangeExpression::copy() const -{ - return new RangeExpression(owner, range.fromCellString(), range.toCellString()); -} - -void RangeExpression::getDeps(std::set &props) const -{ - Range i(range); - - do { - props.insert(Path(owner, i.address())); - } while (i.next()); -} - -Expression *RangeExpression::simplify() const -{ - return copy(); -} - -void RangeExpression::setRange(const Range &r) -{ - range = r; -} - -} - /** * Parse the expression given by \a buffer, and use \a owner as the owner of the * returned expression. If the parser fails for some reason, and exception is thrown. @@ -1846,10 +393,10 @@ void RangeExpression::setRange(const Range &r) * */ -Expression * Spreadsheet::ExpressionParser::parse(const App::DocumentObject *owner, const char* buffer) +Expression * parse(const App::DocumentObject *owner, const char* buffer) { // parse from buffer - ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer); + ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser_scan_string (buffer); initParser(owner); @@ -1874,10 +421,10 @@ Expression * Spreadsheet::ExpressionParser::parse(const App::DocumentObject *own } } -UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, const char* buffer) +UnitExpression * parseUnit(const App::DocumentObject *owner, const char* buffer) { // parse from buffer - ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer); + ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser_scan_string (buffer); initParser(owner); @@ -1912,3 +459,8 @@ UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, c return 0; } } + +} + +} + diff --git a/src/Mod/Spreadsheet/App/SpreadsheetExpression.h b/src/Mod/Spreadsheet/App/SpreadsheetExpression.h index 17b4228c4..a7f0be912 100644 --- a/src/Mod/Spreadsheet/App/SpreadsheetExpression.h +++ b/src/Mod/Spreadsheet/App/SpreadsheetExpression.h @@ -35,318 +35,7 @@ namespace Spreadsheet { -class Expression; - -class SpreadsheetExport ExpressionVisitor { -public: - virtual ~ExpressionVisitor() {} - virtual void visit(Expression * e) = 0; -}; - -class SpreadsheetExport Path { - -public: - - class String { - public: - String(const std::string & s = "", bool _isRealString = false) : str(s), isString(_isRealString) { } - - std::string getString() const { return str; } - - operator std::string() const { return str; } - - operator const char *() const { return str.c_str(); } - - bool operator==(const String & other) const { return str == other.str; } - - bool operator!=(const String & other) const { return str != other.str; } - - bool operator>=(const String & other) const { return str >= other.str; } - - bool operator<(const String & other) const { return str < other.str; } - - bool operator>(const String & other) const { return str > other.str; } - - std::string toString() const; - - bool isRealString() const { return isString; } - - std::string str; - bool isString; - }; - - struct SpreadsheetExport Component { - - enum typeEnum { - SIMPLE, - MAP, - ARRAY - } ; - - std::string component; - typeEnum type; - int index; - String key; - bool keyIsString; - - Component(const std::string & _component, typeEnum _type = SIMPLE, int _index = -1, String _key = String()); - - static Component SimpleComponent(const std::string & _component); - - static Component ArrayComponent(const std::string & _component, int _index); - - static Component MapComponent(const std::string & _component, const String &_key); - - bool operator==(const Component & other) const; - - bool isSimple() const { return type == SIMPLE; } - - bool isMap() const { return type == MAP; } - - bool isArray() const { return type == ARRAY; } - - std::string toString() const; - - }; - - Path(const App::DocumentObject * _owner = 0, const std::string & property = std::string()); - - void addComponent(const Component &c) { components.push_back(c); resolve(); } - - template - void addComponents(const C &cs) { components.insert(components.end(), cs.begin(), cs.end()); resolve(); } - - void setDocumentName(const String & name, bool force = false) { documentName = name; documentNameSet = force; } - - const String getDocumentName() const { return documentName; } - - void setDocumentObjectName(const String & name, bool force = false) { documentObjectName = name; documentObjectNameSet = force; } - - const String getDocumentObjectName() const { return documentObjectName; } - - const std::string & getPropertyName() const { return components[propertyIndex].component; } - - const Component & getPropertyComponent(std::size_t i) const { assert(i < components.size()); return components[propertyIndex + i]; } - - std::string getSubPathStr() const; - - bool operator==(const Path & other) const; - - bool operator!=(const Path & other) const { return !(operator==)(other); } - - bool operator<(const Path &other) const; - - int numComponents() const; - - static Path parse(const App::DocumentObject * _owner, const char * expr); - - virtual std::string toString() const; - - void resolve(); - - void resetResolve(); - - const App::Property *getProperty() const; - - std::string getPythonAccessor() const; - - void renameDocumentObject(const std::string & oldName, const std::string & newName); - - void renameDocument(const std::string &oldName, const std::string &newName); - - App::Document *getDocument() const; - - const App::DocumentObject *getDocumentObject() const; - -protected: - - const App::DocumentObject *getDocumentObject(const App::Document *doc, const std::string &name) const; - - const App::DocumentObject * owner; - mutable int propertyIndex; - String documentName; - bool documentNameSet; - String documentObjectName; - bool documentObjectNameSet; - std::string propertyName; - - std::vector components; -}; - -/** - * Base class for expressions. - * - */ - -class SpreadsheetExport Expression : public Base::BaseClass { - TYPESYSTEM_HEADER(); - -public: - - Expression(const App::DocumentObject * _owner); - - virtual ~Expression(); - - virtual bool isTouched() const { return false; } - - virtual Expression * eval() const = 0; - - virtual std::string toString() const = 0; - - static Expression * parse(const App::DocumentObject * owner, const std::string& buffer); - - virtual Expression * copy() const = 0; - - virtual int priority() const { return 0; } - - virtual void getDeps(std::set &props) const { } - - virtual Expression * simplify() const = 0; - - virtual void visit(ExpressionVisitor & v) { v.visit(this); } - - class Exception : public Base::Exception { - public: - Exception(const char *sMessage) : Base::Exception(sMessage) { } - }; - - const App::DocumentObject * getOwner() const { return owner; } - -protected: - const App::DocumentObject * owner; /**< The document object used to access unqualified variables (i.e local scope) */ -}; - -/** - * Part of an expressions that contains a unit. - * - */ - -class SpreadsheetExport 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() const; - - virtual Expression * copy() const; - - virtual int priority() const { return 20; } - - 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(); } - -protected: - Base::Quantity quantity; - std::string unitStr; /**< The unit string from the original parsed string */ -}; - -/** - * Class implementing a number with an optional unit - */ - -class SpreadsheetExport 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 { return 20; } - - void negate(); - - virtual std::string toString() const; - -protected: -}; - -class SpreadsheetExport 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() const; - - virtual Expression * copy() const; - - virtual int priority() const { return 20; } - - std::string getName() const { return name; } - -protected: - std::string name; /**< Constant's name */ -}; - - -/** - * Class implementing an infix expression. - * - */ - -class SpreadsheetExport OperatorExpression : public UnitExpression { - TYPESYSTEM_HEADER(); -public: - enum Operator { - NONE, - ADD, - SUB, - MUL, - DIV, - 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() const; - - virtual Expression * copy() const; - - virtual int priority() const; - - virtual void getDeps(std::set &props) const; - - virtual void visit(ExpressionVisitor & v); - -protected: - Operator op; /**< Operator working on left and right */ - Expression * left; /**< Left operand */ - Expression * right; /**< Right operand */ -}; - -class SpreadsheetExport RangeExpression : public Expression { +class SpreadsheetExport 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()); @@ -363,9 +52,9 @@ public: virtual int priority() const { return 20; } - virtual void getDeps(std::set &props) const; + virtual void getDeps(std::set &props) const; - virtual Expression * simplify() const; + virtual App::Expression * simplify() const; Range getRange() const { return range; } @@ -375,68 +64,19 @@ protected: Range range; }; -class SpreadsheetExport 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() const; - - virtual Expression * copy() const; - - virtual int priority() const; - - virtual void getDeps(std::set &props) const; - - virtual void visit(ExpressionVisitor & v); - -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 SpreadsheetExport FunctionExpression : public UnitExpression { +class SpreadsheetExport AggregateFunctionExpression : public App::FunctionExpression { 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, - // Aggregates - SUM, + SUM = App::FunctionExpression::LAST, AVERAGE, STDDEV, COUNT, @@ -444,110 +84,21 @@ public: MAX }; - FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, std::vector _args = std::vector()); + AggregateFunctionExpression(const App::DocumentObject *_owner = 0, + App::FunctionExpression::Function _f = App::FunctionExpression::NONE, + std::vector _args = std::vector()); - virtual ~FunctionExpression(); + virtual ~AggregateFunctionExpression(); - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual Expression * simplify() const; + virtual App::Expression * eval() const; virtual std::string toString() const; - - virtual Expression * copy() const; - - virtual int priority() const { return 20; } - - virtual void getDeps(std::set &props) const; - - virtual void visit(ExpressionVisitor & v); - -protected: - 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 SpreadsheetExport VariableExpression : public UnitExpression { - TYPESYSTEM_HEADER(); -public: - VariableExpression(const App::DocumentObject *_owner = 0, Path _var = Path()); - - ~VariableExpression(); - - virtual bool isTouched() const; - - virtual Expression * eval() const; - - virtual Expression * simplify() const; - - virtual std::string toString() const { return var.toString(); } - - virtual Expression * copy() const; - - virtual int priority() const { return 20; } - - virtual void getDeps(std::set &props) const; - - std::string name() const { return var.getPropertyName(); } - - Path getPath() const { return var; } - - void setName(const std::string & name) { assert(0); } - - void resolve(); - - void renameDocumentObject(const std::string & oldName, const std::string & newName); - - void renameDocument(const std::string &oldName, const std::string &newName); - - const App::Property *getProperty() const; - -protected: - - Path var; /**< Variable name */ -}; - -/** - * Class implementing a string. Used to signal either a genuine string or - * a failed evaluation of an expression. - */ - -class SpreadsheetExport 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() const; - - virtual std::string getText() const { return text; } - - virtual int priority() const { return 20; } - - virtual Expression * copy() const; - -protected: - - std::string text; /**< Text string */ }; namespace ExpressionParser { -SpreadsheetExport Expression * parse(const App::DocumentObject *owner, const char *buffer); -SpreadsheetExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer); -SpreadsheetExport Path parsePath(const App::DocumentObject *owner, const char* buffer); +SpreadsheetExport App::Expression * parse(const App::DocumentObject *owner, const char *buffer); +SpreadsheetExport App::UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer); +SpreadsheetExport App::ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer); } } diff --git a/src/Mod/Spreadsheet/App/lex.ExpressionParser.c b/src/Mod/Spreadsheet/App/lex.ExpressionParser.c index 330685ff7..fe2a1a9e9 100644 --- a/src/Mod/Spreadsheet/App/lex.ExpressionParser.c +++ b/src/Mod/Spreadsheet/App/lex.ExpressionParser.c @@ -5607,7 +5607,7 @@ char *ExpressionParsertext; #define strdup _strdup #endif -extern std::stack functions; /**< Function identifier */ +extern std::stack functions; /**< Function identifier */ /*** Flex Declarations and Options ***/ /* change the name of the scanner class. */ @@ -6280,17 +6280,17 @@ yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr case 80: YY_RULE_SETUP #line 242 "ExpressionParser.l" -yylval.fvalue = num_change(ExpressionParsertext,'.',','); return NUM; +yylval.fvalue = num_change(ExpressionParsertext,'.',','); return yylval.fvalue == 1 ? ONE : NUM; YY_BREAK case 81: YY_RULE_SETUP #line 243 "ExpressionParser.l" -yylval.fvalue = num_change(ExpressionParsertext,',','.'); return NUM; +yylval.fvalue = num_change(ExpressionParsertext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; YY_BREAK case 82: YY_RULE_SETUP #line 244 "ExpressionParser.l" -yylval.ivalue = strtoll( ExpressionParsertext, NULL, 0 ); return INTEGER; +yylval.ivalue = strtoll( ExpressionParsertext, NULL, 0 ); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; YY_BREAK case 83: YY_RULE_SETUP @@ -6326,7 +6326,7 @@ YY_RULE_SETUP while (isspace(s[i])) --i; s.erase(i + 1); - std::map::const_iterator j = registered_functions.find(s); + std::map::const_iterator j = registered_functions.find(s); if (j != registered_functions.end()) yylval.func = j->second; else diff --git a/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp b/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp index 8fef8b63a..7955e699e 100644 --- a/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp +++ b/src/Mod/Spreadsheet/Gui/PropertiesDialog.cpp @@ -27,6 +27,7 @@ #include #include "ui_PropertiesDialog.h" +using namespace App; using namespace Spreadsheet; using namespace SpreadsheetGui; @@ -182,7 +183,7 @@ void PropertiesDialog::displayUnitChanged(const QString & text) QPalette palette = ui->displayUnit->palette(); try { - std::auto_ptr e(ExpressionParser::parseUnit(sheet, text.toUtf8().constData())); + std::auto_ptr e(Spreadsheet::ExpressionParser::parseUnit(sheet, text.toUtf8().constData())); displayUnit = DisplayUnit(text.toUtf8().constData(), e->getUnit(), e->getScaler()); palette.setColor(QPalette::Text, Qt::black);