Subversion Repositories wimsdev

Rev

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