Subversion Repositories wimsdev

Rev

Rev 6872 | Rev 8206 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
104 bpr 1
// -*- coding: utf-8 -*-
10 reyssat 2
%{
104 bpr 3
/* inclusions, définition */
10 reyssat 4
#include <string>
5
#include <stdlib.h>
6
#include <stdio.h>
7
#include <unistd.h>
8
#include <math.h>
9
#include "chemeq.h"
10
  //#include <FlexLexer.h>
11
#include <sstream>
12
 
13
  int yylex();
14
  int yyerror(char * msg);
15
 
16
typedef struct{
17
  int i, d; /* integer numerator, denominator */
18
  double r;
19
  AtomeListe * al;
20
  Molec * m;
21
  Chemeq * cq;
22
  Membre * mb;
23
  char symb[4];
24
  moltype t;
25
  std::string s;
26
} yystype;
27
 
28
#define YYSTYPE yystype 
29
 
30
/* variables globales */
31
 
32
 yystype result;
33
 extern char * yytext;
34
 extern int position;
35
 int isequation;
36
 
37
%}
38
 
39
%token Atome
40
%token SpcPlus
41
%token Plus
42
%token Moins
104 bpr 43
%token Mul
10 reyssat 44
%token Fleche
45
%token Int
46
%token Charge
47
%token Frac
48
%token Real
49
%token SpcLpar
50
%token Lpar
51
%token Rpar
52
%token Lsq
53
%token Rsq
54
%token Haut
55
%token Spc
56
%token Sol
57
%token Gas
58
%token Aqueous
59
%token Egal
104 bpr 60
%token Compose
61
%token AntiCompose
10 reyssat 62
 
63
%%
64
 
104 bpr 65
/* les règles */
66
but : chcompose { 
10 reyssat 67
  result=$1;
68
  isequation=1;
69
}
70
| molec {
71
  result=$1;
72
  isequation=0;
73
}
74
;
75
 
601 georgesk 76
chcompose : chc {$$=$1;}
104 bpr 77
| chcompose spc01 Compose spc01 chc {
78
  $1.cq->addChemeq($5.cq);
79
  $$=$1;
80
}
81
| chcompose spc01 AntiCompose spc01 chc { 
82
  $1.cq->subChemeq($5.cq);
83
  $$=$1;
84
}
85
;
86
 
87
chc : chemeq cste{
88
  $$=$1;
89
  $$.cq->constante($2.s);
90
  $$.cq->valeur($2.r);
91
}
92
| Frac spc01 Mul spc01 chc {
93
  $$.cq = $5.cq; $$.cq->multiply($1.i,$1.d);
94
}
95
| Int spc01 Mul spc01 chc {
96
  $$.cq = $5.cq; $$.cq->multiply($1.i,1);
97
}
98
;
99
 
100
cste : /* rien */ {$$.s = ""; $$.r = MINVAL; /* valeur négative : non défini */}
10 reyssat 101
| SpcLpar cste1 Rpar {$$ = $2;}
102
;
103
 
104
cste1 : spc01 nombre volt{$$.s = ""; $$.r = $2.r;}
105
| spc01 id spc01 Egal spc01 nombre volt{$$.s = $2.s; $$.r = $6.r;}
106
;
107
 
108
nombre : Real {$$.r=$1.r;}
109
| Int {$$.r=1.0*$1.i;}
110
| Plus spc01 Real{$$.r=$3.r;}
111
| Moins spc01 Real{$$.r=-$3.r;}
112
| Plus spc01 Int{$$.r=1.0*$3.i;}
113
| Moins spc01 Int{$$.r=-1.0*$3.i;}
114
;
115
 
116
volt : /* rien */
6906 georgesk 117
| spc01 Atome {if ($2.s.compare("V")!=0) yyerror (strdup("only 'V' allowed as unit")); }
10 reyssat 118
;
119
 
120
id : Atome {/* $$.s contient le nom */}
121
;
122
 
123
chemeq : membre Spc Fleche spc01 membre{
124
  $$.cq = new Chemeq($1.mb,$5.mb);
125
}
126
;
127
 
