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