Expressions: Added support for aggregate functions and ranges.

This commit is contained in:
Eivind Kvedalen 2016-03-26 15:46:28 +01:00 committed by wmayer
parent 6c80dd4eae
commit 08692f811b
10 changed files with 1269 additions and 525 deletions

View File

@ -1141,6 +1141,8 @@ void Application::initTypes(void)
App ::StringExpression ::init();
App ::FunctionExpression ::init();
App ::BooleanExpression ::init();
App ::RangeExpression ::init();
}
void Application::initConfig(int argc, char ** argv)

View File

@ -70,6 +70,7 @@ SET(Document_CPP_SRCS
MeasureDistance.cpp
Placement.cpp
Plane.cpp
Range.cpp
Transactions.cpp
VRMLObject.cpp
MaterialObject.cpp
@ -96,6 +97,7 @@ SET(Document_HPP_SRCS
MeasureDistance.h
Placement.h
Plane.h
Range.h
Transactions.h
VRMLObject.h
MaterialObject.h

View File

@ -581,18 +581,50 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
, args(_args)
{
switch (f) {
case NONE:
throw ExpressionError("Unknown function");
case ACOS:
case ASIN:
case ATAN:
case ABS:
case EXP:
case LOG:
case LOG10:
case SIN:
case SINH:
case TAN:
case TANH:
case SQRT:
case COS:
case COSH:
case ROUND:
case TRUNC:
case CEIL:
case FLOOR:
if (args.size() != 1)
throw ExpressionError("Invalid number of arguments: exactly one required.");
break;
case MOD:
case ATAN2:
case POW:
if (args.size() != 2)
throw ExpressionError("Invalid number of arguments.");
throw ExpressionError("Invalid number of arguments: eaxctly two required.");
break;
case STDDEV:
if (args.size() < 2)
throw ExpressionError("Invalid number of arguments: at least two required.");
break;
case SUM:
case AVERAGE:
case COUNT:
case MIN:
case MAX:
if (args.size() == 0)
throw ExpressionError("Invalid number of arguments: at least one required.");
break;
case NONE:
case AGGREGATES:
case LAST:
default:
if (args.size() != 1)
throw ExpressionError("Invalid number of arguments.");
break;
throw ExpressionError("Unknown function");
}
}
@ -625,6 +657,136 @@ bool FunctionExpression::isTouched() const
return false;
}
Expression * FunctionExpression::evalAggregate() const
{
class Collector {
public:
Collector(Function _f)
: f(_f)
, first(true)
, n(0) {
}
void collect(Quantity value) {
if (first) {
q.setUnit(value.getUnit());
mean.setUnit(value.getUnit());
M2.setUnit(value.getUnit());
}
switch (f) {
case AVERAGE:
n++;
case SUM:
q = q + value;
break;
case STDDEV: {
n++;
const Quantity delta = value - mean;
mean = mean + delta / n;
M2 = M2 + delta * (value - mean);
break;
}
case COUNT:
q = q + 1;
break;
case MIN:
if (first || value < q)
q = value;
break;
case MAX:
if (first || value > q)
q = value;
break;
default:
break;
}
first = false;
}
Quantity getQuantity() const {
switch (static_cast<Function>(f)) {
case AVERAGE:
return q / (double)n;
case STDDEV:
if (n < 2)
return Quantity();
else
return (M2 / (n - 1.0)).pow(Quantity(0.5));
default:
break;
}
return q;
}
private:
Function f;
bool first;
int n;
Quantity q;
Quantity mean;
Quantity M2;
};
switch (f) {
case SUM:
case AVERAGE:
case STDDEV:
case COUNT:
case MIN:
case MAX: {
Collector c(f);
for (size_t i = 0; i< args.size(); ++i) {
if (args[i]->isDerivedFrom(RangeExpression::getClassTypeId())) {
RangeExpression * v = static_cast<RangeExpression*>(args[i]);
Range range(v->getRange());
do {
Property * p = owner->getPropertyByName(range.address().c_str());
PropertyQuantity * qp;
PropertyFloat * fp;
if (!p)
continue;
if ((qp = freecad_dynamic_cast<PropertyQuantity>(p)) != 0)
c.collect(qp->getQuantityValue());
else if ((fp = freecad_dynamic_cast<PropertyFloat>(p)) != 0)
c.collect(fp->getValue());
else
throw Exception("Invalid property type for aggregate");
} while (range.next());
}
else if (args[i]->isDerivedFrom(App::VariableExpression::getClassTypeId())) {
std::auto_ptr<Expression> e(args[i]->eval());
NumberExpression * n(freecad_dynamic_cast<NumberExpression>(e.get()));
if (n)
c.collect(n->getQuantity());
}
else if (args[i]->isDerivedFrom(App::NumberExpression::getClassTypeId())) {
c.collect(static_cast<NumberExpression*>(args[i])->getQuantity());
}
}
return new NumberExpression(owner, c.getQuantity());
}
default:
assert(0);
return 0;
}
}
/**
* Evaluate function. Returns a NumberExpression if evaluation is successfuly.
* Throws an ExpressionError exception if something fails.
@ -634,6 +796,10 @@ bool FunctionExpression::isTouched() const
Expression * FunctionExpression::eval() const
{
// Handle aggregate functions
if (f > AGGREGATES)
return evalAggregate();
std::auto_ptr<Expression> e1(args[0]->eval());
std::auto_ptr<Expression> e2(args.size() > 1 ? args[1]->eval() : 0);
NumberExpression * v1 = freecad_dynamic_cast<NumberExpression>(e1.get());
@ -873,49 +1039,69 @@ Expression *FunctionExpression::simplify() const
std::string FunctionExpression::toString() const
{
std::stringstream ss;
for (size_t i = 0; i < args.size(); ++i) {
ss << args[i]->toString();
if (i != args.size() - 1)
ss << "; ";
}
switch (f) {
case ACOS:
return "acos(" + args[0]->toString() + ")";
return "acos(" + ss.str() + ")";
case ASIN:
return "asin(" + args[0]->toString() + ")";
return "asin(" + ss.str() + ")";
case ATAN:
return "atan(" + args[0]->toString() + ")";
return "atan(" + ss.str() + ")";
case ABS:
return "abs(" + args[0]->toString() + ")";
return "abs(" + ss.str() + ")";
case EXP:
return "exp(" + args[0]->toString() + ")";
return "exp(" + ss.str() + ")";
case LOG:
return "log(" + args[0]->toString() + ")";
return "log(" + ss.str() + ")";
case LOG10:
return "log10(" + args[0]->toString() + ")";
return "log10(" + ss.str() + ")";
case SIN:
return "sin(" + args[0]->toString() + ")";
return "sin(" + ss.str() + ")";
case SINH:
return "sinh(" + args[0]->toString() + ")";
return "sinh(" + ss.str() + ")";
case TAN:
return "tan(" + args[0]->toString() + ")";
return "tan(" + ss.str() + ")";
case TANH:
return "tanh(" + args[0]->toString() + ")";
return "tanh(" + ss.str() + ")";
case SQRT:
return "sqrt(" + args[0]->toString() + ")";
return "sqrt(" + ss.str() + ")";
case COS:
return "cos(" + args[0]->toString() + ")";
return "cos(" + ss.str() + ")";
case COSH:
return "cosh(" + args[0]->toString() + ")";
return "cosh(" + ss.str() + ")";
case MOD:
return "mod(" + args[0]->toString() + ", " + args[1]->toString() + ")";
return "mod(" + ss.str() + ")";
case ATAN2:
return "atan2(" + args[0]->toString() + ", " + args[1]->toString() + ")";
return "atan2(" + ss.str() + ")";
case POW:
return "pow(" + args[0]->toString() + ", " + args[1]->toString() + ")";
return "pow(" + ss.str() + ")";
case ROUND:
return "round(" + args[0]->toString() + ")";
return "round(" + ss.str() + ")";
case TRUNC:
return "trunc(" + args[0]->toString() + ")";
return "trunc(" + ss.str() + ")";
case CEIL:
return "ceil(" + args[0]->toString() + ")";
return "ceil(" + ss.str() + ")";
case FLOOR:
return "floor(" + args[0]->toString() + ")";
return "floor(" + ss.str() + ")";
case SUM:
return "sum(" + ss.str() + ")";
case COUNT:
return "count(" + ss.str() + ")";
case AVERAGE:
return "average(" + ss.str() + ")";
case STDDEV:
return "stddev(" + ss.str() + ")";
case MIN:
return "min(" + ss.str() + ")";
case MAX:
return "max(" + ss.str() + ")";
default:
assert(0);
return std::string();
@ -1303,6 +1489,62 @@ Expression *BooleanExpression::copy() const
return new BooleanExpression(owner, getValue() > 0.5 ? true : false);
}
TYPESYSTEM_SOURCE(App::RangeExpression, App::Expression);
RangeExpression::RangeExpression(const 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 {
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<ObjectIdentifier> &props) const
{
Range i(range);
do {
props.insert(ObjectIdentifier(owner, i.address()));
} while (i.next());
}
Expression *RangeExpression::simplify() const
{
return copy();
}
void RangeExpression::setRange(const Range &r)
{
range = r;
}
namespace App {
namespace ExpressionParser {
@ -1311,7 +1553,7 @@ namespace ExpressionParser {
* Error function for parser. Throws a generic Base::Exception with the parser error.
*/
void ExpressionParser_yyerror(char *errorinfo)
void ExpressionParser_yyerror(const char *errorinfo)
{
}
@ -1404,6 +1646,14 @@ static void initParser(const App::DocumentObject *owner)
registered_functions["ceil"] = FunctionExpression::CEIL;
registered_functions["floor"] = FunctionExpression::FLOOR;
// 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;
has_registered_functions = true;
}
}