128
membre : membre SpcPlus spc01 molecs {
104 bpr 129
  $$.mb->addMol($4.m);
10 reyssat 130
}
131
| molecs {
132
  $$.mb = new Membre;
133
  $$.mb->push_back($1.m);
134
}
135
;
136
 
137
molecs : Int spc01 molec {
138
  $$ = $3;
139
  $$.m->nombre($1.i);
140
}
141
| Frac spc01 molec {
142
  $$ = $3;
143
  $$.m->nombre($1.i,$1.d);
144
}
145
| molec{
146
  $$ = $1; 
147
}
148
;
149
 
150
spc01 : /*rien*/
151
| Spc
152
;
153
 
154
molec : composition0 typage{
155
  $$.m = new Molec($1.al,0); $$.m->typage($2.t);
156
}
157
| composition0 charge typage{
158
  $$.m = new Molec($1.al,$2.i);$$.m->typage($3.t);
159
}
160
;
161
 
162
 
163
composition0 : composition {$$.al=$1.al;}
164
| Lsq spc01 composition spc01 Rsq {$$.al=$3.al; $$.al->sq(1);}
165
;
166
 
167
typage : /* rien */ {$$.t = aqueous;}
168
| Aqueous {$$.t = aqueous;}
169
| Sol {$$.t = sol;}
170
| Gas {$$.t = gas;}
171
;
172
 
173
charge : Plus {$$.i=1;}
174
| Haut Plus {$$.i=1;}
175
| Haut Charge {$$.i=$2.i;}
176
| Moins{$$.i=-1;}
177
| Haut  Moins{$$.i=-1;}
178
;
179
 
180
groupe : Lpar composition Rpar {
181
  $$=$2; 
182
}
183
;
184
 
185
atome_general : groupe {
186
  $$.al = new AtomeListe("",0,0,$1.al);
187
}
188
| Atome{
189
  char buffer[25];
104 bpr 190
  if ($1.i==-2) { /* ce n'est pas un atome recensé */
10 reyssat 191
    sprintf(buffer,"nonexistent atom : %s", $1.symb);
192
    yyerror(buffer);
193
  }
194
  $$.al = new AtomeListe($1.symb,$1.i);
195
}
196
;
197
 
198
composition : atome_general molecularite composition {
199
  $$ = $1;
200
  $$.al->setmolecularite($2.i);
201
  $$.al->setsuivant($3.al);
202
}
203
| atome_general molecularite{
204
  $$.al = $1.al;
205
  $$.al->setmolecularite($2.i);
206
}
207
;
208
 
209
molecularite : /*rien*/{
210
  $$.i=1;
211
}
212
| Int {
213
  $$=$1; 
214
}
215
;
216
 
217
%%
218
#include "chemlex.cc"
219
 
220
yyFlexLexer lexer;
221
yyFlexLexer * thelexer = &lexer;
222
 
223
int yylex(){
224
  return thelexer->yylex();
225
}
226
 
104 bpr 227
/* le programme lui-même */
10 reyssat 228
 
229
inline int yyerror(char * msg){
230
  fprintf(stderr, "ERROR %s at %d\n ", msg, position);
231
  exit(1);
232
}
233
 
234
void printVersion(){
6872 georgesk 235
  std::cout << "Chemeq version " << VERSION << "\n(c) Georges Khaznadar <georgesk@debian.org>.";
10 reyssat 236
  std::cout << "\nThis program is free, licensed under G.P.L.\n";
237
}
238
 
239
void printHelp(){
240
  std::cout << "Usage : chemeq [-m] [-l] [-c] [-w] [-C] [-n] [-e] [-s] [-v] [-h]" << std::endl;
241
  std::cout << "        default is equivalent to 'chemeq -mlcwCn'" << std::endl;
242
  std::cout << "        chemeq reads its standard input which must be a standard" << std::endl;
243
  std::cout << "        chemical equation. It outputs many strings useful for chemical" << std::endl;
244
  std::cout << "        calculations." << std::endl;
245
  std::cout << "        As an example you can try the following command :" << std::endl;
246
  std::cout << "        echo \"Fes -> Fe^2+ + 2 e- (0.44 V)\" | chemeq" << std::endl;
247
}
248
 
