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