Subversion Repositories wimsdev

Rev

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