249
#define maxoption 16
250
 
104 bpr 251
void optionadd(char* b, char* allowed, int c);
252
void optionadd(char* b, char* allowed, int c){
253
  if (strchr(allowed,c) && !strchr(b,c) && strlen(b) < maxoption+1){
254
    int l = strlen(b);
255
    b[l]=c; b[l+1]=0;
256
  }
10 reyssat 257
  return;
258
}
259
 
260
int main(int argc, char * argv[]){
6906 georgesk 261
  char * optstr = strdup("mMlcCwnesvh");
10 reyssat 262
  char * envoption=getenv("chemeq_option");
263
  if (envoption==NULL) envoption=getenv("w_chemeq_option");
264
  char * envinput =getenv("chemeq_input");
265
  if (envinput==NULL) envinput=getenv("w_chemeq_input");
266
  char asked[maxoption+1]="";
267
  int i,ch;
268
  bool nooption=1;
472 georgesk 269
  std::ostringstream w;
10 reyssat 270
 
271
  while (-1 != (ch=getopt(argc,argv,optstr))){
272
    optionadd(asked,optstr,ch);
273
  }
274
  if (envoption!=NULL) for(i=0; i<strlen(envoption); i++){
275
    optionadd(asked, optstr, envoption[i]);
276
  }
277
  if (strchr(asked,'h')!=NULL){
278
    printHelp(); return 0;
279
  }
280
  if (strchr(asked,'v')!=NULL){
281
    printVersion(); return 0;
282
  }
283
  if (envinput !=NULL){
284
    std::istringstream iss(envinput);
285
    thelexer= new yyFlexLexer (&iss);
286
  } 
287
  yyparse();
288
 
472 georgesk 289
  bool wantedlatex=(strchr(asked,'l')!=NULL);
10 reyssat 290
  if (isequation) {
291
    for(i=0; i<strlen(asked); i++){
292
      switch(asked[i]){
293
      case 'm': nooption=0;
294
	result.cq->printnorm(std::cout); std::cout << std::endl;
295
	break;
296
      case 'M': nooption=0;
297
	result.cq->printweight(std::cout);
298
	std::cout <<  std::endl;
299
	break;
300
      case 'l': nooption=0;
301
	std::cout << *result.cq << std::endl;
302
	break;
303
      case 'c': nooption=0;
304
	std::cout << result.cq->equilibre() << std::endl;
305
	break;
306
      case 'w': nooption=0;
472 georgesk 307
	result.cq->printNernst(std::cout,w,wantedlatex); std::cout << std::endl;
308
	std::cout << w.str() << std::endl;
10 reyssat 309
	break;
310
      case 'n': nooption=0;
311
	result.cq->normalise();
312
	result.cq->printnorm(std::cout); std::cout << std::endl;
313
	break;
314
      case 'C': nooption=0;
315
	result.cq->printcount(std::cout); std::cout << std::endl;
316
	break;
317
      case 'e': nooption=0;
318
	result.cq->printelec(std::cout); std::cout << std::endl;
319
	break;
320
      case 's': nooption=0;
321
	result.cq->printspecies(std::cout); std::cout << std::endl;
322
	break;
323
      }
324
    }
325
    if (nooption){
326
      result.cq->printnorm(std::cout); std::cout << std::endl;
327
      std::cout << *result.cq << std::endl;
328
      std::cout << result.cq->equilibre() << std::endl;
472 georgesk 329
      result.cq->printNernst(std::cout,w); std::cout << std::endl;
10 reyssat 330
      result.cq->printcount(std::cout); std::cout << std::endl;
331
      result.cq->normalise();
332
      result.cq->printnorm(std::cout); std::cout << std::endl;
333
    }
334
  }
104 bpr 335
  else { /* ce n'est pas une équation */
10 reyssat 336
    for(i=0; i<strlen(asked); i++){
337
      switch(asked[i]){
338
      case 'M': nooption=0;
339
	std::cout << result.m->weight();
340
	std::cout <<  std::endl;
341
	break;
342
      }
343
    }
344
    if (nooption){
345
      std::cout << *result.m;
346
    }
347
  }
348
  return 0;
349
}