View File

@ -33,6 +33,7 @@
#include <Base/Quantity.h>
#include <set>
#include <deque>
#include <App/Range.h>
namespace App {
@ -314,6 +315,18 @@ public:
TRUNC,
CEIL,
FLOOR,
// Aggregates
AGGREGATES,
SUM,
AVERAGE,
STDDEV,
COUNT,
MIN,
MAX,
// Last one
LAST,
};
@ -338,6 +351,8 @@ public:
virtual void visit(ExpressionVisitor & v);
protected:
Expression *evalAggregate() const;
Function f; /**< Function to execute */
std::vector<Expression *> args; /** Arguments to function*/
};
@ -419,6 +434,35 @@ protected:
std::string text; /**< Text string */
};
class AppExport RangeExpression : public App::Expression {
TYPESYSTEM_HEADER();
public:
RangeExpression(const App::DocumentObject * _owner = 0, const std::string & begin = std::string(), const std::string & end = std::string());
virtual ~RangeExpression() { }
virtual bool isTouched() const;
virtual Expression * eval() const;
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const { return 20; }
virtual void getDeps(std::set<App::ObjectIdentifier> &props) const;
virtual App::Expression * simplify() const;
Range getRange() const { return range; }
void setRange(const Range & r);
protected:
Range range;
};
namespace ExpressionParser {
AppExport Expression * parse(const App::DocumentObject *owner, const char *buffer);
AppExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer);
@ -446,6 +490,7 @@ public:
double fvalue;
} constant;
std::vector<Expression*> arguments;
std::vector<Expression*> list;
std::string string;
FunctionExpression::Function func;
ObjectIdentifier::String string_or_identifier;

View File

