Subversion Repositories wimsdev

Rev

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