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