@ -16,7 +16,7 @@ extern std::stack<FunctionExpression::Function> functions; /**< F
extern int last_column;
extern int column;
#define COUNT do { last_column = column; column += yyleng; } while (0)
#define COUNTCHARS do { last_column = column; column += yyleng; } while (0)
%}
@ -141,114 +141,114 @@ EXPO [eE][-+]?[0-9]+
%% /*** Filter language Part ***/
[ \t]+ COUNT;
[ \t]+ COUNTCHARS;
[\n] column = 0;
\<\<(\\(.|\n)|[^\\>\n])*\>\> COUNT; yylval.string = unquote(yytext); return STRING;
\<\<(\\(.|\n)|[^\\>\n])*\>\> COUNTCHARS; yylval.string = unquote(yytext); return STRING;
[+()=/*^,\.\{\}\[\]:;@\?#] COUNT; return *yytext;
[+()=/*^,\.\{\}\[\]:;@\?#] COUNTCHARS; return *yytext;
"==" COUNT; return EQ;
"!=" COUNT; return NEQ;
">" COUNT; return GT;
"<" COUNT; return LT;
">=" COUNT; return GTE;
"<=" COUNT; return LTE;
"==" COUNTCHARS; return EQ;
"!=" COUNTCHARS; return NEQ;
">" COUNTCHARS; return GT;
"<" COUNTCHARS; return LT;
">=" COUNTCHARS; return GTE;
"<=" COUNTCHARS; return LTE;
"-" COUNT; return MINUSSIGN;
"\xe2\x88\x92" COUNT; return MINUSSIGN;
"-" COUNTCHARS; return MINUSSIGN;
"\xe2\x88\x92" COUNTCHARS; return MINUSSIGN;
"nm" COUNT; yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = yytext; return UNIT; // nano meter
"um" COUNT; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter
"\xC2\xB5m" COUNT; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter (greek micro in UTF8)
"mm" COUNT; yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = yytext; return UNIT; // milli meter (internal standard length)
"cm" COUNT; yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = yytext; return UNIT; // centi meter
"dm" COUNT; yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = yytext; return UNIT; // deci meter
"m" COUNT; yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = yytext; return UNIT; // metre
"km" COUNT; yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = yytext; return UNIT; // kilo meter
"nm" COUNTCHARS; yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = yytext; return UNIT; // nano meter
"um" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter
"\xC2\xB5m" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter (greek micro in UTF8)
"mm" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = yytext; return UNIT; // milli meter (internal standard length)
"cm" COUNTCHARS; yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = yytext; return UNIT; // centi meter
"dm" COUNTCHARS; yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = yytext; return UNIT; // deci meter
"m" COUNTCHARS; yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = yytext; return UNIT; // metre
"km" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = yytext; return UNIT; // kilo meter
"l" COUNT; yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = yytext; return UNIT; // Liter dm^3
"l" COUNTCHARS; yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = yytext; return UNIT; // Liter dm^3
"ug" COUNT; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram
"\xC2\xB5g" COUNT; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram
"mg" COUNT; yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = yytext; return UNIT; // milli gram
"g" COUNT; yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = yytext; return UNIT; // gram
"kg" COUNT; yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = yytext; return UNIT; // kilo gram (internal standard for mass)
"t" COUNT; yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = yytext; return UNIT; // Metric Tonne
"ug" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram
"\xC2\xB5g" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram
"mg" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = yytext; return UNIT; // milli gram
"g" COUNTCHARS; yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = yytext; return UNIT; // gram
"kg" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = yytext; return UNIT; // kilo gram (internal standard for mass)
"t" COUNTCHARS; yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = yytext; return UNIT; // Metric Tonne
"s" COUNT; yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = yytext; return UNIT; // second (internal standard time)
"min" COUNT; yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = yytext; return UNIT; // minute
"h" COUNT; yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = yytext; return UNIT; // hour
"s" COUNTCHARS; yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = yytext; return UNIT; // second (internal standard time)
"min" COUNTCHARS; yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = yytext; return UNIT; // minute
"h" COUNTCHARS; yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = yytext; return UNIT; // hour
"A" COUNT; yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = yytext; return UNIT; // Ampere (internal standard electric current)
"mA" COUNT; yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = yytext; return UNIT; // milli Ampere
"kA" COUNT; yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = yytext; return UNIT; // kilo Ampere
"MA" COUNT; yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = yytext; return UNIT; // Mega Ampere
"A" COUNTCHARS; yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = yytext; return UNIT; // Ampere (internal standard electric current)
"mA" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = yytext; return UNIT; // milli Ampere
"kA" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = yytext; return UNIT; // kilo Ampere
"MA" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = yytext; return UNIT; // Mega Ampere
"K" COUNT; yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin (internal standard thermodynamic temperature)
"mK" COUNT; yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin
"\xC2\xB5K" COUNT; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin
"uK" COUNT; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin
"K" COUNTCHARS; yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin (internal standard thermodynamic temperature)
"mK" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin
"\xC2\xB5K" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin
"uK" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin
"mol" COUNT; yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = yytext; return UNIT; // Mole (internal standard amount of substance)
"mol" COUNTCHARS; yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = yytext; return UNIT; // Mole (internal standard amount of substance)
"cd" COUNT; yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = yytext; return UNIT; // Candela (internal standard luminous intensity)
"cd" COUNTCHARS; yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = yytext; return UNIT; // Candela (internal standard luminous intensity)
"in" COUNT; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch
"\"" COUNT; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch
"ft" COUNT; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot
"'" COUNT; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot
"thou" COUNT; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // thou (in/1000)
"mil" COUNT; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // mil (the thou in US)
"yd" COUNT; yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = yytext; return UNIT; // yard
"mi" COUNT; yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = yytext; return UNIT; // mile
"in" COUNTCHARS; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch
"\"" COUNTCHARS; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch
"ft" COUNTCHARS; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot
"'" COUNTCHARS; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot
"thou" COUNTCHARS; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // thou (in/1000)
"mil" COUNTCHARS; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // mil (the thou in US)
"yd" COUNTCHARS; yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = yytext; return UNIT; // yard
"mi" COUNTCHARS; yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = yytext; return UNIT; // mile
"lb" COUNT; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound
"lbm" COUNT; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound
"oz" COUNT; yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = yytext; return UNIT; // ounce
"st" COUNT; yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = yytext; return UNIT; // Stone
"cwt" COUNT; yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = yytext; return UNIT; // hundredweights
"lb" COUNTCHARS; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound
"lbm" COUNTCHARS; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound
"oz" COUNTCHARS; yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = yytext; return UNIT; // ounce
"st" COUNTCHARS; yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = yytext; return UNIT; // Stone
"cwt" COUNTCHARS; yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = yytext; return UNIT; // hundredweights
"lbf" COUNT; yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = yytext; return UNIT; // pound
"lbf" COUNTCHARS; yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = yytext; return UNIT; // pound
"N" COUNT; yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = yytext; return UNIT; // Newton (kg*m/s^2)a-za-za-z
"kN" COUNT; yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton
"MN" COUNT; yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton
"mN" COUNT; yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton
"N" COUNTCHARS; yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = yytext; return UNIT; // Newton (kg*m/s^2)a-za-za-z
"kN" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton
"MN" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton
"mN" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = yytext; return UNIT; // Newton
"Pa" COUNT; yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal (kg/m*s^2 or N/m^2)
"kPa" COUNT; yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal
"MPa" COUNT; yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal
"GPa" COUNT; yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal
"Pa" COUNTCHARS; yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal (kg/m*s^2 or N/m^2)
"kPa" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal
"MPa" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal
"GPa" COUNTCHARS; yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal
"Torr" COUNT; yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = yytext; return UNIT; // portion of Pascal ( 101325/760 )
"mTorr" COUNT; yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = yytext; return UNIT; //
"uTorr" COUNT; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; //
"\xC2\xB5Torr" COUNT; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; //
"Torr" COUNTCHARS; yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = yytext; return UNIT; // portion of Pascal ( 101325/760 )
"mTorr" COUNTCHARS; yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = yytext; return UNIT; //
"uTorr" COUNTCHARS; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; //
"\xC2\xB5Torr" COUNTCHARS; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; //
"psi" COUNT; yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = yytext; return UNIT; // pounds/in^2
"ksi" COUNT; yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = yytext; return UNIT; // 1000 x pounds/in^2
"psi" COUNTCHARS; yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = yytext; return UNIT; // pounds/in^2
"ksi" COUNTCHARS; yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = yytext; return UNIT; // 1000 x pounds/in^2
"W" COUNT; yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = yytext; return UNIT; // Watt (kg*m^2/s^3)
"VA" COUNT; yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = yytext; return UNIT; // VoltAmpere (kg*m^2/s^3)
"W" COUNTCHARS; yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = yytext; return UNIT; // Watt (kg*m^2/s^3)
"VA" COUNTCHARS; yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = yytext; return UNIT; // VoltAmpere (kg*m^2/s^3)
"J" COUNT; yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = yytext; return UNIT; // Joule (kg*m^2/s^2)
"Nm" COUNT; yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = yytext; return UNIT; // N*m = Joule
"VAs" COUNT; yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = yytext; return UNIT; // V*A*s = Joule
"CV" COUNT; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; //
"Ws" COUNT; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; // W*s = Joule
"J" COUNTCHARS; yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = yytext; return UNIT; // Joule (kg*m^2/s^2)
"Nm" COUNTCHARS; yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = yytext; return UNIT; // N*m = Joule
"VAs" COUNTCHARS; yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = yytext; return UNIT; // V*A*s = Joule
"CV" COUNTCHARS; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; //
"Ws" COUNTCHARS; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; // W*s = Joule
"\xC2\xB0" COUNT; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle)
"deg" COUNT; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle)
"rad" COUNT; yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = yytext; return UNIT; // radian
"gon" COUNT; yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = yytext; return UNIT; // gon
"\xC2\xB0" COUNTCHARS; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle)
"deg" COUNTCHARS; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle)
"rad" COUNTCHARS; yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = yytext; return UNIT; // radian
"gon" COUNTCHARS; yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = yytext; return UNIT; // gon
{DIGIT}*"."{DIGIT}+{EXPO}? COUNT; yylval.fvalue = num_change(yytext,'.',','); return yylval.fvalue == 1 ? ONE : NUM;
{DIGIT}*","{DIGIT}+{EXPO}? COUNT; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
{DIGIT}+{EXPO} COUNT; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
{DIGIT}+ { COUNT;
{DIGIT}*"."{DIGIT}+{EXPO}? COUNTCHARS; yylval.fvalue = num_change(yytext,'.',','); return yylval.fvalue == 1 ? ONE : NUM;
{DIGIT}*","{DIGIT}+{EXPO}? COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
{DIGIT}+{EXPO} COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
{DIGIT}+ { COUNTCHARS;
yylval.ivalue = strtoll( yytext, NULL, 0 );
if (yylval.ivalue == LLONG_MIN)
throw Base::Exception("Integer underflow");
@ -257,15 +257,15 @@ EXPO [eE][-+]?[0-9]+
if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER;
}
"pi" COUNT; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi
"e" COUNT; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e
"pi" COUNTCHARS; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi
"e" COUNTCHARS; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e
$[A-Za-z]{1,2}+${DIGIT}+ COUNT; yylval.string = yytext; return CELLADDRESS;
[A-Za-z]{1,2}${DIGIT}+ COUNT; yylval.string = yytext; return CELLADDRESS;
$[A-Za-z]{1,2}{DIGIT}+ COUNT; yylval.string = yytext; return CELLADDRESS;
$[A-Za-z]{1,2}+${DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDRESS;
[A-Za-z]{1,2}${DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDRESS;
$[A-Za-z]{1,2}{DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDRESS;
({L}{M}*)({L}{M}*|{N}|_)*[\20\t]*\( {
COUNT;
COUNTCHARS;
std::string s = yytext;
size_t i = s.size() - 2;
while (isspace(s[i]))
@ -279,4 +279,4 @@ $[A-Za-z]{1,2}{DIGIT}+ COUNT; yylval.string = yytext; return CELLADDRESS;
return FUNC;
}
({L}{M}*)({L}{M}*|{N}|_)* COUNT; yylval.string = yytext; return IDENTIFIER;
({L}{M}*)({L}{M}*|{N}|_)* COUNTCHARS; yylval.string = yytext; return IDENTIFIER;

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
%{
#define YYSTYPE semantic_type
#define YYSTYPE App::ExpressionParser::semantic_type
std::stack<FunctionExpression::Function> functions; /**< Function identifier */
@ -39,6 +39,7 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%type <constant> CONSTANT
%type <expr> num
%type <expr> basic_num
%type <expr> range
%type <path> identifier
%type <components> path subpath
%type <func> FUNC
@ -97,8 +98,17 @@ num: basic_num { $$ = $1; }
;
args: exp { $$.push_back($1); }
| range { $$.push_back($1); }
| args ',' exp { $1.push_back($3); $$ = $1; }
| args ';' exp { $1.push_back($3); $$ = $1; }
| args ',' range { $1.push_back($3); $$ = $1; }
| args ';' range { $1.push_back($3); $$ = $1; }
;
range: CELLADDRESS ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
| CELLADDRESS ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
| IDENTIFIER ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
| IDENTIFIER ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
;
cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }

