Subversion Repositories wimsdev

Rev

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