1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Parsers for algebraic expressions coming from UFO, outputting into
17 different languages/frameworks (Fortran and Pythia8). Uses the PLY 3.3
18 Lex + Yacc framework"""
19
20 import logging
21 import os
22 import re
23 import sys
24 import copy
25
26 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
27 sys.path.append(os.path.join(root_path, os.path.pardir))
28
29 import madgraph.various.misc as misc
30
31 from madgraph import MadGraph5Error
32 import vendor.ply.lex as lex
33 import vendor.ply.yacc as yacc
34 import models.check_param_card as check_param_card
35
36 logger = logging.getLogger('madgraph.ufo_parsers')
37
38
39
41 """Appropriate Error for a wrong parsing"""
42
44 """A base class for parsers for algebraic expressions coming from UFO."""
45
46 parsed_string = ""
47 logical_equiv = {}
48
50 """Initialize the lex and yacc"""
51
52 modname = self.__class__.__name__
53 self.debugfile = os.path.devnull
54 self.tabmodule = os.path.join(root_path, "iolibs", modname + "_" + "parsetab.py")
55 lex.lex(module=self, debug=0)
56 self.y=yacc.yacc(module=self, debug=0, debugfile=self.debugfile,
57 tabmodule=self.tabmodule)
58
64
65
66 tokens = (
67 'LOGICAL','LOGICALCOMB','POWER', 'CSC', 'SEC', 'ACSC', 'ASEC', 'TAN', 'ATAN',
68 'SQRT', 'CONJ', 'RE', 'RE2', 'IM', 'PI', 'COMPLEX', 'FUNCTION', 'IF','ELSE',
69 'VARIABLE', 'NUMBER','COND','REGLOG', 'REGLOGP', 'REGLOGM','RECMS','ARG'
70 )
71 literals = "=+-*/(),"
72
73
74
76 r'(?<!\w)csc(?=\()'
77 return t
79 r'(?<!\w)sec(?=\()'
80 return t
82 r'(?<!\w)acsc(?=\()'
83 return t
85 r'(?<!\w)tan(?=\()|(?<!\w)cmath.tan(?=\()'
86 return t
88 r'(?<!\w)atan(?=\()|(?<!\w)cmath.atan(?=\()'
89 return t
91 r'(?<!\w)asec(?=\()'
92 return t
94 r'(?<!\w)reglog(?=\()'
95 return t
97 r'(?<!\w)reglogp(?=\()'
98 return t
100 r'(?<!\w)reglogm(?=\()'
101 return t
103 r'(?<!\w)recms(?=\()'
104 return t
106 r'(?<!\w)cond(?=\()'
107 return t
109 r'(?<!\w)arg(?=\()'
110 return t
112 r'(?<!\w)if\s'
113 return t
115 r'(?<!\w)else\s'
116 return t
118 r'==|!=|<=|>=|<|>'
119 return t
121 r'(?<!\w)and(?=[\s\(])|(?<!\w)or(?=[\s\(])'
122 return t
124 r'cmath\.sqrt'
125 return t
127 r'cmath\.pi'
128 return t
130 r'complexconjugate'
131 return t
133 r'(?<!\w)im(?=\()'
134 return t
136 r'(?<!\w)re(?=\()'
137 return t
139 r'\.real|\.imag|\.conjugate\(\)'
140 return t
141
143 r'(?<!\w)complex(?=\()'
144 return t
146 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
147 return t
149 r'[a-zA-Z_][0-9a-zA-Z_]*'
150 return t
151
152 t_NUMBER = r'([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)([eE][+-]{0,1}[0-9]+){0,1}j{0,1}'
153 t_POWER = r'\*\*'
154
155 t_ignore = " \t"
156
157 re_cmath_function = re.compile("cmath\.(?P<name>[0-9a-zA-Z_]+)")
158
160 r'\n+'
161 t.lexer.lineno += t.value.count("\n")
162
164 logger.error("Illegal character '%s'" % t.value[0])
165 t.lexer.skip(1)
166
168 """remove variable related to the latest parsing"""
169
170 return
171
172
173
174 - def build(self,**kwargs):
175 self.lexer = lex.lex(module=self, **kwargs)
176
177
178
179 precedence = (
180 ('right', 'LOGICALCOMB'),
181 ('right', 'LOGICAL'),
182 ('right','IF'),
183 ('right','ELSE'),
184 ('left','='),
185 ('left','+','-'),
186 ('left','*','/'),
187 ('left', 'RE2'),
188 ('right','UMINUS'),
189 ('left','POWER'),
190 ('right','REGLOG'),
191 ('right','REGLOGP'),
192 ('right','REGLOGM'),
193 ('right','RECMS'),
194 ('right','ARG'),
195 ('right','CSC'),
196 ('right','SEC'),
197 ('right','ACSC'),
198 ('right','ASEC'),
199 ('right','SQRT'),
200 ('right','CONJ'),
201 ('right','RE'),
202 ('right','IM'),
203 ('right','FUNCTION'),
204 ('right','COMPLEX'),
205 ('right','COND'),
206 )
207
208
212
214 '''expression : expression '=' expression
215 | expression '+' expression
216 | expression '-' expression
217 | expression '*' expression
218 | expression '/' expression'''
219 p[0] = p[1] + p[2] + p[3]
220
222 '''boolexpression : expression LOGICAL expression'''
223 if p[2] not in self.logical_equiv:
224 p[0] = p[1] + p[2] + p[3]
225 else:
226 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
227
229 '''boolexpression : boolexpression LOGICALCOMB boolexpression'''
230 if p[2] not in self.logical_equiv:
231 p[0] = p[1] + p[2] + p[3]
232 else:
233 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
234
236 "expression : '-' expression %prec UMINUS"
237 p[0] = '-' + p[2]
238
240 "group : '(' expression ')'"
241 p[0] = '(' + p[2] +')'
242
243
245 "boolexpression : '(' boolexpression ')'"
246 p[0] = '(' + p[2] +')'
247
249 "expression : group"
250 p[0] = p[1]
251
253 "expression : FUNCTION '(' expression ')'"
254 p1 = p[1]
255 re_groups = self.re_cmath_function.match(p1)
256 if re_groups:
257 p1 = re_groups.group("name")
258 p[0] = p1 + '(' + p[3] + ')'
259
261 "expression : FUNCTION '(' expression ',' expression ')'"
262 p1 = p[1]
263 re_groups = self.re_cmath_function.match(p1)
264 if re_groups:
265 p1 = re_groups.group("name")
266 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
267
269 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
270 p1 = p[1]
271 re_groups = self.re_cmath_function.match(p1)
272 if re_groups:
273 p1 = re_groups.group("name")
274 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
275
277 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
278 p1 = p[1]
279 re_groups = self.re_cmath_function.match(p1)
280 if re_groups:
281 p1 = re_groups.group("name")
282 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
283
290
292 """A parser for UFO algebraic expressions, outputting
293 Fortran-style code."""
294
295
296
297
298
299
300 logical_equiv = {'==':'.EQ.',
301 '>=':'.GE.',
302 '<=':'.LE.',
303 '!=':'.NE.',
304 '>':'.GT.',
305 '<':'.LT.',
306 'or':'.OR.',
307 'and':'.AND.'}
308
313
315 """remove information about object parse for previous parsing
316 """
317 self.to_define = set()
318
319
320
321
323 "expression : NUMBER"
324 if p[1].endswith('j'):
325 p[0] = ('DCMPLX(0d0, %e)' % float(p[1][:-1])).replace('e', 'd')
326 else:
327 p[0] = ('%e' % float(p[1])).replace('e', 'd')
328
330 "expression : VARIABLE"
331 p[0] = p[1].lower()
332
334 'expression : expression POWER expression'
335 try:
336 p3 = float(p[3].replace('d','e'))
337
338 if p3 == int(p3):
339 p3 = str(int(p3))
340 p[0] = p[1] + "**" + p3
341 else:
342 p[0] = p[1] + "**" + p[3]
343 except Exception:
344 p[0] = p[1] + "**" + p[3]
345
347 "expression : expression IF boolexpression ELSE expression "
348 p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
349 self.to_define.add('condif')
350
352 "expression : expression IF expression ELSE expression "
353 p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\
354 %(p[3], p[1], p[5])
355 self.to_define.add('condif')
356
358 "expression : COND '(' expression ',' expression ',' expression ')'"
359 p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
360 self.to_define.add('cond')
361
363 "expression : RECMS '(' boolexpression ',' expression ')'"
364 p[0] = 'RECMS('+p[3]+',DCMPLX('+p[5]+'))'
365 self.to_define.add('recms')
366
368 "expression : COMPLEX '(' expression ',' expression ')'"
369 p[0] = 'DCMPLX(' + p[3] + ',' + p[5] + ')'
370
372 '''expression : CSC group
373 | SEC group
374 | ACSC group
375 | ASEC group
376 | RE group
377 | IM group
378 | ARG group
379 | SQRT group
380 | CONJ group
381 | REGLOG group
382 | REGLOGP group
383 | REGLOGM group
384 | TAN group
385 | ATAN group'''
386
387 if p[1] == 'csc': p[0] = '1d0/sin' + p[2]
388 elif p[1] == 'sec': p[0] = '1d0/cos' + p[2]
389 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
390 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
391 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(dble' + p[2]+')'
392 elif p[1] in ['tan', 'cmath.tan'] : p[0] = 'tan(dble' + p[2]+')'
393 elif p[1] == 're': p[0] = 'dble' + p[2]
394 elif p[1] == 'im': p[0] = 'dimag' + p[2]
395 elif p[1] == 'arg': p[0] = 'arg(DCMPLX'+p[2]+')'
396 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(dcmplx' + p[2]+')'
397 elif p[1] == 'complexconjugate': p[0] = 'conjg(DCMPLX' + p[2]+')'
398 elif p[1] == 'reglog': p[0] = 'reglog(DCMPLX' + p[2] +')'
399 elif p[1] == 'reglogp': p[0] = 'reglogp(DCMPLX' + p[2] + ')'
400 elif p[1] == 'reglogm': p[0] = 'reglogm(DCMPLX' + p[2] + ')'
401
402 if p[1] in ['reglog', 'reglogp', 'reglogm']:
403 self.to_define.add(p[1])
404
406 ''' expression : expression RE2 '''
407
408 if p[2] == '.real':
409 if p[1].startswith('('):
410 p[0] = 'dble' +p[1]
411 else:
412 p[0] = 'dble(%s)' % p[1]
413 elif p[2] == '.imag':
414 if p[1].startswith('('):
415 p[0] = 'dimag' +p[1]
416 else:
417 p[0] = 'dimag(%s)' % p[1]
418 elif p[2] == '.conjugate()':
419 if p[1].startswith('('):
420 p[0] = 'conjg(DCMPLX%s)' % p[1]
421 else:
422 p[0] = 'conjg(DCMPLX(%s))' % p[1]
423
425 '''expression : PI'''
426 p[0] = 'pi'
427 self.to_define.add('pi')
428
429
431 """A parser for UFO algebraic expressions, outputting
432 Fortran-style code for quadruple precision computation."""
433
434 mp_prefix = check_param_card.ParamCard.mp_prefix
435
436
437
438
440 "expression : NUMBER"
441
442 if p[1].endswith('j'):
443 p[0] = 'CMPLX(0.000000e+00_16, %e_16 ,KIND=16)' % float(p[1][:-1])
444 else:
445 p[0] = '%e_16' % float(p[1])
446
448 "expression : VARIABLE"
449
450 p[0] = (self.mp_prefix+p[1]).lower()
451
453 'expression : expression POWER expression'
454 try:
455 p3 = float(p[3].replace('_16',''))
456
457 if p3 == int(p3):
458 p3 = str(int(p3))
459 p[0] = p[1] + "**" + p3
460 else:
461 p[0] = p[1] + "**" + p[3]
462 except Exception:
463 p[0] = p[1] + "**" + p[3]
464
466 "expression : expression IF boolexpression ELSE expression "
467 p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
468 self.to_define.add('condif')
469
471 "expression : expression IF expression ELSE expression "
472 p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\
473 %(p[3], p[1], p[5])
474 self.to_define.add('condif')
475
477 "expression : COMPLEX '(' expression ',' expression ')'"
478 p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
479
481 "expression : COND '(' expression ',' expression ',' expression ')'"
482 p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\
483 ',KIND=16),CMPLX('+p[7]+',KIND=16))'
484 self.to_define.add('cond')
485
487 "expression : RECMS '(' boolexpression ',' expression ')'"
488 p[0] = 'MP_RECMS('+p[3]+',CMPLX('+p[5]+',KIND=16))'
489 self.to_define.add('recms')
490
492 '''expression : CSC group
493 | SEC group
494 | ACSC group
495 | ASEC group
496 | RE group
497 | IM group
498 | ARG group
499 | SQRT group
500 | CONJ group
501 | REGLOG group
502 | REGLOGP group
503 | REGLOGM group
504 | TAN group
505 | ATAN group'''
506
507 if p[1] == 'csc': p[0] = '1e0_16/cos' + p[2]
508 elif p[1] == 'sec': p[0] = '1e0_16/sin' + p[2]
509 elif p[1] == 'acsc': p[0] = 'asin(1e0_16/' + p[2] + ')'
510 elif p[1] == 'asec': p[0] = 'acos(1e0_16/' + p[2] + ')'
511 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(real' + p[2]+')'
512 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan(real' + p[2]+')'
513 elif p[1] == 're': p[0] = 'real' + p[2]
514 elif p[1] == 'im': p[0] = 'imag' + p[2]
515 elif p[1] == 'arg': p[0] = 'mp_arg(CMPLX(' + p[2] + ',KIND=16))'
516 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(CMPLX(' + p[2] + ',KIND=16))'
517 elif p[1] == 'complexconjugate': p[0] = 'conjg(CMPLX(' + p[2] + ',KIND=16))'
518 elif p[1] == 'reglog': p[0] = 'mp_reglog(CMPLX(' + p[2] +',KIND=16))'
519 elif p[1] == 'reglogp': p[0] = 'mp_reglogp(CMPLX(' + p[2] + ',KIND=16))'
520 elif p[1] == 'reglogm': p[0] = 'mp_reglogm(CMPLX(' + p[2] + ',KIND=16))'
521
522 if p[1] in ['reglog', 'reglogp', 'reglogm']:
523 self.to_define.add(p[1])
524
526 ''' expression : expression RE2 '''
527
528 if p[2] == '.real':
529 if p[1].startswith('('):
530 p[0] = 'real' +p[1]
531 else:
532 p[0] = 'real(%s)' % p[1]
533 elif p[2] == '.imag':
534 if p[1].startswith('('):
535 p[0] = 'imag' +p[1]
536 else:
537 p[0] = 'imag(%s)' % p[1]
538 elif p[2] == '.conjugate()':
539 p[0] = 'conjg(CMPLX(%s,KIND=16))' % p[1]
540
541
543 '''expression : PI'''
544 p[0] = self.mp_prefix+'pi'
545 self.to_define.add('pi')
546
547
549 """A parser for UFO algebraic expressions, outputting
550 C++-style code."""
551
552 logical_equiv = {'==':'==',
553 '>=':'>=',
554 '<=':'<=',
555 '!=':'!=',
556 '>':'>',
557 '<':'<',
558 'or':'||',
559 'and':'&&'}
560
561
562
563
565 'expression : NUMBER'
566
567 if p[1].endswith('j'):
568 p[0] = 'std::complex<double>(0., %e)' % float(p[1][:-1])
569 else:
570 p[0] = ('%e' % float(p[1])).replace('e', 'd')
571
572
573 p[0] = p[1]
574
575 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000:
576 p[0] = str(int(float(p[1]))) + '.'
577
579 'expression : VARIABLE'
580 p[0] = p[1]
581
583 "expression : expression IF boolexpression ELSE expression "
584 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
585
587 "expression : expression IF expression ELSE expression "
588 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
589
591 "expression : COND '(' expression ',' expression ',' expression ')'"
592 p[0] = 'COND('+p[3]+','+p[5]+','+p[7]+')'
593
595 "expression : RECMS '(' boolexpression ',' expression ')'"
596 p[0] = 'RECMS('+p[3]+','+p[5]+')'
597
599 'expression : expression POWER expression'
600 p1=p[1]
601 p3=p[3]
602 if p[1][0] == '(' and p[1][-1] == ')':
603 p1 = p[1][1:-1]
604 if p[3][0] == '(' and p[3][-1] == ')':
605 p3 = p[3][1:-1]
606 if float(p3) == 2:
607 p[0] = '((' + p1 + ')*(' + p1 + '))'
608 elif float(p3) == 3:
609 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
610 elif float(p3) == 4:
611 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
612 elif float(p3) == 0.5 or p3 == '0.5' or p3 == '1./2' or p3 == '1/2.' or p3 == '1./2.':
613 p[0] = 'sqrt(' + p1 + ')'
614 elif float(p3) == 1./3 or p3 == '1./3' or p3 == '1/3.' or p3 == '1./3.':
615 p[0] = 'cbrt(' + p1 + ')'
616 else:
617 p[0] = 'pow(' + p1 + ',' + p3 + ')'
618
620 "expression : COMPLEX '(' expression ',' expression ')'"
621 p[0] = 'std::complex<double>(' + p[3] + ',' + p[5] + ')'
622
624 '''expression : CSC group
625 | SEC group
626 | ACSC group
627 | ASEC group
628 | TAN group
629 | ATAN group
630 | RE group
631 | IM group
632 | ARG group
633 | SQRT group
634 | CONJ group
635 | REGLOG group
636 | REGLOGP group
637 | REGLOGM group'''
638 if p[1] == 'csc': p[0] = '1./cos' + p[2]
639 elif p[1] == 'sec': p[0] = '1./sin' + p[2]
640 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
641 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
642 elif p[1] in ['atan', 'cmath.atan']: p[0] = 'atan' +p[2]
643 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan' +p[2]
644 elif p[1] == 're': p[0] = 'real' + p[2]
645 elif p[1] == 'im': p[0] = 'imag' + p[2]
646 elif p[1] == 'arg':p[0] = 'arg' + p[2]
647 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt' + p[2]
648 elif p[1] == 'complexconjugate': p[0] = 'conj' + p[2]
649 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
650 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
651 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
652
654 ''' expression : expression RE2 '''
655
656 if p[2] == '.real':
657 if p[1].startswith('('):
658 p[0] = 'real' +p[1]
659 else:
660 p[0] = 'real(%s)' % p[1]
661 elif p[2] == '.imag':
662 if p[1].startswith('('):
663 p[0] = 'imag' +p[1]
664 else:
665 p[0] = 'imag(%s)' % p[1]
666
667
669 '''expression : PI'''
670 p[0] = 'M_PI'
671
673 """An ad hoc parser for UFO algebraic expressions with if statement, outputting
674 Python-style code, with the conditional 'if' expressions simplified using
675 pre-defined set of variables specified when instanciating this parser."""
676
677 logical_equiv = {'==':'==',
678 '>=':'>=',
679 '<=':'<=',
680 '!=':'!=',
681 '>':'>',
682 '<':'<',
683 'or':' or ',
684 'and':' and '}
685
687 """Initialize the lex and yacc"""
688
689 self.changes_performed = 0
690
691 if len(args) > 0:
692 if isinstance(args[0],dict):
693 self.defined_variables = copy.copy(args[0])
694 elif isinstance(args[0],str):
695 try:
696 self.defined_variables = eval(args[0])
697 except:
698 raise ModelError, 'The expression "%s"'%str(args[0])+\
699 " given as defined variables for the UFOExpressionParserPythonIF"+\
700 " does not have a correct syntax."
701 if not isinstance(self.defined_variables, dict):
702 raise ModelError, 'The argument "%s"'%str(args[0])+\
703 " given as defined variables for the UFOExpressionParserPythonIF"+\
704 " is not a dictionary."
705 else:
706 raise ModelError, "The argument %s"%str(args[0])+\
707 " given as defined variables for the UFOExpressionParserPythonIF"+\
708 " must be either a dictionary or a string."
709 args = args[1:]
710 for key, value in self.defined_variables.items():
711 if not isinstance(key,str) or \
712 not any(isinstance(value,t) for t in [float,complex,int]):
713
714 del self.defined_variables[key]
715
716 else:
717
718
719
720 self.defined_variables = None
721
722 super(UFOExpressionParserPythonIF,self).__init__(*args, **kw)
723
724 - def parse(self, *args, **kw):
725 """ Wrapper around the parse function so as to also return the number
726 of if substitutions made."""
727 self.changes_performed = 0
728 new_expression = super(UFOExpressionParserPythonIF,self).parse(*args, **kw)
729 return new_expression, self.changes_performed
730
732 "expression : NUMBER"
733 p[0] = p[1]
734
736 "expression : VARIABLE"
737 p[0] = p[1]
738
740 'expression : expression POWER expression'
741 p[0] = p[1] + "**" + p[3]
742
744 "expression : expression IF boolexpression ELSE expression "
745 if self.defined_variables is None:
746 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
747 return
748 try:
749 p[0] = '%s'%p[1] if eval(p[3],self.defined_variables) else '%s'%p[5]
750 self.changes_performed += 1
751 except Exception:
752 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
753
755 "expression : expression IF expression ELSE expression "
756 if self.defined_variables is None:
757 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
758 return
759 try:
760 p[0] = '%s'%p[1] if eval(p[3]+'!= 0.0',self.defined_variables) else '%s'%p[5]
761 self.changes_performed += 1
762 except Exception:
763 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
764
766 "expression : COND '(' expression ',' expression ',' expression ')'"
767
768
769 p[0] = 'cond('+p[3]+','+p[5]+','+p[7]+')'
770
772 "expression : COMPLEX '(' expression ',' expression ')'"
773 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
774
776 "expression : RECMS '(' boolexpression ',' expression ')'"
777 p[0] = 'recms('+p[3]+','+p[5]+')'
778
780 '''expression : CSC group
781 | SEC group
782 | ACSC group
783 | ASEC group
784 | RE group
785 | IM group
786 | ARG group
787 | SQRT group
788 | TAN group
789 | ATAN group
790 | CONJ group
791 | REGLOG group
792 | REGLOGP group
793 | REGLOGM group'''
794 if p[1] == 'csc': p[0] = 'csc' + p[2]
795 elif p[1] == 'sec': p[0] = 'sec' + p[2]
796 elif p[1] == 'acsc': p[0] = 'acsc' + p[2]
797 elif p[1] == 'asec': p[0] = 'asec' + p[2]
798 elif p[1] in ['tan','cmath.tan']: p[0] = 'tan' + p[2]
799 elif p[1] in ['atan','cmath.atan']: p[0] = 'atan' + p[2]
800 elif p[1] == 're': p[0] = 're' + p[2]
801 elif p[1] == 'im': p[0] = 'im' + p[2]
802 elif p[1] == 'arg': p[0] = 'arg' + p[2]
803 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'cmath.sqrt' + p[2]
804 elif p[1] == 'complexconjugate': p[0] = 'complexconjugate' + p[2]
805 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
806 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
807 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
808
810 ''' expression : expression RE2 '''
811 p[0] = p[1]+p[2]
812
814 '''expression : PI'''
815
816 p[0] = 'cmath.pi'
817
818
819
820
821 if __name__ == '__main__':
822
823 if len(sys.argv) == 1:
824 print "Please specify a parser: fortran, mpfortran or c++"
825 exit()
826 if sys.argv[1] == "fortran":
827 calc = UFOExpressionParserFortran()
828 elif sys.argv[1] == "mpfortran":
829 calc = UFOExpressionParserMPFortran()
830 elif sys.argv[1] == "c++":
831 calc = UFOExpressionParserCPP()
832 elif sys.argv[1] == "aloha":
833 calc = UFOExpressionParserCPP()
834 elif sys.argv[1] == "pythonif":
835 if len(sys.argv) > 2:
836 calc = UFOExpressionParserPythonIF(sys.argv[2])
837 else:
838 calc = UFOExpressionParserPythonIF()
839 else:
840 print "Please specify a parser: fortran, mpfortran, c++ or pythonif"
841 print "You gave", sys.argv[1]
842 if len(sys.argv) > 2:
843 print "with the second argument",sys.argv[2]
844 exit()
845
846 while 1:
847 try:
848 s = raw_input('calc > ')
849 except EOFError:
850 break
851 if not s: continue
852 print calc.parse(s)
853