244
src/App/Range.cpp Normal file
View File

@ -0,0 +1,244 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#include "Range.h"
#include <Base/Exception.h>
#include <assert.h>
#include <string.h>
#include <boost/regex.hpp>
using namespace App;
const int App::CellAddress::MAX_ROWS = 16384;
const int App::CellAddress::MAX_COLUMNS = 26 * 26 + 26;
Range::Range(const char * range)
{
std::string from;
std::string to;
assert(range != NULL);
if (strchr(range, ':') == NULL) {
from = range;
to = range;
}
else {
std::string s = range;
from = s.substr(0, s.find(':'));
to = s.substr(s.find(':') + 1);
}
CellAddress begin(from);
CellAddress end(to);
row_begin = begin.row();
col_begin = begin.col();
row_end = end.row();
col_end = end.col();
row_curr = row_begin;
col_curr = col_begin;
}
Range::Range(int _row_begin, int _col_begin, int _row_end, int _col_end)
: row_curr(_row_begin)
, col_curr(_col_begin)
, row_begin(_row_begin)
, col_begin(_col_begin)
, row_end(_row_end)
, col_end(_col_end)
{
}
Range::Range(const CellAddress &from, const CellAddress &to)
: row_curr(from.row())
, col_curr(from.col())
, row_begin(from.row())
, col_begin(from.col())
, row_end(to.row())
, col_end(to.col())
{
}
bool Range::next()
{
if (row_curr < row_end) {
row_curr++;
return true;
}
if (col_curr < col_end) {
if (row_curr == row_end + 1)
return false;
row_curr = row_begin;
++col_curr;
return true;
}
return false;
}
/**
* Decode a row specification into a 0-based integer.
*
* @param rowstr Row specified as a string, with "1" being the first row.
*
* @returns The row.
*/
int App::decodeRow(const std::string &rowstr)
{
int row = validRow(rowstr);
if (row >= 0)
return row;
else
throw Base::Exception("Invalid row specification.");
}
/**
* Decode a column specification into a 0-based integer.
*
* @param colstr Column specified as a string, with "A" begin the first column.
*
* @returns The column.
*
*/
int App::decodeColumn(const std::string &colstr)
{
int col = validColumn(colstr);
if (col >= 0)
return col;
else
throw Base::Exception("Invalid column specification");
}
/**
* Determine wheter a row specification is valid or not.
*
* @param rowstr Row specified as a string, with "1" being the first row.
*
* @returns 0 or positive on success, -1 on error.
*/
int App::validRow(const std::string &rowstr)
{
char * end;
int i = strtol(rowstr.c_str(), &end, 10);
if (i <0 || i >= CellAddress::MAX_ROWS || *end)
return -1;
return i - 1;
}
/**
* Determine whether a column specification is valid or not.
*
* @param colstr Column specified as a string, with "A" begin the first column.
*
* @returns 0 or positive on success, -1 on error.
*
*/
int App::validColumn(const std::string &colstr)
{
int col = 0;
if (colstr.length() == 1) {
if ((colstr[0] >= 'A' && colstr[0] <= 'Z'))
col = colstr[0] - 'A';
else
return -1;
}
else {
col = 0;
for (std::string::const_reverse_iterator i = colstr.rbegin(); i != colstr.rend(); ++i) {
int v;
if ((*i >= 'A' && *i <= 'Z'))
v = *i - 'A';
else
return -1;
col = col * 26 + v;
}
col += 26;
}
return col;
}
/**
* Convert a string address into integer \a row and \a column.
* row and col are 0-based.
*
* This function will throw an exception if the specified \a address is invalid.
*
* @param address Address to parse.
* @param row Reference to integer where row position is stored.
* @param col Reference to integer where col position is stored.
*
*/
App::CellAddress App::stringToAddress(const char * strAddress)
{
static const boost::regex e("\\${0,1}([A-Z]{1,2})\\${0,1}([0-9]{1,5})");
boost::cmatch cm;
assert(strAddress != 0);
if (boost::regex_match(strAddress, cm, e)) {
const boost::sub_match<const char *> colstr = cm[1];
const boost::sub_match<const char *> rowstr = cm[2];
return CellAddress(decodeRow(rowstr.str()), decodeColumn(colstr.str()));
}
else
throw Base::Exception("Invalid cell specifier.");
}
/**
* Convert given \a cell address into its string representation.
*
* @returns Address given as a string.
*/
std::string App::CellAddress::toString() const
{
std::stringstream s;
if (col() < 26)
s << (char)('A' + col());
else {
int colnum = col() - 26;
s << (char)('A' + (colnum / 26));
s << (char)('A' + (colnum % 26));
}
s << (row() + 1);
return s.str();
}

