first finished implementation of Quantity parser
This commit is contained in:
parent
4db2355159
commit
3ee7b20927
|
@ -1,2 +1,2 @@
|
|||
C:\Tools\GnuWin32\bin\flex.exe -oQuantityLexer.c QuantityParser.l
|
||||
C:\Tools\GnuWin32\bin\bison -oQuantityParser.c QuantityParser.y
|
||||
C:\cygwin\bin\flex.exe -oQuantityLexer.c QuantityParser.l
|
||||
C:\cygwin\bin\bison -oQuantityParser.c QuantityParser.y
|
2
src/Base/Parser.sh
Normal file
2
src/Base/Parser.sh
Normal file
|
@ -0,0 +1,2 @@
|
|||
flex -oQuantityLexer.c QuantityParser.l
|
||||
bison -oQuantityParser.c QuantityParser.y
|
|
@ -127,6 +127,7 @@ void Quantity_yyerror(char *errorinfo)
|
|||
|
||||
namespace QuantityParser {
|
||||
|
||||
#define YYINITDEPTH 20
|
||||
// show the parser the lexer method
|
||||
#define yylex QuantityLexer
|
||||
int QuantityLexer(void);
|
||||
|
|
|
@ -55,6 +55,9 @@ public:
|
|||
|
||||
static Quantity parse(const char* buffer);
|
||||
|
||||
const Unit & getUnit(void) const{return _Unit;}
|
||||
double getValue(void) const{return _Value;}
|
||||
|
||||
protected:
|
||||
double _Value;
|
||||
Unit _Unit;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -32,54 +32,78 @@ ID [a-z][a-z0-9]*
|
|||
|
||||
[-+()=/*^] { return *yytext; }
|
||||
|
||||
"mm" yylval = 1.0; return UNIT; // millimeter (internal standard length)
|
||||
"m" yylval = 1000.0; return UNIT; // meter
|
||||
"cm" yylval = 10.0; return UNIT; // centimeter
|
||||
"dm" yylval = 100.0; return UNIT; // decimeter
|
||||
"km" yylval = 1000000.0; return UNIT; // kilometer
|
||||
"nm" yylval = Quantity(1.0e-6 ,Unit(1)); return UNIT; // nano meter
|
||||
"ym" yylval = Quantity(1.0e-3 ,Unit(1)); return UNIT; // micro meter
|
||||
"mm" yylval = Quantity(1.0 ,Unit(1)); return UNIT; // milli meter
|
||||
"cm" yylval = Quantity(10.0 ,Unit(1)); return UNIT; // centi meter
|
||||
"dm" yylval = Quantity(100.0 ,Unit(1)); return UNIT; // deci meter
|
||||
"m" yylval = Quantity(1.0e3 ,Unit(1)); return UNIT; // meter
|
||||
"km" yylval = Quantity(1.0e6 ,Unit(1)); return UNIT; // kilo meter
|
||||
"l" yylval = Quantity(1000000.0 ,Unit(3)); return UNIT; // Liter dm^3
|
||||
|
||||
"in" yylval = 25.4; return UNIT; // inch
|
||||
"\"" yylval = 25.4; return UNIT; // inch
|
||||
"fo" yylval = 304.8; return UNIT; // foot
|
||||
"'" yylval = 304.8; return UNIT; // foot
|
||||
"th" yylval = 0.0254; return UNIT; // thou
|
||||
"yr" yylval = 914.4; return UNIT; // yard
|
||||
"yg" yylval = Quantity(1.0e-9 ,Unit(0,1)); return UNIT; // milli gram
|
||||
"mg" yylval = Quantity(1.0e-6 ,Unit(0,1)); return UNIT; // milli gram
|
||||
"g" yylval = Quantity(1.0e-3 ,Unit(0,1)); return UNIT; // gram
|
||||
"kg" yylval = Quantity(1.0 ,Unit(0,1)); return UNIT; // kilo gram
|
||||
"t" yylval = Quantity(1000.0 ,Unit(0,1)); return UNIT; // ton
|
||||
|
||||
"kg" yylval = 1.0; return UNIT; // kilogram (internal standard mass)
|
||||
"g" yylval = 0.001; return UNIT; // gram
|
||||
"mg" yylval = 0.000001; return UNIT; // milligram
|
||||
"t" yylval = 1000.0; return UNIT; // ton
|
||||
"s" yylval = Quantity(1.0 ,Unit(0,0,1)); return UNIT; // second (internal standard time)
|
||||
"min" yylval = Quantity(60.0 ,Unit(0,0,1)); return UNIT; // minute
|
||||
"h" yylval = Quantity(3600.0 ,Unit(0,0,1)); return UNIT; // hour
|
||||
|
||||
"lb" yylval = 0.45359237; return UNIT; // pound
|
||||
"oz" yylval = 0.45359237; return UNIT; // ounce
|
||||
"st" yylval = 6.35029318; return UNIT; // Stone
|
||||
"cwt" yylval = 50.80234544;return UNIT; // hundredweights
|
||||
"A" yylval = Quantity(1.0 ,Unit(0,0,0,1)); return UNIT; // Ampere (internal standard electric current)
|
||||
"mA" yylval = Quantity(0.001 ,Unit(0,0,0,1)); return UNIT; // milli Ampere
|
||||
"kA" yylval = Quantity(1000.0 ,Unit(0,0,0,1)); return UNIT; // kilo Ampere
|
||||
"MA" yylval = Quantity(1.0e6 ,Unit(0,0,0,1)); return UNIT; // Mega Ampere
|
||||
|
||||
"deg" yylval = 1.0; return UNIT; // degree (internal standard angle)
|
||||
"rad" yylval = 180/M_PI; return UNIT; // radian
|
||||
"gon" yylval = 360.0/400.0;return UNIT; // gon
|
||||
"K" yylval = Quantity(1.0 ,Unit(0,0,0,0,1)); return UNIT; // Kelvin (internal standard thermodynamic temperature)
|
||||
"mK" yylval = Quantity(0.001 ,Unit(0,0,0,0,1)); return UNIT; // Kelvin
|
||||
"yK" yylval = Quantity(0.000001 ,Unit(0,0,0,0,1)); return UNIT; // Kelvin
|
||||
|
||||
"s" yylval = 1.0; return UNIT; // second (internal standard time)
|
||||
"min" yylval = 60.0; return UNIT; // minute
|
||||
"h" yylval = 3600.0; return UNIT; // hour
|
||||
"mol" yylval = Quantity(1.0 ,Unit(0,0,0,0,0,1)); return UNIT; // Mole (internal standard amount of substance)
|
||||
|
||||
"A" yylval = 1.0; return UNIT; // Ampere (internal standard electric current)
|
||||
"K" yylval = 1.0; return UNIT; // Kelvin (internal standard thermodynamic temperature)
|
||||
"cd" yylval = 1.0; return UNIT; // Candela (internal standard luminous intensity)
|
||||
"mol" yylval = 1.0; return UNIT; // Mole (internal standard amount of substance)
|
||||
"cd" yylval = Quantity(1.0 ,Unit(0,0,0,0,0,0,1)); return UNIT; // Candela (internal standard luminous intensity)
|
||||
|
||||
"yl" yylval = 1.0; return UNIT; // microliter mm^3(derived standard volume)
|
||||
"ml" yylval = 1000.0; return UNIT; // milliliter cm^3
|
||||
"l" yylval = 1000000.0; return UNIT; // Liter dm^3
|
||||
"deg" yylval = Quantity(1.0 ,Unit(0,0,0,0,0,0,0,1)); return UNIT; // degree (internal standard angle)
|
||||
"rad" yylval = Quantity(180/M_PI ,Unit(0,0,0,0,0,0,0,1)); return UNIT; // radian
|
||||
"gon" yylval = Quantity(360.0/400.0 ,Unit(0,0,0,0,0,0,0,1)); return UNIT; // gon
|
||||
|
||||
"in" yylval = Quantity(25.4 ,Unit(1)); return UNIT; // inch
|
||||
"\"" yylval = Quantity(25.4 ,Unit(1)); return UNIT; // inch
|
||||
"fo" yylval = Quantity(304.8 ,Unit(1)); return UNIT; // foot
|
||||
"'" yylval = Quantity(304.8 ,Unit(1)); return UNIT; // foot
|
||||
"th" yylval = Quantity(0.0254 ,Unit(1)); return UNIT; // thou
|
||||
"yr" yylval = Quantity(914.4 ,Unit(1)); return UNIT; // yard
|
||||
|
||||
|
||||
"lb" yylval = Quantity(0.45359237 ,Unit(0,1)); return UNIT; // pound
|
||||
"oz" yylval = Quantity(0.45359237 ,Unit(0,1)); return UNIT; // ounce
|
||||
"st" yylval = Quantity(6.35029318 ,Unit(0,1)); return UNIT; // Stone
|
||||
"cwt" yylval = Quantity(50.80234544 ,Unit(0,1)); return UNIT; // hundredweights
|
||||
|
||||
|
||||
|
||||
|
||||
{DIGIT}+"."{DIGIT}* {yylval = atof( yytext ); return NUM;}
|
||||
{DIGIT}+ {yylval = atof( yytext ); return NUM;}
|
||||
{DIGIT}+["."","]{DIGIT}*[eE][-+]?[0-9]+ {for(char* c=yytext;*c!='\0';c++)if(*c==',')*c='.'; yylval = atof( yytext ); return NUM;}
|
||||
{DIGIT}+["."","]{DIGIT}* {for(char* c=yytext;*c!='\0';c++)if(*c==',')*c='.'; yylval = atof( yytext ); return NUM;}
|
||||
{DIGIT}+ {yylval = atof( yytext ); return NUM;}
|
||||
|
||||
"pi" {yylval = M_PI ; return NUM;} // constant pi
|
||||
"e" {yylval = M_E ; return NUM;} // constant e
|
||||
|
||||
|
||||
"acos" return ACOS;
|
||||
"asin" return ASIN;
|
||||
"atan" return ATAN;
|
||||
"atan2" return ATAN2;
|
||||
"cos" return COS;
|
||||
"exp" return EXP;
|
||||
"abs" return ABS;
|
||||
"mod" return MOD;
|
||||
"log" return LOG;
|
||||
"log10" return LOG10;
|
||||
"pow" return POW;
|
||||
"sin" return SIN;
|
||||
"sinh" return SINH;
|
||||
"tan" return TAN;
|
||||
"tanh" return TANH;
|
||||
"sqrt" return SQRT;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
/* Bison declarations. */
|
||||
%token UNIT NUM
|
||||
%token ACOS ASIN ATAN ATAN2 COS EXP ABS MOD LOG LOG10 POW SIN SINH TAN TANH SQRT;
|
||||
%left '-' '+'
|
||||
%left '*' '/'
|
||||
%left NEG /* negation--unary minus */
|
||||
|
@ -22,19 +23,43 @@
|
|||
|
||||
%%
|
||||
|
||||
input: exp { QuantResult = $1 ; }
|
||||
;
|
||||
|
||||
exp: NUM { $$ = $1; }
|
||||
| UNIT { $$ = $1; }
|
||||
| NUM UNIT { $$ = $1*$2; }
|
||||
| exp '+' exp { $$ = $1 + $3; }
|
||||
| exp '-' exp { $$ = $1 - $3; }
|
||||
| exp '*' exp { $$ = $1 * $3; }
|
||||
| exp '/' exp { $$ = $1 / $3; }
|
||||
| '-' exp %prec NEG { $$ = -$2; }
|
||||
| exp '^' NUM { $$ = $1.pow($3); }
|
||||
| '(' exp ')' { $$ = $2; }
|
||||
input: num { QuantResult = $1 ; }
|
||||
| unit { QuantResult = $1 ; }
|
||||
| quantity { QuantResult = $1 ; }
|
||||
| quantity quantity { QuantResult = $1 + $2; }
|
||||
;
|
||||
num: NUM { $$ = $1; }
|
||||
| num '+' num { $$ = $1.getValue() + $3.getValue(); }
|
||||
| num '-' num { $$ = $1.getValue() - $3.getValue(); }
|
||||
| num '*' num { $$ = $1.getValue() * $3.getValue(); }
|
||||
| num '/' num { $$ = $1.getValue() / $3.getValue(); }
|
||||
| '-' num %prec NEG { $$ = -$2.getValue(); }
|
||||
| num '^' num { $$ = pow ($1.getValue(), $3.getValue());}
|
||||
| '(' num ')' { $$ = $2; }
|
||||
| ACOS '(' num ')' { $$ = acos($3.getValue()); }
|
||||
| ASIN '(' num ')' { $$ = asin($3.getValue()); }
|
||||
| ATAN '(' num ')' { $$ = atan($3.getValue()); }
|
||||
| ATAN2 '(' num ',' num ')' { $$ = atan2($3.getValue(),$5.getValue());}
|
||||
| ABS '(' num ')' { $$ = fabs($3.getValue()); }
|
||||
| EXP '(' num ')' { $$ = exp($3.getValue()); }
|
||||
| MOD '(' num ',' num ')' { $$ = fmod($3.getValue(),$5.getValue()); }
|
||||
| LOG '(' num ')' { $$ = log($3.getValue()); }
|
||||
| LOG10 '(' num ')' { $$ = log10($3.getValue()); }
|
||||
| POW '(' num ',' num ')' { $$ = pow($3.getValue(),$5.getValue()); }
|
||||
| SIN '(' num ')' { $$ = sin($3.getValue()); }
|
||||
| SINH '(' num ')' { $$ = sinh($3.getValue()); }
|
||||
| TAN '(' num ')' { $$ = tan($3.getValue()); }
|
||||
| TANH '(' num ')' { $$ = tanh($3.getValue()); }
|
||||
| SQRT '(' num ')' { $$ = tanh($3.getValue()); }
|
||||
| COS '(' num ')' { $$ = cos($3.getValue()); }
|
||||
;
|
||||
|
||||
unit: UNIT { $$ = $1; }
|
||||
| unit '*' unit { $$ = $1 * $3; }
|
||||
| unit '/' unit { $$ = $1 / $3; }
|
||||
| unit '^' num { $$ = $1.pow ($3); }
|
||||
;
|
||||
quantity: num unit { $$ = $1*$2; }
|
||||
;
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,11 @@ using namespace Base;
|
|||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string QuantityPy::representation(void) const
|
||||
{
|
||||
return std::string("<Quantity object>");
|
||||
std::stringstream ret;
|
||||
ret << getQuantityPtr()->getValue() << " ";
|
||||
ret << getQuantityPtr()->getUnit().getString();
|
||||
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
PyObject *QuantityPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
|
||||
|
|
|
@ -51,7 +51,14 @@ Unit::Unit(int8_t Length,
|
|||
|
||||
Unit::Unit()
|
||||
{
|
||||
|
||||
Sig.Length = 0;
|
||||
Sig.Mass = 0;
|
||||
Sig.Time = 0;
|
||||
Sig.ElectricCurrent = 0;
|
||||
Sig.ThermodynamicTemperature = 0;
|
||||
Sig.AmountOfSubstance = 0;
|
||||
Sig.LuminoseIntensity = 0;
|
||||
Sig.Angle = 0;
|
||||
}
|
||||
|
||||
Unit::Unit(const Unit& that)
|
||||
|
@ -148,4 +155,125 @@ Unit& Unit::operator = (const Unit &New)
|
|||
Sig.Angle = New.Sig.Angle ;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string Unit::getString(void) const
|
||||
{
|
||||
std::stringstream ret;
|
||||
|
||||
if(isEmpty())
|
||||
return "";
|
||||
|
||||
if( Sig.Length > 0 ||
|
||||
Sig.Mass > 0 ||
|
||||
Sig.Time > 0 ||
|
||||
Sig.ElectricCurrent > 0 ||
|
||||
Sig.ThermodynamicTemperature> 0 ||
|
||||
Sig.AmountOfSubstance > 0 ||
|
||||
Sig.LuminoseIntensity > 0 ||
|
||||
Sig.Angle > 0 ){
|
||||
if(Sig.Length > 0){
|
||||
ret << "mm";
|
||||
if(Sig.Length >1)
|
||||
ret << "^" << Sig.Length;
|
||||
}
|
||||
if(Sig.Mass > 0){
|
||||
ret << "kg";
|
||||
if(Sig.Mass >1)
|
||||
ret << "^" << Sig.Mass;
|
||||
}
|
||||
if(Sig.Time > 0){
|
||||
ret << "s";
|
||||
if(Sig.Time >1)
|
||||
ret << "^" << Sig.Time;
|
||||
}
|
||||
if(Sig.ElectricCurrent > 0){
|
||||
ret << "A";
|
||||
if(Sig.ElectricCurrent >1)
|
||||
ret << "^" << Sig.ElectricCurrent;
|
||||
}
|
||||
if(Sig.ThermodynamicTemperature > 0){
|
||||
ret << "K";
|
||||
if(Sig.ThermodynamicTemperature >1)
|
||||
ret << "^" << Sig.ThermodynamicTemperature;
|
||||
}
|
||||
if(Sig.AmountOfSubstance > 0){
|
||||
ret << "mol";
|
||||
if(Sig.AmountOfSubstance >1)
|
||||
ret << "^" << Sig.AmountOfSubstance;
|
||||
}
|
||||
if(Sig.LuminoseIntensity > 0){
|
||||
ret << "cd";
|
||||
if(Sig.LuminoseIntensity >1)
|
||||
ret << "^" << Sig.LuminoseIntensity;
|
||||
}
|
||||
if(Sig.Angle > 0){
|
||||
ret << "deg";
|
||||
if(Sig.Angle >1)
|
||||
ret << "^" << Sig.Angle;
|
||||
}
|
||||
}else{
|
||||
ret << "1";
|
||||
}
|
||||
|
||||
if( Sig.Length < 0 ||
|
||||
Sig.Mass < 0 ||
|
||||
Sig.Time < 0 ||
|
||||
Sig.ElectricCurrent < 0 ||
|
||||
Sig.ThermodynamicTemperature< 0 ||
|
||||
Sig.AmountOfSubstance < 0 ||
|
||||
Sig.LuminoseIntensity < 0 ||
|
||||
Sig.Angle < 0 ){
|
||||
ret << "/";
|
||||
if(Sig.Length < 0){
|
||||
ret << "mm";
|
||||
if(Sig.Length <-1)
|
||||
ret << "^" << abs(Sig.Length);
|
||||
}
|
||||
if(Sig.Mass < 0){
|
||||
ret << "kg";
|
||||
if(Sig.Mass <-1)
|
||||
ret << "^" << abs(Sig.Mass);
|
||||
}
|
||||
if(Sig.Time < 0){
|
||||
ret << "s";
|
||||
if(Sig.Time <-1)
|
||||
ret << "^" << abs(Sig.Time);
|
||||
}
|
||||
if(Sig.ElectricCurrent < 0){
|
||||
ret << "A";
|
||||
if(Sig.ElectricCurrent <-1)
|
||||
ret << "^" << abs(Sig.ElectricCurrent);
|
||||
}
|
||||
if(Sig.ThermodynamicTemperature < 0){
|
||||
ret << "K";
|
||||
if(Sig.ThermodynamicTemperature <-1)
|
||||
ret << "^" << abs(Sig.ThermodynamicTemperature);
|
||||
}
|
||||
if(Sig.AmountOfSubstance < 0){
|
||||
ret << "mol";
|
||||
if(Sig.AmountOfSubstance <-1)
|
||||
ret << "^" << abs(Sig.AmountOfSubstance);
|
||||
}
|
||||
if(Sig.LuminoseIntensity < 0){
|
||||
ret << "cd";
|
||||
if(Sig.LuminoseIntensity <-1)
|
||||
ret << "^" << abs(Sig.LuminoseIntensity);
|
||||
}
|
||||
if(Sig.Angle < 0){
|
||||
ret << "deg";
|
||||
if(Sig.Angle <-1)
|
||||
ret << "^" << abs(Sig.Angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return ret.str();
|
||||
}
|
|
@ -73,6 +73,7 @@ public:
|
|||
|
||||
bool isEmpty(void)const;
|
||||
char getLengthDimension(void){return Sig.Length;}
|
||||
std::string getString(void) const;
|
||||
|
||||
protected:
|
||||
UnitSignature Sig;
|
||||
|
|
|
@ -132,6 +132,7 @@ protected:
|
|||
protected: // the python API wrapper methodes
|
||||
static PyObject *sTranslateUnit (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sGetWithPrefs (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
static PyObject *sParseQuantity (PyObject *self,PyObject *args,PyObject *kwd);
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "Exception.h"
|
||||
/// Here the FreeCAD includes sorted by Base,App,Gui......
|
||||
#include "UnitsApi.h"
|
||||
#include "Quantity.h"
|
||||
#include "QuantityPy.h"
|
||||
|
||||
|
||||
|
||||
|
@ -66,6 +68,9 @@ PyMethodDef UnitsApi::Methods[] = {
|
|||
" Temperature \n"
|
||||
|
||||
},
|
||||
{"parseQuantity", (PyCFunction) UnitsApi::sParseQuantity ,1,
|
||||
"parseQuantity(string) -> Base.Quantity()\n\n"
|
||||
},
|
||||
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
@ -116,3 +121,25 @@ PyObject* UnitsApi::sGetWithPrefs(PyObject * /*self*/, PyObject *args,PyObject *
|
|||
}
|
||||
}
|
||||
|
||||
PyObject* UnitsApi::sParseQuantity(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
|
||||
{
|
||||
char *pstr;
|
||||
if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
Quantity rtn;
|
||||
try {
|
||||
rtn = Quantity::parse(pstr);
|
||||
}
|
||||
catch (const Base::Exception&) {
|
||||
PyErr_Format(PyExc_IOError, "invalid unit expression \n");
|
||||
return 0L;
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
PyErr_Format(PyExc_IOError, "invalid unit expression \n");
|
||||
return 0L;
|
||||
}
|
||||
|
||||
return new QuantityPy(new Quantity(rtn));
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user