%{
/* Lexer for the FreeCAD  Units language   */
/* (c) 2013 Juergen Riegel  LGPL           */


/* This disables inclusion of unistd.h, which is not available under Visual C++
 * on Win32. The C++ scanner uses STL streams instead. */
#define YY_NO_UNISTD_H

%}

/*** Flex Declarations and Options ***/


/* the manual says "somewhat more optimized" */
%option batch
%option never-interactive 


/* no support for include files is planned */
%option noyywrap nounput 

DIGIT    [0-9]
ID       [a-z][a-z0-9]*

%x C_COMMENT

%% /*** Filter language Part ***/

"\["            { BEGIN(C_COMMENT); }
<C_COMMENT>"\]" { BEGIN(INITIAL); }
<C_COMMENT>.    { ;}

 
[ \t]       ;
[\n]+       ;

[-+()=/*^]  { return *yytext; }

 "nm"       yylval = Quantity::NanoMetre;           return UNIT; // nano meter
 "um"       yylval = Quantity::MicroMetre;          return UNIT; // micro meter
 "\xC2\xB5m"    yylval = Quantity::MicroMetre;          return UNIT; // micro meter    (greek micro in UTF8)
 "mm"       yylval = Quantity::MilliMetre;          return UNIT; // milli meter    (internal standard length)
 "cm"       yylval = Quantity::CentiMetre;          return UNIT; // centi meter
 "dm"       yylval = Quantity::DeciMetre;           return UNIT; // deci meter
 "m"        yylval = Quantity::Metre;               return UNIT; // metre
 "km"       yylval = Quantity::KiloMetre;           return UNIT; // kilo meter

 "l"        yylval = Quantity::Liter;               return UNIT; // Liter      dm^3
 
 "ug"       yylval = Quantity::MicroGram;           return UNIT; // micro gram
 "\xC2\xB5g"    yylval = Quantity::MicroGram;           return UNIT; // micro gram
 "mg"       yylval = Quantity::MilliGram;           return UNIT; // milli gram
 "g"        yylval = Quantity::Gram;                return UNIT; // gram
 "kg"       yylval = Quantity::KiloGram;            return UNIT; // kilo gram      (internal standard for mass) 
 "t"        yylval = Quantity::Ton;                 return UNIT; // Metric Tonne
 
 "s"        yylval = Quantity::Second;              return UNIT; // second         (internal standard time)
 "min"      yylval = Quantity::Minute;              return UNIT; // minute
 "h"        yylval = Quantity::Hour;                return UNIT; // hour  
 
 "A"        yylval = Quantity::Ampere;              return UNIT; // Ampere         (internal standard electric current)
 "mA"       yylval = Quantity::MilliAmpere;         return UNIT; // milli Ampere         
 "kA"       yylval = Quantity::KiloAmpere;          return UNIT; // kilo Ampere         
 "MA"       yylval = Quantity::MegaAmpere;          return UNIT; // Mega Ampere         
 
 "K"        yylval = Quantity::Kelvin;              return UNIT; // Kelvin         (internal standard thermodynamic temperature)
 "mK"       yylval = Quantity::MilliKelvin;         return UNIT; // Kelvin         
 "\xC2\xB5K"    yylval = Quantity::MicroKelvin;         return UNIT; // Kelvin         
 "uK"       yylval = Quantity::MicroKelvin;         return UNIT; // Kelvin         
 
 "mol"      yylval = Quantity::Mole;                return UNIT; // Mole           (internal standard amount of substance)        
 
 "cd"       yylval = Quantity::Candela;             return UNIT; // Candela        (internal standard luminous intensity)        
 
 "in"       yylval = Quantity::Inch;                return UNIT; // inch
 "\""       yylval = Quantity::Inch;                return UNIT; // inch
 "ft"       yylval = Quantity::Foot;                return UNIT; // foot
 "'"        yylval = Quantity::Foot;                return UNIT; // foot
 "thou"     yylval = Quantity::Thou;                return UNIT; // thou (in/1000)
 "mil"      yylval = Quantity::Thou;                return UNIT; // mil  (the thou in US)
 "yd"       yylval = Quantity::Yard;                return UNIT; // yard
 "mi"       yylval = Quantity::Mile;                return UNIT; // mile
 
 
 
 "lb"       yylval = Quantity::Pound;               return UNIT; // pound
 "lbm"      yylval = Quantity::Pound;               return UNIT; // pound 
 "oz"       yylval = Quantity::Ounce;               return UNIT; // ounce
 "st"       yylval = Quantity::Stone;               return UNIT; // Stone
 "cwt"      yylval = Quantity::Hundredweights;      return UNIT; // hundredweights
 
 "lbf"      yylval = Quantity::PoundForce;          return UNIT; // pound
 
 "N"        yylval = Quantity::Newton;              return UNIT; // Newton (kg*m/s^2)
 "kN"       yylval = Quantity::KiloNewton;          return UNIT; // Newton 
 "MN"       yylval = Quantity::MegaNewton;          return UNIT; // Newton 
 "mN"       yylval = Quantity::MilliNewton;         return UNIT; // Newton 
 
 "Pa"       yylval = Quantity::Pascal;              return UNIT; // Pascal (kg/m*s^2 or N/m^2) 
 "kPa"      yylval = Quantity::KiloPascal;          return UNIT; // Pascal 
 "MPa"      yylval = Quantity::MegaPascal;          return UNIT; // Pascal  
 "GPa"      yylval = Quantity::GigaPascal;          return UNIT; // Pascal  

 "Torr"     yylval = Quantity::Torr;                return UNIT; // portion of Pascal ( 101325/760 ) 
 "mTorr"    yylval = Quantity::mTorr;               return UNIT; //  
 "uTorr"    yylval = Quantity::yTorr;               return UNIT; //  
 "\xC2\xB5Torr"    yylval = Quantity::yTorr;               return UNIT; //  
 
 "psi"      yylval = Quantity::PSI;                 return UNIT; // pounds/in^2 
 "ksi"      yylval = Quantity::KSI;                 return UNIT; // 1000 x pounds/in^2 
 
 "W"        yylval = Quantity::Watt;                return UNIT; // Watt (kg*m^2/s^3) 
 "VA"       yylval = Quantity::VoltAmpere;          return UNIT; // VoltAmpere (kg*m^2/s^3) 
 
 "J"        yylval = Quantity::Joule;               return UNIT; // Joule (kg*m^2/s^2) 
 "Nm"       yylval = Quantity::NewtonMeter;         return UNIT; // N*m = Joule 
 "VAs"      yylval = Quantity::VoltAmpereSecond;    return UNIT; // V*A*s = Joule 
 "CV"       yylval = Quantity::WattSecond;          return UNIT; //  
 "Ws"       yylval = Quantity::WattSecond;          return UNIT; // W*s = Joule 
 
 "\xC2\xB0" yylval = Quantity::Degree;              return UNIT; // degree         (internal standard angle)
 "deg"      yylval = Quantity::Degree;              return UNIT; // degree         (internal standard angle)
 "rad"      yylval = Quantity::Radian;              return UNIT; // radian         
 "gon"      yylval = Quantity::Gon;                 return UNIT; // gon         

{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;

.                      return *yytext;
