Rev 104 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
%{
/* inclusions, définition */
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include "chemeq.h"
//#include <FlexLexer.h>
#include <sstream>
int yylex();
int yyerror(char * msg);
typedef struct{
int i, d; /* integer numerator, denominator */
double r;
AtomeListe * al;
Molec * m;
Chemeq * cq;
Membre * mb;
char symb[4];
moltype t;
std::string s;
} yystype;
#define YYSTYPE yystype
/* variables globales */
yystype result;
extern char * yytext;
extern int position;
int isequation;
%}
%token Atome
%token SpcPlus
%token Plus
%token Moins
%token Fleche
%token Int
%token Charge
%token Frac
%token Real
%token SpcLpar
%token Lpar
%token Rpar
%token Lsq
%token Rsq
%token Haut
%token Spc
%token Sol
%token Gas
%token Aqueous
%token Egal
%%
/* les règles */
but : chemeq cste{
result=$1;
result.cq->constante($2.s);
result.cq->valeur($2.r);
isequation=1;
}
| molec {
result=$1;
isequation=0;
}
;
cste : /* rien */ {$$.s = ""; $$.r = -1.0; /* valeur négative : non défini */}
| SpcLpar cste1 Rpar {$$ = $2;}
;
cste1 : spc01 nombre volt{$$.s = ""; $$.r = $2.r;}
| spc01 id spc01 Egal spc01 nombre volt{$$.s = $2.s; $$.r = $6.r;}
;
nombre : Real {$$.r=$1.r;}
| Int {$$.r=1.0*$1.i;}
| Plus spc01 Real{$$.r=$3.r;}
| Moins spc01 Real{$$.r=-$3.r;}
| Plus spc01 Int{$$.r=1.0*$3.i;}
| Moins spc01 Int{$$.r=-1.0*$3.i;}
;
volt : /* rien */
| spc01 Atome {if ($2.s != std::string("V")) yyerror ("only 'V' allowed as unit"); }
;
id : Atome {/* $$.s contient le nom */}
;
chemeq : membre Spc Fleche spc01 membre{
$$.cq = new Chemeq($1.mb,$5.mb);
}
;
membre : membre SpcPlus spc01 molecs {
$$.mb->push_back($4.m);
}
| molecs {
$$.mb = new Membre;
$$.mb->push_back($1.m);
}
;
molecs : Int spc01 molec {
$$ = $3;
$$.m->nombre($1.i);
}
| Frac spc01 molec {
$$ = $3;
$$.m->nombre($1.i,$1.d);
}
| molec{
$$ = $1;
}
;
spc01 : /*rien*/
| Spc
;
molec : composition0 typage{
$$.m = new Molec($1.al,0); $$.m->typage($2.t);
}
| composition0 charge typage{
$$.m = new Molec($1.al,$2.i);$$.m->typage($3.t);
}
;
composition0 : composition {$$.al=$1.al;}
| Lsq spc01 composition spc01 Rsq {$$.al=$3.al; $$.al->sq(1);}
;
typage : /* rien */ {$$.t = aqueous;}
| Aqueous {$$.t = aqueous;}
| Sol {$$.t = sol;}
| Gas {$$.t = gas;}
;
charge : Plus {$$.i=1;}
| Haut Plus {$$.i=1;}
| Haut Charge {$$.i=$2.i;}
| Moins{$$.i=-1;}
| Haut Moins{$$.i=-1;}
;
groupe : Lpar composition Rpar {
$$=$2;
}
;
atome_general : groupe {
$$.al = new AtomeListe("",0,0,$1.al);
}
| Atome{
char buffer[25];
if ($1.i==-2) { /* ce n'est pas un atome recensé */
sprintf(buffer,"nonexistent atom : %s", $1.symb);
yyerror(buffer);
}
$$.al = new AtomeListe($1.symb,$1.i);
}
;
composition : atome_general molecularite composition {
$$ = $1;
$$.al->setmolecularite($2.i);
$$.al->setsuivant($3.al);
}
| atome_general molecularite{
$$.al = $1.al;
$$.al->setmolecularite($2.i);
}
;
molecularite : /*rien*/{
$$.i=1;
}
| Int {
$$=$1;
}
;
%%
#include "chemlex.cc"
yyFlexLexer lexer;
yyFlexLexer * thelexer = &lexer;
int yylex(){
return thelexer->yylex();
}
/* le programme lui-même */
inline int yyerror(char * msg){
fprintf(stderr, "ERROR %s at %d\n ", msg, position);
exit(1);
}
void printVersion(){
std::cout << "Chemeq version " << VERSION << "\n(c) Georges Khaznadar <georgesk@ofset.org>.";
std::cout << "\nThis program is free, licensed under G.P.L.\n";
}
void printHelp(){
std::cout << "Usage : chemeq [-m] [-l] [-c] [-w] [-C] [-n] [-e] [-s] [-v] [-h]" << std::endl;
std::cout << " default is equivalent to 'chemeq -mlcwCn'" << std::endl;
std::cout << " chemeq reads its standard input which must be a standard" << std::endl;
std::cout << " chemical equation. It outputs many strings useful for chemical" << std::endl;
std::cout << " calculations." << std::endl;
std::cout << " As an example you can try the following command :" << std::endl;
std::cout << " echo \"Fes -> Fe^2+ + 2 e- (0.44 V)\" | chemeq" << std::endl;
}
#define maxoption 16
void optionadd(char* b, char* allowed, char c);
void optionadd(char* b, char* allowed, char c){
int l = strlen(b);
/* if (strchr(allowed,c)==NULL || strchr(b,c)!=NULL || l >= maxoption){ */
/* return; */
/* } */
// assert (strchr(allowed,c)!=NULL && strchr(b,c)==NULL && strlen(b)<maxoption);
b[l]=c; b[l+1]=0;
return;
}
int main(int argc, char * argv[]){
char * optstr = "mMlcCwnesvh";
char * envoption=getenv("chemeq_option");
if (envoption==NULL) envoption=getenv("w_chemeq_option");
char * envinput =getenv("chemeq_input");
if (envinput==NULL) envinput=getenv("w_chemeq_input");
char asked[maxoption+1]="";
int i,ch;
bool nooption=1;
while (-1 != (ch=getopt(argc,argv,optstr))){
optionadd(asked,optstr,ch);
}
if (envoption!=NULL) for(i=0; i<strlen(envoption); i++){
optionadd(asked, optstr, envoption[i]);
}
if (strchr(asked,'h')!=NULL){
printHelp(); return 0;
}
if (strchr(asked,'v')!=NULL){
printVersion(); return 0;
}
if (envinput !=NULL){
std::istringstream iss(envinput);
thelexer= new yyFlexLexer (&iss);
}
yyparse();
if (isequation) {
for(i=0; i<strlen(asked); i++){
switch(asked[i]){
case 'm': nooption=0;
result.cq->printnorm(std::cout); std::cout << std::endl;
break;
case 'M': nooption=0;
result.cq->printweight(std::cout);
std::cout << std::endl;
break;
case 'l': nooption=0;
std::cout << *result.cq << std::endl;
break;
case 'c': nooption=0;
std::cout << result.cq->equilibre() << std::endl;
break;
case 'w': nooption=0;
result.cq->printNernst(std::cout); std::cout << std::endl;
break;
case 'n': nooption=0;
result.cq->normalise();
result.cq->printnorm(std::cout); std::cout << std::endl;
break;
case 'C': nooption=0;
result.cq->printcount(std::cout); std::cout << std::endl;
break;
case 'e': nooption=0;
result.cq->printelec(std::cout); std::cout << std::endl;
break;
case 's': nooption=0;
result.cq->printspecies(std::cout); std::cout << std::endl;
break;
}
}
if (nooption){
result.cq->printnorm(std::cout); std::cout << std::endl;
std::cout << *result.cq << std::endl;
std::cout << result.cq->equilibre() << std::endl;
result.cq->printNernst(std::cout); std::cout << std::endl;
result.cq->printcount(std::cout); std::cout << std::endl;
result.cq->normalise();
result.cq->printnorm(std::cout); std::cout << std::endl;
}
}
else { /* ce n'est pas une équation */
for(i=0; i<strlen(asked); i++){
switch(asked[i]){
case 'M': nooption=0;
std::cout << result.m->weight();
std::cout << std::endl;
break;
}
}
if (nooption){
std::cout << *result.m;
}
}
return 0;
}