139
src/App/Range.h Normal file
View File

@ -0,0 +1,139 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef RANGE_H
#define RANGE_H
#include <string>
namespace App {
struct CellAddress;
AppExport CellAddress stringToAddress(const char *strAddress);
AppExport int decodeColumn(const std::string &colstr);
AppExport int decodeRow(const std::string &rowstr);
AppExport int validColumn(const std::string &colstr);
AppExport int validRow(const std::string &rowstr);
struct AppExport CellAddress {
CellAddress(int row = -1, int col = -1) : _row(row), _col(col) { }
CellAddress(const char * address) {
*this = stringToAddress(address);
}
CellAddress(const std::string & address) {
*this = stringToAddress(address.c_str());
}
inline int row() const { return _row; }
inline int col() const { return _col; }
inline bool operator<(const CellAddress & other) const { return asInt() < other.asInt(); }
inline bool operator==(const CellAddress & other) const { return asInt() == other.asInt(); }
inline bool operator!=(const CellAddress & other) const { return asInt() != other.asInt(); }
inline bool isValid() { return (row() >=0 && row() < MAX_ROWS && col() >= 0 && col() < MAX_COLUMNS); }
std::string toString() const;
// Static members
static const int MAX_ROWS;
static const int MAX_COLUMNS;
protected:
inline unsigned int asInt() const { return ((_row << 16) | _col); }
short _row;
short _col;
};
/**
* @brief The Range class is a spreadsheet range iterator. It takes
* a starting (row, col) and an ending (row, col). Notice that ranges
* are always at least one element. The next() functions is therefore
* used e.g as follows:
*
* do {
* ...
* while (range.next());
*
*/
class AppExport Range {
public:
Range(const char *range);
Range(int _row_begin, int _col_begin, int _row_end, int _col_end);
Range(const CellAddress & from, const CellAddress & to);
bool next();
/** Current row */
inline int row() const { return row_curr; }
/** Current column */
inline int column() const { return col_curr; }
/** Position of start of range */
inline CellAddress from() const { return CellAddress(row_begin, col_begin); }
/** Position of end of range */
inline CellAddress to() const { return CellAddress(row_end, col_end); }
/** Start of range as a string */
inline std::string fromCellString() const { return CellAddress(row_begin, col_begin).toString(); }
/** End of range as a string */
inline std::string toCellString() const { return CellAddress(row_end, col_end).toString(); }
/** Current cell as a string */
inline std::string address() const { return CellAddress(row_curr, col_curr).toString(); }
/** The raneg as a string */
inline std::string rangeString() const {
return CellAddress(row_begin, col_begin).toString() + ":" + CellAddress(row_end, col_end).toString();
}
CellAddress operator*() const { return CellAddress(row_curr, col_curr); }
/** Number of elements in range */
inline int size() const { return (row_end - row_begin + 1) * (col_end - col_begin + 1); }
private:
int row_curr, col_curr;
int row_begin, col_begin;
int row_end, col_end;
};
}
#endif // RANGE_H

