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', 'BUILTIN', '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)abs|bool|float|int|min|max(?=\()'
134 return t
136 r'(?<!\w)im(?=\()'
137 return t
139 r'(?<!\w)re(?=\()'
140 return t
142 r'\.real|\.imag|\.conjugate\(\)'
143 return t
144
146 r'(?<!\w)complex(?=\()'
147 return t
149 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
150 return t
152 r'[a-zA-Z_][0-9a-zA-Z_]*'
153 return t
154
155 t_NUMBER = r'([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)([eE][+-]{0,1}[0-9]+){0,1}j{0,1}'
156 t_POWER = r'\*\*'
157
158 t_ignore = " \t"
159
160 re_cmath_function = re.compile("cmath\.(?P<name>[0-9a-zA-Z_]+)")
161
163 r'\n+'
164 t.lexer.lineno += t.value.count("\n")
165
167 logger.error("Illegal character '%s'" % t.value[0])
168 t.lexer.skip(1)
169
171 """remove variable related to the latest parsing"""
172
173 return
174
175
176
177 - def build(self,**kwargs):
178 self.lexer = lex.lex(module=self, **kwargs)
179
180
181
182 precedence = (
183 ('right', 'LOGICALCOMB'),
184 ('right', 'LOGICAL'),
185 ('right','IF'),
186 ('right','ELSE'),
187 ('left','='),
188 ('left','+','-'),
189 ('left','*','/'),
190 ('left', 'RE2'),
191 ('right','UMINUS'),
192 ('left','POWER'),
193 ('right','REGLOG'),
194 ('right','REGLOGP'),
195 ('right','REGLOGM'),
196 ('right','RECMS'),
197 ('right','ARG'),
198 ('right','CSC'),
199 ('right','SEC'),
200 ('right','ACSC'),
201 ('right','ASEC'),
202 ('right','SQRT'),
203 ('right','CONJ'),
204 ('right','RE'),
205 ('right','IM'),
206 ('right', 'BUILTIN'),
207 ('right','FUNCTION'),
208 ('right','COMPLEX'),
209 ('right','COND'),
210 )
211
212
216
218 '''expression : expression '=' expression
219 | expression '+' expression
220 | expression '-' expression
221 | expression '*' expression
222 | expression '/' expression'''
223 p[0] = p[1] + p[2] + p[3]
224
226 '''boolexpression : expression LOGICAL expression'''
227 if p[2] not in self.logical_equiv:
228 p[0] = p[1] + p[2] + p[3]
229 else:
230 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
231
233 '''boolexpression : boolexpression LOGICALCOMB boolexpression'''
234 if p[2] not in self.logical_equiv:
235 p[0] = p[1] + p[2] + p[3]
236 else:
237 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
238
240 "expression : '-' expression %prec UMINUS"
241 p[0] = '-' + p[2]
242
244 "group : '(' expression ')'"
245 p[0] = '(' + p[2] +')'
246
247
249 "boolexpression : '(' boolexpression ')'"
250 p[0] = '(' + p[2] +')'
251
253 "expression : group"
254 p[0] = p[1]
255
257 "expression : FUNCTION '(' expression ')'"
258 p1 = p[1]
259 re_groups = self.re_cmath_function.match(p1)
260 if re_groups:
261 p1 = re_groups.group("name")
262 p[0] = p1 + '(' + p[3] + ')'
263
265 "expression : FUNCTION '(' expression ',' expression ')'"
266 p1 = p[1]
267 re_groups = self.re_cmath_function.match(p1)
268 if re_groups:
269 p1 = re_groups.group("name")
270 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
271
273 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
274 p1 = p[1]
275 re_groups = self.re_cmath_function.match(p1)
276 if re_groups:
277 p1 = re_groups.group("name")
278 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
279
281 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
282 p1 = p[1]
283 re_groups = self.re_cmath_function.match(p1)
284 if re_groups:
285 p1 = re_groups.group("name")
286 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
287
294
296 """A parser for UFO algebraic expressions, outputting
297 Fortran-style code."""
298
299
300 builtin_equiv = {'abs': 'ABS',
301 'bool': 'LOGICAL',
302 'float': 'REAL',
303
304 'int': 'INTEGER',
305 'min': 'MIN',
306 'max': 'MAX'
307 }
308
309
310
311
312 logical_equiv = {'==':'.EQ.',
313 '>=':'.GE.',
314 '<=':'.LE.',
315 '!=':'.NE.',
316 '>':'.GT.',
317 '<':'.LT.',
318 'or':'.OR.',
319 'and':'.AND.'}
320
321 types_def = { bool: lambda v: v ,
322 int :lambda v: 'INT(%s)' % v ,
323 float: lambda v: 'DBLE(%s)' % v,
324 complex: lambda v: 'DCMPLX(%s)' % v }
325
326 - def __init__(self, model, *args, **opts):
331
333 """remove information about object parse for previous parsing
334 """
335 self.to_define = set()
336
337
338
339
341 "expression : NUMBER"
342
343 if p[1].endswith('j'):
344 p[0] = ('DCMPLX(0d0, %e)' % float(p[1][:-1])).replace('e', 'd')
345 else:
346 p[0] = ('%e' % float(p[1])).replace('e', 'd')
347
349 "expression : VARIABLE"
350 p[0] = p[1].lower()
351
353 'expression : expression POWER expression'
354 try:
355 p3 = float(p[3].replace('d','e'))
356
357 if p3 == int(p3):
358 p3 = str(int(p3))
359 p[0] = p[1] + "**" + p3
360 else:
361 p[0] = p[1] + "**" + p[3]
362 except Exception:
363 p[0] = p[1] + "**" + p[3]
364
366 "expression : expression IF boolexpression ELSE expression "
367 p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
368 self.to_define.add('condif')
369
371 "expression : expression IF expression ELSE expression "
372 p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\
373 %(p[3], p[1], p[5])
374 self.to_define.add('condif')
375
377 "expression : COND '(' expression ',' expression ',' expression ')'"
378 p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
379 self.to_define.add('cond')
380
382 "expression : RECMS '(' boolexpression ',' expression ')'"
383 p[0] = 'RECMS('+p[3]+',DCMPLX('+p[5]+'))'
384 self.to_define.add('recms')
385
387 "expression : COMPLEX '(' expression ',' expression ')'"
388 p[0] = 'DCMPLX(' + p[3] + ',' + p[5] + ')'
389
391 '''expression : CSC group
392 | SEC group
393 | ACSC group
394 | ASEC group
395 | RE group
396 | IM group
397 | ARG group
398 | SQRT group
399 | CONJ group
400 | REGLOG group
401 | REGLOGP group
402 | REGLOGM group
403 | TAN group
404 | ATAN group
405 | BUILTIN group'''
406
407 if p[1] == 'csc': p[0] = '1d0/sin' + p[2]
408 elif p[1] == 'sec': p[0] = '1d0/cos' + p[2]
409 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
410 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
411 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(dble' + p[2]+')'
412 elif p[1] in ['tan', 'cmath.tan'] : p[0] = 'tan(dble' + p[2]+')'
413 elif p[1] == 're': p[0] = 'dble' + p[2]
414 elif p[1] == 'im': p[0] = 'dimag' + p[2]
415 elif p[1] == 'arg': p[0] = 'arg(DCMPLX'+p[2]+')'
416 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(dcmplx' + p[2]+')'
417 elif p[1] == 'complexconjugate': p[0] = 'conjg(DCMPLX' + p[2]+')'
418 elif p[1] == 'reglog': p[0] = 'reglog(DCMPLX' + p[2] +')'
419 elif p[1] == 'reglogp': p[0] = 'reglogp(DCMPLX' + p[2] + ')'
420 elif p[1] == 'reglogm': p[0] = 'reglogm(DCMPLX' + p[2] + ')'
421 elif p[1] in self.builtin_equiv: p[0] = self.builtin_equiv[p[1]] + p[2]
422
423 if p[1] in ['reglog', 'reglogp', 'reglogm']:
424 self.to_define.add(p[1])
425
427 self.modelfct = dict([(f.name,f) for f in self.model.get('functions')])
428
430 "expression : FUNCTION '(' expression ')'"
431 p1 = p[1]
432 re_groups = self.re_cmath_function.match(p1)
433 if re_groups:
434 p1 = re_groups.group("name")
435 p[0] = p1 + '(' + p[3] + ')'
436 else:
437 if not hasattr(self, 'modelfct'):
438 self.create_modelfct()
439 if p1 in self.modelfct:
440 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
441 types = [self.types_def[complex] for _ in self.modelfct[p1].arguments]
442 else:
443 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
444
445 p[0] = p1 + '(' + types[0](p[3]) + ')'
446 else:
447 p[0] = p1 + '(' + p[3] + ')'
448
449
451 '''expression : FUNCTION '(' expression ',' expression ')'
452 | FUNCTION '(' boolexpression ',' expression ')' '''
453
454 p1 = p[1]
455 re_groups = self.re_cmath_function.match(p1)
456 if re_groups:
457 p1 = re_groups.group("name")
458 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
459 else:
460 if not hasattr(self, 'modelfct'):
461 self.create_modelfct()
462 if p1 in self.modelfct:
463 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
464 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
465 else:
466 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
467
468 p[0] = p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ')'
469 else:
470 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
471
473 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
474 p1 = p[1]
475 re_groups = self.re_cmath_function.match(p1)
476 if re_groups:
477 p1 = re_groups.group("name")
478 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
479 else:
480 if not hasattr(self, 'modelfct'):
481 self.create_modelfct()
482 if p1 in self.modelfct:
483 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
484 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
485 else:
486 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
487
488 p[0] = p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ')'
489 else:
490 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
491
493 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
494 p1 = p[1]
495 re_groups = self.re_cmath_function.match(p1)
496 if re_groups:
497 p1 = re_groups.group("name")
498 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
499 else:
500 if not hasattr(self, 'modelfct'):
501 self.create_modelfct()
502 if p1 in self.modelfct:
503 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
504 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
505 else:
506 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
507 p[0] = p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ' , ' + types[3](p[9]) + ')'
508
509 else:
510 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
511
513 ''' expression : expression RE2 '''
514
515 if p[2] == '.real':
516 if p[1].startswith('('):
517 p[0] = 'dble' +p[1]
518 else:
519 p[0] = 'dble(%s)' % p[1]
520 elif p[2] == '.imag':
521 if p[1].startswith('('):
522 p[0] = 'dimag' +p[1]
523 else:
524 p[0] = 'dimag(%s)' % p[1]
525 elif p[2] == '.conjugate()':
526 if p[1].startswith('('):
527 p[0] = 'conjg(DCMPLX%s)' % p[1]
528 else:
529 p[0] = 'conjg(DCMPLX(%s))' % p[1]
530
532 '''expression : PI'''
533 p[0] = 'pi'
534 self.to_define.add('pi')
535
536
538 """A parser for UFO algebraic expressions, outputting
539 Fortran-style code for quadruple precision computation."""
540
541 mp_prefix = check_param_card.ParamCard.mp_prefix
542 types_def = { bool: lambda v: v ,
543 int :lambda v: 'mp__%s' % v if not v.startswith(('(','mp__','1','2','3','4','5','6','7','8','9','0','-')) else v,
544 float: lambda v: 'mp__%s' % v if not v.startswith(('(','mp__','1','2','3','4','5','6','7','8','9','0','-')) else v,
545 complex: lambda v: 'CMPLX(mp__%s, KIND=16)' % v if not v.startswith(('(','mp__','1','2','3','4','5','6','7','8','9','0','-' )) else 'CMPLX(%s, KIND=16)' % v}
546
547 builtin_equiv = {'abs': lambda v: 'ABS' +v,
548 'bool': lambda v: 'LOGICAL' +v ,
549 'float': lambda v: 'REAL(' +v+", KIND=16)",
550 'complex': lambda v: 'COMPLEX(' +v+", KIND=16)",
551 'int': lambda v: 'INTEGER' +v ,
552 'min': lambda v: 'MIN' +v ,
553 'max': lambda v: 'MAX' +v
554 }
555
556
557
558
560 "expression : NUMBER"
561
562 if p[1].endswith('j'):
563 p[0] = 'CMPLX(0.000000e+00_16, %e_16 ,KIND=16)' % float(p[1][:-1])
564 else:
565 p[0] = '%e_16' % float(p[1])
566
568 "expression : VARIABLE"
569
570 p[0] = (self.mp_prefix+p[1]).lower()
571
573 'expression : expression POWER expression'
574 try:
575 p3 = float(p[3].replace('_16',''))
576
577 if p3 == int(p3):
578 p3 = str(int(p3))
579 p[0] = p[1] + "**" + p3
580 else:
581 p[0] = p[1] + "**" + p[3]
582 except Exception:
583 p[0] = p[1] + "**" + p[3]
584
586 "expression : FUNCTION '(' expression ')'"
587 p1 = p[1]
588 re_groups = self.re_cmath_function.match(p1)
589 if re_groups:
590 p1 = re_groups.group("name")
591 p[0] = p1 + '(' + p[3] + ')'
592 else:
593 if not hasattr(self, 'modelfct'):
594 self.create_modelfct()
595 if p1 in self.modelfct:
596 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
597 types = [self.types_def[complex] for _ in self.modelfct[p1].arguments]
598 else:
599 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
600
601 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ')'
602 else:
603 p[0] = 'MP_' + p1 + '(' + p[3] + ')'
604
605
607 '''expression : FUNCTION '(' expression ',' expression ')'
608 | FUNCTION '(' boolexpression ',' expression ')' '''
609
610 p1 = p[1]
611 re_groups = self.re_cmath_function.match(p1)
612 if re_groups:
613 p1 = re_groups.group("name")
614 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
615 else:
616 if not hasattr(self, 'modelfct'):
617 self.create_modelfct()
618 if p1 in self.modelfct:
619 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
620 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
621 else:
622 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
623
624 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ')'
625 else:
626 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ')'
627
629 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
630 p1 = p[1]
631 re_groups = self.re_cmath_function.match(p1)
632 if re_groups:
633 p1 = re_groups.group("name")
634 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
635 else:
636 if not hasattr(self, 'modelfct'):
637 self.create_modelfct()
638 if p1 in self.modelfct:
639 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
640 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
641 else:
642 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
643
644 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ')'
645 else:
646 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
647
649 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
650 p1 = p[1]
651 re_groups = self.re_cmath_function.match(p1)
652 if re_groups:
653 p1 = re_groups.group("name")
654 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
655 else:
656 if not hasattr(self, 'modelfct'):
657 self.create_modelfct()
658 if p1 in self.modelfct:
659 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
660 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
661 else:
662 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
663 misc.sprint(types)
664 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ' , ' + types[3](p[9]) + ')'
665
666 else:
667 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
668
669
670
672 "expression : expression IF boolexpression ELSE expression "
673 p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
674 self.to_define.add('condif')
675
677 "expression : expression IF expression ELSE expression "
678 p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\
679 %(p[3], p[1], p[5])
680 self.to_define.add('condif')
681
683 "expression : COMPLEX '(' expression ',' expression ')'"
684 p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
685
687 "expression : COND '(' expression ',' expression ',' expression ')'"
688 p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\
689 ',KIND=16),CMPLX('+p[7]+',KIND=16))'
690 self.to_define.add('cond')
691
693 "expression : RECMS '(' boolexpression ',' expression ')'"
694 p[0] = 'MP_RECMS('+p[3]+',CMPLX('+p[5]+',KIND=16))'
695 self.to_define.add('recms')
696
698 '''expression : CSC group
699 | SEC group
700 | ACSC group
701 | ASEC group
702 | RE group
703 | IM group
704 | ARG group
705 | SQRT group
706 | CONJ group
707 | REGLOG group
708 | REGLOGP group
709 | REGLOGM group
710 | TAN group
711 | ATAN group
712 | BUILTIN group'''
713
714 if p[1] == 'csc': p[0] = '1e0_16/cos' + p[2]
715 elif p[1] == 'sec': p[0] = '1e0_16/sin' + p[2]
716 elif p[1] == 'acsc': p[0] = 'asin(1e0_16/' + p[2] + ')'
717 elif p[1] == 'asec': p[0] = 'acos(1e0_16/' + p[2] + ')'
718 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(real' + p[2]+')'
719 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan(real' + p[2]+')'
720 elif p[1] == 're': p[0] = 'real' + p[2]
721 elif p[1] == 'im': p[0] = 'imag' + p[2]
722 elif p[1] == 'arg': p[0] = 'mp_arg(CMPLX(' + p[2] + ',KIND=16))'
723 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(CMPLX(' + p[2] + ',KIND=16))'
724 elif p[1] == 'complexconjugate': p[0] = 'conjg(CMPLX(' + p[2] + ',KIND=16))'
725 elif p[1] == 'reglog': p[0] = 'mp_reglog(CMPLX(' + p[2] +',KIND=16))'
726 elif p[1] == 'reglogp': p[0] = 'mp_reglogp(CMPLX(' + p[2] + ',KIND=16))'
727 elif p[1] == 'reglogm': p[0] = 'mp_reglogm(CMPLX(' + p[2] + ',KIND=16))'
728 elif p[1] in self.builtin_equiv: p[0] = self.builtin_equiv[p[1]](p[2])
729
730 if p[1] in ['reglog', 'reglogp', 'reglogm']:
731 self.to_define.add(p[1])
732
734 ''' expression : expression RE2 '''
735
736 if p[2] == '.real':
737 if p[1].startswith('('):
738 p[0] = 'real' +p[1]
739 else:
740 p[0] = 'real(%s)' % p[1]
741 elif p[2] == '.imag':
742 if p[1].startswith('('):
743 p[0] = 'imag' +p[1]
744 else:
745 p[0] = 'imag(%s)' % p[1]
746 elif p[2] == '.conjugate()':
747 p[0] = 'conjg(CMPLX(%s,KIND=16))' % p[1]
748
749
751 '''expression : PI'''
752 p[0] = self.mp_prefix+'pi'
753 self.to_define.add('pi')
754
755
757 """A parser for UFO algebraic expressions, outputting
758 C++-style code."""
759
760 logical_equiv = {'==':'==',
761 '>=':'>=',
762 '<=':'<=',
763 '!=':'!=',
764 '>':'>',
765 '<':'<',
766 'or':'||',
767 'and':'&&'}
768
769 builtin_equiv = {'abs': 'ABS',
770 'bool': 'bool',
771 'float': 'float',
772
773 'int': 'int',
774 'min': 'min',
775 'max': 'max'
776 }
777
778
779
780
782 'expression : NUMBER'
783
784 if p[1].endswith('j'):
785 p[0] = 'std::complex<double>(0., %e)' % float(p[1][:-1])
786 else:
787 p[0] = ('%e' % float(p[1])).replace('e', 'd')
788
789
790 p[0] = p[1]
791
792 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000:
793 p[0] = str(int(float(p[1]))) + '.'
794
796 'expression : VARIABLE'
797 p[0] = p[1]
798
800 "expression : expression IF boolexpression ELSE expression "
801 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
802
804 "expression : expression IF expression ELSE expression "
805 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
806
808 "expression : COND '(' expression ',' expression ',' expression ')'"
809 p[0] = 'COND('+p[3]+','+p[5]+','+p[7]+')'
810
812 "expression : RECMS '(' boolexpression ',' expression ')'"
813 p[0] = 'RECMS('+p[3]+','+p[5]+')'
814
816 'expression : expression POWER expression'
817 p1=p[1]
818 p3=p[3]
819 if p[1][0] == '(' and p[1][-1] == ')':
820 p1 = p[1][1:-1]
821 if p[3][0] == '(' and p[3][-1] == ')':
822 p3 = p[3][1:-1]
823 if float(p3) == 2:
824 p[0] = '((' + p1 + ')*(' + p1 + '))'
825 elif float(p3) == 3:
826 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
827 elif float(p3) == 4:
828 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
829 elif float(p3) == 0.5 or p3 == '0.5' or p3 == '1./2' or p3 == '1/2.' or p3 == '1./2.':
830 p[0] = 'sqrt(' + p1 + ')'
831 elif float(p3) == 1./3 or p3 == '1./3' or p3 == '1/3.' or p3 == '1./3.':
832 p[0] = 'cbrt(' + p1 + ')'
833 else:
834 p[0] = 'pow(' + p1 + ',' + p3 + ')'
835
837 "expression : COMPLEX '(' expression ',' expression ')'"
838 p[0] = 'std::complex<double>(' + p[3] + ',' + p[5] + ')'
839
841 '''expression : CSC group
842 | SEC group
843 | ACSC group
844 | ASEC group
845 | TAN group
846 | ATAN group
847 | RE group
848 | IM group
849 | ARG group
850 | SQRT group
851 | CONJ group
852 | REGLOG group
853 | REGLOGP group
854 | REGLOGM group
855 | BUILTIN group '''
856 if p[1] == 'csc': p[0] = '1./cos' + p[2]
857 elif p[1] == 'sec': p[0] = '1./sin' + p[2]
858 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
859 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
860 elif p[1] in ['atan', 'cmath.atan']: p[0] = 'atan' +p[2]
861 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan' +p[2]
862 elif p[1] == 're': p[0] = 'real' + p[2]
863 elif p[1] == 'im': p[0] = 'imag' + p[2]
864 elif p[1] == 'arg':p[0] = 'arg' + p[2]
865 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt' + p[2]
866 elif p[1] == 'complexconjugate': p[0] = 'conj' + p[2]
867 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
868 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
869 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
870 elif p[1] in self.buitin_equiv: p[0] = self.builtin_equiv[p[1]] + p[2]
871
872
874 ''' expression : expression RE2 '''
875
876 if p[2] == '.real':
877 if p[1].startswith('('):
878 p[0] = 'real' +p[1]
879 else:
880 p[0] = 'real(%s)' % p[1]
881 elif p[2] == '.imag':
882 if p[1].startswith('('):
883 p[0] = 'imag' +p[1]
884 else:
885 p[0] = 'imag(%s)' % p[1]
886
887
889 '''expression : PI'''
890 p[0] = 'M_PI'
891
893 """An ad hoc parser for UFO algebraic expressions with if statement, outputting
894 Python-style code, with the conditional 'if' expressions simplified using
895 pre-defined set of variables specified when instanciating this parser."""
896
897 logical_equiv = {'==':'==',
898 '>=':'>=',
899 '<=':'<=',
900 '!=':'!=',
901 '>':'>',
902 '<':'<',
903 'or':' or ',
904 'and':' and '}
905
906 builtin_equiv = {'abs': 'abs',
907 'bool': 'bool',
908 'float': 'float',
909
910 'int': 'int',
911 'min': 'min',
912 'max': 'max'
913 }
914
916 """Initialize the lex and yacc"""
917
918 self.changes_performed = 0
919
920 if len(args) > 0:
921 if isinstance(args[0],dict):
922 self.defined_variables = copy.copy(args[0])
923 elif isinstance(args[0],str):
924 try:
925 self.defined_variables = eval(args[0])
926 except:
927 raise ModelError, 'The expression "%s"'%str(args[0])+\
928 " given as defined variables for the UFOExpressionParserPythonIF"+\
929 " does not have a correct syntax."
930 if not isinstance(self.defined_variables, dict):
931 raise ModelError, 'The argument "%s"'%str(args[0])+\
932 " given as defined variables for the UFOExpressionParserPythonIF"+\
933 " is not a dictionary."
934 else:
935 raise ModelError, "The argument %s"%str(args[0])+\
936 " given as defined variables for the UFOExpressionParserPythonIF"+\
937 " must be either a dictionary or a string."
938 args = args[1:]
939 for key, value in self.defined_variables.items():
940 if not isinstance(key,str) or \
941 not any(isinstance(value,t) for t in [float,complex,int]):
942
943 del self.defined_variables[key]
944
945 else:
946
947
948
949 self.defined_variables = None
950
951 super(UFOExpressionParserPythonIF,self).__init__(*args, **kw)
952
953 - def parse(self, *args, **kw):
954 """ Wrapper around the parse function so as to also return the number
955 of if substitutions made."""
956 self.changes_performed = 0
957 new_expression = super(UFOExpressionParserPythonIF,self).parse(*args, **kw)
958 return new_expression, self.changes_performed
959
961 "expression : NUMBER"
962 p[0] = p[1]
963
965 "expression : VARIABLE"
966 p[0] = p[1]
967
969 'expression : expression POWER expression'
970 p[0] = p[1] + "**" + p[3]
971
973 "expression : expression IF boolexpression ELSE expression "
974 if self.defined_variables is None:
975 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
976 return
977 try:
978 p[0] = '%s'%p[1] if eval(p[3],self.defined_variables) else '%s'%p[5]
979 self.changes_performed += 1
980 except Exception:
981 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
982
984 "expression : expression IF expression ELSE expression "
985 if self.defined_variables is None:
986 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
987 return
988 try:
989 p[0] = '%s'%p[1] if eval(p[3]+'!= 0.0',self.defined_variables) else '%s'%p[5]
990 self.changes_performed += 1
991 except Exception:
992 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
993
995 "expression : COND '(' expression ',' expression ',' expression ')'"
996
997
998 p[0] = 'cond('+p[3]+','+p[5]+','+p[7]+')'
999
1001 "expression : COMPLEX '(' expression ',' expression ')'"
1002 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
1003
1005 "expression : RECMS '(' boolexpression ',' expression ')'"
1006 p[0] = 'recms('+p[3]+','+p[5]+')'
1007
1009 '''expression : CSC group
1010 | SEC group
1011 | ACSC group
1012 | ASEC group
1013 | RE group
1014 | IM group
1015 | ARG group
1016 | SQRT group
1017 | TAN group
1018 | ATAN group
1019 | CONJ group
1020 | REGLOG group
1021 | REGLOGP group
1022 | REGLOGM group
1023 | BUILTIN group'''
1024 if p[1] == 'csc': p[0] = 'csc' + p[2]
1025 elif p[1] == 'sec': p[0] = 'sec' + p[2]
1026 elif p[1] == 'acsc': p[0] = 'acsc' + p[2]
1027 elif p[1] == 'asec': p[0] = 'asec' + p[2]
1028 elif p[1] in ['tan','cmath.tan']: p[0] = 'tan' + p[2]
1029 elif p[1] in ['atan','cmath.atan']: p[0] = 'atan' + p[2]
1030 elif p[1] == 're': p[0] = 're' + p[2]
1031 elif p[1] == 'im': p[0] = 'im' + p[2]
1032 elif p[1] == 'arg': p[0] = 'arg' + p[2]
1033 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'cmath.sqrt' + p[2]
1034 elif p[1] == 'complexconjugate': p[0] = 'complexconjugate' + p[2]
1035 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
1036 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
1037 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
1038 elif p[1] in self.builtin_equiv: p[0] = self.builtin_equiv[p[1]] + p[2]
1039
1041 ''' expression : expression RE2 '''
1042 p[0] = p[1]+p[2]
1043
1045 '''expression : PI'''
1046
1047 p[0] = 'cmath.pi'
1048
1049
1050
1051
1052 if __name__ == '__main__':
1053
1054 if len(sys.argv) == 1:
1055 print "Please specify a parser: fortran, mpfortran or c++"
1056 exit()
1057 if sys.argv[1] == "fortran":
1058 calc = UFOExpressionParserFortran()
1059 elif sys.argv[1] == "mpfortran":
1060 calc = UFOExpressionParserMPFortran()
1061 elif sys.argv[1] == "c++":
1062 calc = UFOExpressionParserCPP()
1063 elif sys.argv[1] == "aloha":
1064 calc = UFOExpressionParserCPP()
1065 elif sys.argv[1] == "pythonif":
1066 if len(sys.argv) > 2:
1067 calc = UFOExpressionParserPythonIF(sys.argv[2])
1068 else:
1069 calc = UFOExpressionParserPythonIF()
1070 else:
1071 print "Please specify a parser: fortran, mpfortran, c++ or pythonif"
1072 print "You gave", sys.argv[1]
1073 if len(sys.argv) > 2:
1074 print "with the second argument",sys.argv[2]
1075 exit()
1076
1077 while 1:
1078 try:
1079 s = raw_input('calc > ')
1080 except EOFError:
1081 break
1082 if not s: continue
1083 print calc.parse(s)
1084