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