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 | } |