View File

@ -5615,7 +5615,7 @@ extern std::stack<FunctionExpression::Function> functions; /**< F
extern int last_column;
extern int column;
#define COUNT do { last_column = column; column += ExpressionParserleng; } while (0)
#define COUNTCHARS do { last_column = column; column += ExpressionParserleng; } while (0)
/*** Flex Declarations and Options ***/
/* change the name of the scanner class. */
@ -5892,7 +5892,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
#line 144 "ExpressionParser.l"
COUNT;
COUNTCHARS;
YY_BREAK
case 2:
/* rule 2 can match eol */
@ -5904,407 +5904,407 @@ case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
#line 147 "ExpressionParser.l"
COUNT; yylval.string = unquote(ExpressionParsertext); return STRING;
COUNTCHARS; yylval.string = unquote(ExpressionParsertext); return STRING;
YY_BREAK
case 4:
YY_RULE_SETUP
#line 149 "ExpressionParser.l"
COUNT; return *ExpressionParsertext;
COUNTCHARS; return *ExpressionParsertext;
YY_BREAK
case 5:
YY_RULE_SETUP
#line 151 "ExpressionParser.l"
COUNT; return EQ;
COUNTCHARS; return EQ;
YY_BREAK
case 6:
YY_RULE_SETUP
#line 152 "ExpressionParser.l"
COUNT; return NEQ;
COUNTCHARS; return NEQ;
YY_BREAK
case 7:
YY_RULE_SETUP
#line 153 "ExpressionParser.l"
COUNT; return GT;
COUNTCHARS; return GT;
YY_BREAK
case 8:
YY_RULE_SETUP
#line 154 "ExpressionParser.l"
COUNT; return LT;
COUNTCHARS; return LT;
YY_BREAK
case 9:
YY_RULE_SETUP
#line 155 "ExpressionParser.l"
COUNT; return GTE;
COUNTCHARS; return GTE;
YY_BREAK
case 10:
YY_RULE_SETUP
#line 156 "ExpressionParser.l"
COUNT; return LTE;
COUNTCHARS; return LTE;
YY_BREAK
case 11:
YY_RULE_SETUP
#line 158 "ExpressionParser.l"
COUNT; return MINUSSIGN;
COUNTCHARS; return MINUSSIGN;
YY_BREAK
case 12:
YY_RULE_SETUP
#line 159 "ExpressionParser.l"
COUNT; return MINUSSIGN;
COUNTCHARS; return MINUSSIGN;
YY_BREAK
case 13:
YY_RULE_SETUP
#line 161 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // nano meter
COUNTCHARS; yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // nano meter
YY_BREAK
case 14:
YY_RULE_SETUP
#line 162 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro meter
COUNTCHARS; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro meter
YY_BREAK
case 15:
YY_RULE_SETUP
#line 163 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro meter (greek micro in UTF8)
COUNTCHARS; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro meter (greek micro in UTF8)
YY_BREAK
case 16:
YY_RULE_SETUP
#line 164 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli meter (internal standard length)
COUNTCHARS; yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli meter (internal standard length)
YY_BREAK
case 17:
YY_RULE_SETUP
#line 165 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // centi meter
COUNTCHARS; yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // centi meter
YY_BREAK
case 18:
YY_RULE_SETUP
#line 166 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // deci meter
COUNTCHARS; yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // deci meter
YY_BREAK
case 19:
YY_RULE_SETUP
#line 167 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // metre
COUNTCHARS; yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // metre
YY_BREAK
case 20:
YY_RULE_SETUP
#line 168 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo meter
COUNTCHARS; yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo meter
YY_BREAK
case 21:
YY_RULE_SETUP
#line 170 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Liter dm^3
COUNTCHARS; yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Liter dm^3
YY_BREAK
case 22:
YY_RULE_SETUP
#line 172 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro gram
COUNTCHARS; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro gram
YY_BREAK
case 23:
YY_RULE_SETUP
#line 173 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro gram
COUNTCHARS; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // micro gram
YY_BREAK
case 24:
YY_RULE_SETUP
#line 174 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli gram
COUNTCHARS; yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli gram
YY_BREAK
case 25:
YY_RULE_SETUP
#line 175 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // gram
COUNTCHARS; yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // gram
YY_BREAK
case 26:
YY_RULE_SETUP
#line 176 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo gram (internal standard for mass)
COUNTCHARS; yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo gram (internal standard for mass)
YY_BREAK
case 27:
YY_RULE_SETUP
#line 177 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Metric Tonne
COUNTCHARS; yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Metric Tonne
YY_BREAK
case 28:
YY_RULE_SETUP
#line 179 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // second (internal standard time)
COUNTCHARS; yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // second (internal standard time)
YY_BREAK
case 29:
YY_RULE_SETUP
#line 180 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // minute
COUNTCHARS; yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // minute
YY_BREAK
case 30:
YY_RULE_SETUP
#line 181 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // hour
COUNTCHARS; yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // hour
YY_BREAK
case 31:
YY_RULE_SETUP
#line 183 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Ampere (internal standard electric current)
COUNTCHARS; yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Ampere (internal standard electric current)
YY_BREAK
case 32:
YY_RULE_SETUP
#line 184 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli Ampere
COUNTCHARS; yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // milli Ampere
YY_BREAK
case 33:
YY_RULE_SETUP
#line 185 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo Ampere
COUNTCHARS; yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // kilo Ampere
YY_BREAK
case 34:
YY_RULE_SETUP
#line 186 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Mega Ampere
COUNTCHARS; yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Mega Ampere
YY_BREAK
case 35:
YY_RULE_SETUP
#line 188 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin (internal standard thermodynamic temperature)
COUNTCHARS; yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin (internal standard thermodynamic temperature)
YY_BREAK
case 36:
YY_RULE_SETUP
#line 189 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin
COUNTCHARS; yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin
YY_BREAK
case 37:
YY_RULE_SETUP
#line 190 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin
COUNTCHARS; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin
YY_BREAK
case 38:
YY_RULE_SETUP
#line 191 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin
COUNTCHARS; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Kelvin
YY_BREAK
case 39:
YY_RULE_SETUP
#line 193 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Mole (internal standard amount of substance)
COUNTCHARS; yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Mole (internal standard amount of substance)
YY_BREAK
case 40:
YY_RULE_SETUP
#line 195 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Candela (internal standard luminous intensity)
COUNTCHARS; yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Candela (internal standard luminous intensity)
YY_BREAK
case 41:
YY_RULE_SETUP
#line 197 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // inch
COUNTCHARS; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // inch
YY_BREAK
case 42:
YY_RULE_SETUP
#line 198 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // inch
COUNTCHARS; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // inch
YY_BREAK
case 43:
YY_RULE_SETUP
#line 199 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // foot
COUNTCHARS; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // foot
YY_BREAK
case 44:
YY_RULE_SETUP
#line 200 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // foot
COUNTCHARS; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // foot
YY_BREAK
case 45:
YY_RULE_SETUP
#line 201 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // thou (in/1000)
COUNTCHARS; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // thou (in/1000)
YY_BREAK
case 46:
YY_RULE_SETUP
#line 202 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // mil (the thou in US)
COUNTCHARS; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // mil (the thou in US)
YY_BREAK
case 47:
YY_RULE_SETUP
#line 203 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // yard
COUNTCHARS; yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // yard
YY_BREAK
case 48:
YY_RULE_SETUP
#line 204 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // mile
COUNTCHARS; yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // mile
YY_BREAK
case 49:
YY_RULE_SETUP
#line 208 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound
COUNTCHARS; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound
YY_BREAK
case 50:
YY_RULE_SETUP
#line 209 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound
COUNTCHARS; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound
YY_BREAK
case 51:
YY_RULE_SETUP
#line 210 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // ounce
COUNTCHARS; yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // ounce
YY_BREAK
case 52:
YY_RULE_SETUP
#line 211 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Stone
COUNTCHARS; yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Stone
YY_BREAK
case 53:
YY_RULE_SETUP
#line 212 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // hundredweights
COUNTCHARS; yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // hundredweights
YY_BREAK
case 54:
YY_RULE_SETUP
#line 214 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound
COUNTCHARS; yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pound
YY_BREAK
case 55:
YY_RULE_SETUP
#line 216 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton (kg*m/s^2)a-za-za-z
COUNTCHARS; yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton (kg*m/s^2)a-za-za-z
YY_BREAK
case 56:
YY_RULE_SETUP
#line 217 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton
COUNTCHARS; yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton
YY_BREAK
case 57:
YY_RULE_SETUP
#line 218 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton
COUNTCHARS; yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton
YY_BREAK
case 58:
YY_RULE_SETUP
#line 219 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton
COUNTCHARS; yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Newton
YY_BREAK
case 59:
YY_RULE_SETUP
#line 221 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal (kg/m*s^2 or N/m^2)
COUNTCHARS; yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal (kg/m*s^2 or N/m^2)
YY_BREAK
case 60:
YY_RULE_SETUP
#line 222 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal
COUNTCHARS; yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal
YY_BREAK
case 61:
YY_RULE_SETUP
#line 223 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal
COUNTCHARS; yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal
YY_BREAK
case 62:
YY_RULE_SETUP
#line 224 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal
COUNTCHARS; yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Pascal
YY_BREAK
case 63:
YY_RULE_SETUP
#line 226 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // portion of Pascal ( 101325/760 )
COUNTCHARS; yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // portion of Pascal ( 101325/760 )
YY_BREAK
case 64:
YY_RULE_SETUP
#line 227 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
COUNTCHARS; yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
YY_BREAK
case 65:
YY_RULE_SETUP
#line 228 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
COUNTCHARS; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
YY_BREAK
case 66:
YY_RULE_SETUP
#line 229 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
COUNTCHARS; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
YY_BREAK
case 67:
YY_RULE_SETUP
#line 231 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pounds/in^2
COUNTCHARS; yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // pounds/in^2
YY_BREAK
case 68:
YY_RULE_SETUP
#line 232 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // 1000 x pounds/in^2
COUNTCHARS; yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // 1000 x pounds/in^2
YY_BREAK
case 69:
YY_RULE_SETUP
#line 234 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Watt (kg*m^2/s^3)
COUNTCHARS; yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Watt (kg*m^2/s^3)
YY_BREAK
case 70:
YY_RULE_SETUP
#line 235 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // VoltAmpere (kg*m^2/s^3)
COUNTCHARS; yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // VoltAmpere (kg*m^2/s^3)
YY_BREAK
case 71:
YY_RULE_SETUP
#line 237 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Joule (kg*m^2/s^2)
COUNTCHARS; yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // Joule (kg*m^2/s^2)
YY_BREAK
case 72:
YY_RULE_SETUP
#line 238 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // N*m = Joule
COUNTCHARS; yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // N*m = Joule
YY_BREAK
case 73:
YY_RULE_SETUP
#line 239 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // V*A*s = Joule
COUNTCHARS; yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // V*A*s = Joule
YY_BREAK
case 74:
YY_RULE_SETUP
#line 240 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
COUNTCHARS; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; //
YY_BREAK
case 75:
YY_RULE_SETUP
#line 241 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // W*s = Joule
COUNTCHARS; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // W*s = Joule
YY_BREAK
case 76:
YY_RULE_SETUP
#line 243 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // degree (internal standard angle)
COUNTCHARS; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // degree (internal standard angle)
YY_BREAK
case 77:
YY_RULE_SETUP
#line 244 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // degree (internal standard angle)
COUNTCHARS; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // degree (internal standard angle)
YY_BREAK
case 78:
YY_RULE_SETUP
#line 245 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // radian
COUNTCHARS; yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // radian
YY_BREAK
case 79:
YY_RULE_SETUP
#line 246 "ExpressionParser.l"
COUNT; yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // gon
COUNTCHARS; yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = ExpressionParsertext; return UNIT; // gon
YY_BREAK
case 80:
YY_RULE_SETUP
#line 248 "ExpressionParser.l"
COUNT; yylval.fvalue = num_change(ExpressionParsertext,'.',','); return yylval.fvalue == 1 ? ONE : NUM;
COUNTCHARS; yylval.fvalue = num_change(ExpressionParsertext,'.',','); return yylval.fvalue == 1 ? ONE : NUM;
YY_BREAK
case 81:
YY_RULE_SETUP
#line 249 "ExpressionParser.l"
COUNT; yylval.fvalue = num_change(ExpressionParsertext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
COUNTCHARS; yylval.fvalue = num_change(ExpressionParsertext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
YY_BREAK
case 82:
YY_RULE_SETUP
#line 250 "ExpressionParser.l"
COUNT; yylval.fvalue = num_change(ExpressionParsertext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
COUNTCHARS; yylval.fvalue = num_change(ExpressionParsertext,',','.'); return yylval.fvalue == 1 ? ONE : NUM;
YY_BREAK
case 83:
YY_RULE_SETUP
#line 251 "ExpressionParser.l"
{ COUNT;
{ COUNTCHARS;
yylval.ivalue = strtoll( ExpressionParsertext, NULL, 0 );
if (yylval.ivalue == LLONG_MIN)
throw Base::Exception("Integer underflow");
@ -6316,33 +6316,33 @@ YY_RULE_SETUP
case 84:
YY_RULE_SETUP
#line 260 "ExpressionParser.l"
COUNT; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi
COUNTCHARS; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi
YY_BREAK
case 85:
YY_RULE_SETUP
#line 261 "ExpressionParser.l"
COUNT; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e
COUNTCHARS; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e
YY_BREAK
case 86:
YY_RULE_SETUP
#line 263 "ExpressionParser.l"
COUNT; yylval.string = ExpressionParsertext; return CELLADDRESS;
COUNTCHARS; yylval.string = ExpressionParsertext; return CELLADDRESS;
YY_BREAK
case 87:
YY_RULE_SETUP
#line 264 "ExpressionParser.l"
COUNT; yylval.string = ExpressionParsertext; return CELLADDRESS;
COUNTCHARS; yylval.string = ExpressionParsertext; return CELLADDRESS;
YY_BREAK
case 88:
YY_RULE_SETUP
#line 265 "ExpressionParser.l"
COUNT; yylval.string = ExpressionParsertext; return CELLADDRESS;
COUNTCHARS; yylval.string = ExpressionParsertext; return CELLADDRESS;
YY_BREAK
case 89:
YY_RULE_SETUP
#line 267 "ExpressionParser.l"
{
COUNT;
COUNTCHARS;
std::string s = ExpressionParsertext;
size_t i = s.size() - 2;
while (isspace(s[i]))
@ -6359,7 +6359,7 @@ YY_RULE_SETUP
case 90:
YY_RULE_SETUP
#line 282 "ExpressionParser.l"
COUNT; yylval.string = ExpressionParsertext; return IDENTIFIER;
COUNTCHARS; yylval.string = ExpressionParsertext; return IDENTIFIER;
YY_BREAK
case 91:
YY_RULE_SETUP