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'
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
244 "boolexpression : '(' boolexpression ')'"
245 p[0] = '(' + p[2] +')'
246
248 "expression : group"
249 p[0] = p[1]
250
252 "expression : FUNCTION '(' expression ')'"
253 p1 = p[1]
254 re_groups = self.re_cmath_function.match(p1)
255 if re_groups:
256 p1 = re_groups.group("name")
257 p[0] = p1 + '(' + p[3] + ')'
258
260 "expression : FUNCTION '(' expression ',' expression ')'"
261 p1 = p[1]
262 re_groups = self.re_cmath_function.match(p1)
263 if re_groups:
264 p1 = re_groups.group("name")
265 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
266
273
275 """A parser for UFO algebraic expressions, outputting
276 Fortran-style code."""
277
278
279
280
281
282
283 logical_equiv = {'==':'.EQ.',
284 '>=':'.GE.',
285 '<=':'.LE.',
286 '!=':'.NE.',
287 '>':'.GT.',
288 '<':'.LT.',
289 'or':'.OR.',
290 'and':'.AND.'}
291
296
298 """remove information about object parse for previous parsing
299 """
300 self.to_define = set()
301
302
303
304
306 "expression : NUMBER"
307 if p[1].endswith('j'):
308 p[0] = ('DCMPLX(0d0, %e)' % float(p[1][:-1])).replace('e', 'd')
309 else:
310 p[0] = ('%e' % float(p[1])).replace('e', 'd')
311
313 "expression : VARIABLE"
314 p[0] = p[1].lower()
315
317 'expression : expression POWER expression'
318 try:
319 p3 = float(p[3].replace('d','e'))
320
321 if p3 == int(p3):
322 p3 = str(int(p3))
323 p[0] = p[1] + "**" + p3
324 else:
325 p[0] = p[1] + "**" + p[3]
326 except Exception:
327 p[0] = p[1] + "**" + p[3]
328
330 "expression : expression IF boolexpression ELSE expression "
331 p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
332 self.to_define.add('condif')
333
335 "expression : expression IF expression ELSE expression "
336 p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\
337 %(p[3], p[1], p[5])
338 self.to_define.add('condif')
339
341 "expression : COND '(' expression ',' expression ',' expression ')'"
342 p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
343 self.to_define.add('cond')
344
346 "expression : RECMS '(' boolexpression ',' expression ')'"
347 p[0] = 'RECMS('+p[3]+',DCMPLX('+p[5]+'))'
348 self.to_define.add('recms')
349
351 "expression : COMPLEX '(' expression ',' expression ')'"
352 p[0] = 'DCMPLX(' + p[3] + ',' + p[5] + ')'
353
355 '''expression : CSC group
356 | SEC group
357 | ACSC group
358 | ASEC group
359 | RE group
360 | IM group
361 | ARG group
362 | SQRT group
363 | CONJ group
364 | REGLOG group
365 | REGLOGP group
366 | REGLOGM group
367 | TAN group
368 | ATAN group'''
369
370 if p[1] == 'csc': p[0] = '1d0/sin' + p[2]
371 elif p[1] == 'sec': p[0] = '1d0/cos' + p[2]
372 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
373 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
374 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(dble' + p[2]+')'
375 elif p[1] in ['tan', 'cmath.tan'] : p[0] = 'tan(dble' + p[2]+')'
376 elif p[1] == 're': p[0] = 'dble' + p[2]
377 elif p[1] == 'im': p[0] = 'dimag' + p[2]
378 elif p[1] == 'arg': p[0] = 'arg(DCMPLX'+p[2]+')'
379 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(dcmplx' + p[2]+')'
380 elif p[1] == 'complexconjugate': p[0] = 'conjg(DCMPLX' + p[2]+')'
381 elif p[1] == 'reglog': p[0] = 'reglog(DCMPLX' + p[2] +')'
382 elif p[1] == 'reglogp': p[0] = 'reglogp(DCMPLX' + p[2] + ')'
383 elif p[1] == 'reglogm': p[0] = 'reglogm(DCMPLX' + p[2] + ')'
384
385 if p[1] in ['reglog', 'reglogp', 'reglogm']:
386 self.to_define.add(p[1])
387
389 ''' expression : expression RE2 '''
390
391 if p[2] == '.real':
392 if p[1].startswith('('):
393 p[0] = 'dble' +p[1]
394 else:
395 p[0] = 'dble(%s)' % p[1]
396 elif p[2] == '.imag':
397 if p[1].startswith('('):
398 p[0] = 'dimag' +p[1]
399 else:
400 p[0] = 'dimag(%s)' % p[1]
401
403 '''expression : PI'''
404 p[0] = 'pi'
405 self.to_define.add('pi')
406
408 """A parser for UFO algebraic expressions, outputting
409 Fortran-style code for quadruple precision computation."""
410
411 mp_prefix = check_param_card.ParamCard.mp_prefix
412
413
414
415
417 "expression : NUMBER"
418
419 if p[1].endswith('j'):
420 p[0] = 'CMPLX(0.000000e+00_16, %e_16 ,KIND=16)' % float(p[1][:-1])
421 else:
422 p[0] = '%e_16' % float(p[1])
423
425 "expression : VARIABLE"
426
427 p[0] = (self.mp_prefix+p[1]).lower()
428
430 'expression : expression POWER expression'
431 try:
432 p3 = float(p[3].replace('_16',''))
433
434 if p3 == int(p3):
435 p3 = str(int(p3))
436 p[0] = p[1] + "**" + p3
437 else:
438 p[0] = p[1] + "**" + p[3]
439 except Exception:
440 p[0] = p[1] + "**" + p[3]
441
443 "expression : expression IF boolexpression ELSE expression "
444 p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
445 self.to_define.add('mp_condif')
446
448 "expression : expression IF expression ELSE expression "
449 p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\
450 %(p[3], p[1], p[5])
451 self.to_define.add('mp_condif')
452
454 "expression : COMPLEX '(' expression ',' expression ')'"
455 p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
456
458 "expression : COND '(' expression ',' expression ',' expression ')'"
459 p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\
460 ',KIND=16),CMPLX('+p[7]+',KIND=16))'
461 self.to_define.add('mp_cond')
462
464 "expression : RECMS '(' boolexpression ',' expression ')'"
465 p[0] = 'MP_RECMS('+p[3]+',CMPLX('+p[5]+',KIND=16))'
466 self.to_define.add('mp_recms')
467
469 '''expression : CSC group
470 | SEC group
471 | ACSC group
472 | ASEC group
473 | RE group
474 | IM group
475 | ARG group
476 | SQRT group
477 | CONJ group
478 | REGLOG group
479 | REGLOGP group
480 | REGLOGM group
481 | TAN group
482 | ATAN group'''
483
484 if p[1] == 'csc': p[0] = '1e0_16/cos' + p[2]
485 elif p[1] == 'sec': p[0] = '1e0_16/sin' + p[2]
486 elif p[1] == 'acsc': p[0] = 'asin(1e0_16/' + p[2] + ')'
487 elif p[1] == 'asec': p[0] = 'acos(1e0_16/' + p[2] + ')'
488 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(real' + p[2]+')'
489 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan(real' + p[2]+')'
490 elif p[1] == 're': p[0] = 'real' + p[2]
491 elif p[1] == 'im': p[0] = 'imag' + p[2]
492 elif p[1] == 'arg': p[0] = 'mp_arg(CMPLX(' + p[2] + ',KIND=16))'
493 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(CMPLX(' + p[2] + ',KIND=16))'
494 elif p[1] == 'complexconjugate': p[0] = 'conjg(CMPLX(' + p[2] + ',KIND=16))'
495 elif p[1] == 'reglog': p[0] = 'mp_reglog(CMPLX(' + p[2] +',KIND=16))'
496 elif p[1] == 'reglogp': p[0] = 'mp_reglogp(CMPLX(' + p[2] + ',KIND=16))'
497 elif p[1] == 'reglogm': p[0] = 'mp_reglogm(CMPLX(' + p[2] + ',KIND=16))'
498
499 if p[1] in ['reglog', 'reglogp', 'reglogm']:
500 self.to_define.add(p[1])
501
503 ''' expression : expression RE2 '''
504
505 if p[2] == '.real':
506 if p[1].startswith('('):
507 p[0] = 'real' +p[1]
508 else:
509 p[0] = 'real(%s)' % p[1]
510 elif p[2] == '.imag':
511 if p[1].startswith('('):
512 p[0] = 'imag' +p[1]
513 else:
514 p[0] = 'imag(%s)' % p[1]
515
516
521
523 """A parser for UFO algebraic expressions, outputting
524 C++-style code."""
525
526 logical_equiv = {'==':'==',
527 '>=':'>=',
528 '<=':'<=',
529 '!=':'!=',
530 '>':'>',
531 '<':'<',
532 'or':'||',
533 'and':'&&'}
534
535
536
537
539 'expression : NUMBER'
540
541 if p[1].endswith('j'):
542 p[0] = 'std::complex<double>(0., %e)' % float(p[1][:-1])
543 else:
544 p[0] = ('%e' % float(p[1])).replace('e', 'd')
545
546
547 p[0] = p[1]
548
549 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000:
550 p[0] = str(int(float(p[1]))) + '.'
551
553 'expression : VARIABLE'
554 p[0] = p[1]
555
557 "expression : expression IF boolexpression ELSE expression "
558 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
559
561 "expression : expression IF expression ELSE expression "
562 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
563
565 "expression : COND '(' expression ',' expression ',' expression ')'"
566 p[0] = 'COND('+p[3]+','+p[5]+','+p[7]+')'
567
569 "expression : RECMS '(' boolexpression ',' expression ')'"
570 p[0] = 'RECMS('+p[3]+','+p[5]+')'
571
573 'expression : expression POWER expression'
574 p1=p[1]
575 p3=p[3]
576 if p[1][0] == '(' and p[1][-1] == ')':
577 p1 = p[1][1:-1]
578 if p[3][0] == '(' and p[3][-1] == ')':
579 p3 = p[3][1:-1]
580 if float(p3) == 2:
581 p[0] = '((' + p1 + ')*(' + p1 + '))'
582 elif float(p3) == 3:
583 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
584 elif float(p3) == 4:
585 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
586 elif float(p3) == 0.5 or p3 == '0.5' or p3 == '1./2' or p3 == '1/2.' or p3 == '1./2.':
587 p[0] = 'sqrt(' + p1 + ')'
588 elif float(p3) == 1./3 or p3 == '1./3' or p3 == '1/3.' or p3 == '1./3.':
589 p[0] = 'cbrt(' + p1 + ')'
590 else:
591 p[0] = 'pow(' + p1 + ',' + p3 + ')'
592
594 "expression : COMPLEX '(' expression ',' expression ')'"
595 p[0] = 'std::complex<double>(' + p[3] + ',' + p[5] + ')'
596
598 '''expression : CSC group
599 | SEC group
600 | ACSC group
601 | ASEC group
602 | TAN group
603 | ATAN group
604 | RE group
605 | IM group
606 | ARG group
607 | SQRT group
608 | CONJ group
609 | REGLOG group
610 | REGLOGP group
611 | REGLOGM group'''
612 if p[1] == 'csc': p[0] = '1./cos' + p[2]
613 elif p[1] == 'sec': p[0] = '1./sin' + p[2]
614 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
615 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
616 elif p[1] in ['atan', 'cmath.atan']: p[0] = 'atan' +p[2]
617 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan' +p[2]
618 elif p[1] == 're': p[0] = 'real' + p[2]
619 elif p[1] == 'im': p[0] = 'imag' + p[2]
620 elif p[1] == 'arg':p[0] = 'arg' + p[2]
621 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt' + p[2]
622 elif p[1] == 'complexconjugate': p[0] = 'conj' + p[2]
623 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
624 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
625 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
626
628 ''' expression : expression RE2 '''
629
630 if p[2] == '.real':
631 if p[1].startswith('('):
632 p[0] = 'real' +p[1]
633 else:
634 p[0] = 'real(%s)' % p[1]
635 elif p[2] == '.imag':
636 if p[1].startswith('('):
637 p[0] = 'imag' +p[1]
638 else:
639 p[0] = 'imag(%s)' % p[1]
640
641
643 '''expression : PI'''
644 p[0] = 'M_PI'
645
647 """An ad hoc parser for UFO algebraic expressions with if statement, outputting
648 Python-style code, with the conditional 'if' expressions simplified using
649 pre-defined set of variables specified when instanciating this parser."""
650
651 logical_equiv = {'==':'==',
652 '>=':'>=',
653 '<=':'<=',
654 '!=':'!=',
655 '>':'>',
656 '<':'<',
657 'or':' or ',
658 'and':' and '}
659
661 """Initialize the lex and yacc"""
662
663 self.changes_performed = 0
664
665 if len(args) > 0:
666 if isinstance(args[0],dict):
667 self.defined_variables = copy.copy(args[0])
668 elif isinstance(args[0],str):
669 try:
670 self.defined_variables = eval(args[0])
671 except:
672 raise ModelError, 'The expression "%s"'%str(args[0])+\
673 " given as defined variables for the UFOExpressionParserPythonIF"+\
674 " does not have a correct syntax."
675 if not isinstance(self.defined_variables, dict):
676 raise ModelError, 'The argument "%s"'%str(args[0])+\
677 " given as defined variables for the UFOExpressionParserPythonIF"+\
678 " is not a dictionary."
679 else:
680 raise ModelError, "The argument %s"%str(args[0])+\
681 " given as defined variables for the UFOExpressionParserPythonIF"+\
682 " must be either a dictionary or a string."
683 args = args[1:]
684 for key, value in self.defined_variables.items():
685 if not isinstance(key,str) or \
686 not any(isinstance(value,t) for t in [float,complex,int]):
687
688 del self.defined_variables[key]
689
690 else:
691
692
693
694 self.defined_variables = None
695
696 super(UFOExpressionParserPythonIF,self).__init__(*args, **kw)
697
698 - def parse(self, *args, **kw):
699 """ Wrapper around the parse function so as to also return the number
700 of if substitutions made."""
701 self.changes_performed = 0
702 new_expression = super(UFOExpressionParserPythonIF,self).parse(*args, **kw)
703 return new_expression, self.changes_performed
704
706 "expression : NUMBER"
707 p[0] = p[1]
708
710 "expression : VARIABLE"
711 p[0] = p[1]
712
714 'expression : expression POWER expression'
715 p[0] = p[1] + "**" + p[3]
716
718 "expression : expression IF boolexpression ELSE expression "
719 if self.defined_variables is None:
720 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
721 return
722 try:
723 p[0] = '%s'%p[1] if eval(p[3],self.defined_variables) else '%s'%p[5]
724 self.changes_performed += 1
725 except Exception:
726 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
727
729 "expression : expression IF expression ELSE expression "
730 if self.defined_variables is None:
731 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
732 return
733 try:
734 p[0] = '%s'%p[1] if eval(p[3]+'!= 0.0',self.defined_variables) else '%s'%p[5]
735 self.changes_performed += 1
736 except Exception:
737 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
738
740 "expression : COND '(' expression ',' expression ',' expression ')'"
741
742
743 p[0] = 'cond('+p[3]+','+p[5]+','+p[7]+')'
744
746 "expression : COMPLEX '(' expression ',' expression ')'"
747 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
748
750 "expression : RECMS '(' boolexpression ',' expression ')'"
751 p[0] = 'recms('+p[3]+','+p[5]+')'
752
754 '''expression : CSC group
755 | SEC group
756 | ACSC group
757 | ASEC group
758 | RE group
759 | IM group
760 | ARG group
761 | SQRT group
762 | TAN group
763 | ATAN group
764 | CONJ group
765 | REGLOG group
766 | REGLOGP group
767 | REGLOGM group'''
768 if p[1] == 'csc': p[0] = 'csc' + p[2]
769 elif p[1] == 'sec': p[0] = 'sec' + p[2]
770 elif p[1] == 'acsc': p[0] = 'acsc' + p[2]
771 elif p[1] == 'asec': p[0] = 'asec' + p[2]
772 elif p[1] in ['tan','cmath.tan']: p[0] = 'tan' + p[2]
773 elif p[1] in ['atan','cmath.atan']: p[0] = 'atan' + p[2]
774 elif p[1] == 're': p[0] = 're' + p[2]
775 elif p[1] == 'im': p[0] = 'im' + p[2]
776 elif p[1] == 'arg': p[0] = 'arg' + p[2]
777 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'cmath.sqrt' + p[2]
778 elif p[1] == 'complexconjugate': p[0] = 'complexconjugate' + p[2]
779 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
780 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
781 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
782
784 ''' expression : expression RE2 '''
785 p[0] = p[1]+p[2]
786
788 '''expression : PI'''
789 p[0] = 'cmath.pi'
790
791
792
793
794 if __name__ == '__main__':
795
796 if len(sys.argv) == 1:
797 print "Please specify a parser: fortran, mpfortran or c++"
798 exit()
799 if sys.argv[1] == "fortran":
800 calc = UFOExpressionParserFortran()
801 elif sys.argv[1] == "mpfortran":
802 calc = UFOExpressionParserMPFortran()
803 elif sys.argv[1] == "c++":
804 calc = UFOExpressionParserCPP()
805 elif sys.argv[1] == "aloha":
806 calc = UFOExpressionParserCPP()
807 elif sys.argv[1] == "pythonif":
808 if len(sys.argv) > 2:
809 calc = UFOExpressionParserPythonIF(sys.argv[2])
810 else:
811 calc = UFOExpressionParserPythonIF()
812 else:
813 print "Please specify a parser: fortran, mpfortran, c++ or pythonif"
814 print "You gave", sys.argv[1]
815 if len(sys.argv) > 2:
816 print "with the second argument",sys.argv[2]
817 exit()
818
819 while 1:
820 try:
821 s = raw_input('calc > ')
822 except EOFError:
823 break
824 if not s: continue
825 print calc.parse(s)
826