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 from __future__ import absolute_import
21 from __future__ import print_function
22 import logging
23 import os
24 import re
25 import sys
26 import copy
27 from six.moves import input
28
29 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
30 sys.path.append(os.path.join(root_path, os.path.pardir))
31
32 import madgraph.various.misc as misc
33
34 from madgraph import MadGraph5Error
35 import vendor.ply.lex as lex
36 import vendor.ply.yacc as yacc
37 import models.check_param_card as check_param_card
38
39 logger = logging.getLogger('madgraph.ufo_parsers')
40
41
42
44 """Appropriate Error for a wrong parsing"""
45
47 """A base class for parsers for algebraic expressions coming from UFO."""
48
49 parsed_string = ""
50 logical_equiv = {}
51
53 """Initialize the lex and yacc"""
54
55 modname = self.__class__.__name__
56 self.debugfile = os.path.devnull
57 self.tabmodule = os.path.join(root_path, "iolibs", modname + "_" + "parsetab.py")
58 lex.lex(module=self, debug=0)
59 self.y=yacc.yacc(module=self, debug=0, debugfile=self.debugfile,
60 tabmodule=self.tabmodule)
61
67
68
69 tokens = (
70 'LOGICAL','LOGICALCOMB','POWER', 'CSC', 'SEC', 'ACSC', 'ASEC', 'TAN', 'ATAN',
71 'SQRT', 'BUILTIN', 'CONJ', 'RE', 'RE2', 'IM', 'PI', 'COMPLEX', 'FUNCTION', 'IF','ELSE',
72 'VARIABLE', 'NUMBER','COND','REGLOG', 'REGLOGP', 'REGLOGM','RECMS','ARG'
73 )
74 literals = "=+-*/(),"
75
76
77
79 r'(?<!\w)csc(?=\()'
80 return t
82 r'(?<!\w)sec(?=\()'
83 return t
85 r'(?<!\w)acsc(?=\()'
86 return t
88 r'(?<!\w)tan(?=\()|(?<!\w)cmath.tan(?=\()'
89 return t
91 r'(?<!\w)atan(?=\()|(?<!\w)cmath.atan(?=\()'
92 return t
94 r'(?<!\w)asec(?=\()'
95 return t
97 r'(?<!\w)reglog(?=\()'
98 return t
100 r'(?<!\w)reglogp(?=\()'
101 return t
103 r'(?<!\w)reglogm(?=\()'
104 return t
106 r'(?<!\w)recms(?=\()'
107 return t
109 r'(?<!\w)cond(?=\()'
110 return t
112 r'(?<!\w)arg(?=\()'
113 return t
115 r'(?<!\w)if\s'
116 return t
118 r'(?<!\w)else\s'
119 return t
121 r'==|!=|<=|>=|<|>'
122 return t
124 r'(?<!\w)and(?=[\s\(])|(?<!\w)or(?=[\s\(])'
125 return t
127 r'cmath\.sqrt'
128 return t
130 r'cmath\.pi'
131 return t
133 r'complexconjugate'
134 return t
136 r'(?<!\w)abs|bool|float|int|min|max(?=\()'
137 return t
139 r'(?<!\w)im(?=\()'
140 return t
142 r'(?<!\w)re(?=\()'
143 return t
145 r'\.real|\.imag|\.conjugate\(\)'
146 return t
147
149 r'(?<!\w)complex(?=\()'
150 return t
152 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
153 return t
155 r'[a-zA-Z_][0-9a-zA-Z_]*'
156 return t
157
158 t_NUMBER = r'([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)([eE][+-]{0,1}[0-9]+){0,1}j{0,1}'
159 t_POWER = r'\*\*'
160
161 t_ignore = " \t"
162
163 re_cmath_function = re.compile("cmath\.(?P<name>[0-9a-zA-Z_]+)")
164
166 r'\n+'
167 t.lexer.lineno += t.value.count("\n")
168
170 logger.error("Illegal character '%s'" % t.value[0])
171 t.lexer.skip(1)
172
174 """remove variable related to the latest parsing"""
175
176 return
177
178
179
180 - def build(self,**kwargs):
181 self.lexer = lex.lex(module=self, **kwargs)
182
183
184
185 precedence = (
186 ('right', 'LOGICALCOMB'),
187 ('right', 'LOGICAL'),
188 ('right','IF'),
189 ('right','ELSE'),
190 ('left','='),
191 ('left','+','-'),
192 ('left','*','/'),
193 ('left', 'RE2'),
194 ('right','UMINUS'),
195 ('left','POWER'),
196 ('right','REGLOG'),
197 ('right','REGLOGP'),
198 ('right','REGLOGM'),
199 ('right','RECMS'),
200 ('right','ARG'),
201 ('right','CSC'),
202 ('right','SEC'),
203 ('right','ACSC'),
204 ('right','ASEC'),
205 ('right','SQRT'),
206 ('right','CONJ'),
207 ('right','RE'),
208 ('right','IM'),
209 ('right', 'BUILTIN'),
210 ('right','FUNCTION'),
211 ('right','COMPLEX'),
212 ('right','COND'),
213 )
214
215
219
221 '''expression : expression '=' expression
222 | expression '+' expression
223 | expression '-' expression
224 | expression '*' expression
225 | expression '/' expression'''
226 p[0] = p[1] + p[2] + p[3]
227
229 '''boolexpression : expression LOGICAL expression'''
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 '''boolexpression : boolexpression LOGICALCOMB boolexpression'''
237 if p[2] not in self.logical_equiv:
238 p[0] = p[1] + p[2] + p[3]
239 else:
240 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
241
243 "expression : '-' expression %prec UMINUS"
244 p[0] = '-' + p[2]
245
247 "group : '(' expression ')'"
248 p[0] = '(' + p[2] +')'
249
250
252 "boolexpression : '(' boolexpression ')'"
253 p[0] = '(' + p[2] +')'
254
256 "expression : group"
257 p[0] = p[1]
258
260 "expression : FUNCTION '(' 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] + ')'
266
268 "expression : FUNCTION '(' expression ',' expression ')'"
269 p1 = p[1]
270 re_groups = self.re_cmath_function.match(p1)
271 if re_groups:
272 p1 = re_groups.group("name")
273 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
274
276 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
277 p1 = p[1]
278 re_groups = self.re_cmath_function.match(p1)
279 if re_groups:
280 p1 = re_groups.group("name")
281 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
282
284 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
285 p1 = p[1]
286 re_groups = self.re_cmath_function.match(p1)
287 if re_groups:
288 p1 = re_groups.group("name")
289 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
290
297
299 """A parser for UFO algebraic expressions, outputting
300 Fortran-style code."""
301
302
303 builtin_equiv = {'abs': 'ABS',
304 'bool': 'LOGICAL',
305 'float': 'REAL',
306
307 'int': 'INTEGER',
308 'min': 'MIN',
309 'max': 'MAX'
310 }
311
312
313
314
315 logical_equiv = {'==':'.EQ.',
316 '>=':'.GE.',
317 '<=':'.LE.',
318 '!=':'.NE.',
319 '>':'.GT.',
320 '<':'.LT.',
321 'or':'.OR.',
322 'and':'.AND.'}
323
324 types_def = { bool: lambda v: v ,
325 int :lambda v: 'INT(%s)' % v ,
326 float: lambda v: 'DBLE(%s)' % v,
327 complex: lambda v: 'DCMPLX(%s)' % v }
328
329 - def __init__(self, model, *args, **opts):
334
336 """remove information about object parse for previous parsing
337 """
338 self.to_define = set()
339
340
341
342
344 "expression : NUMBER"
345
346 if p[1].endswith('j'):
347 p[0] = ('DCMPLX(0d0, %e)' % float(p[1][:-1])).replace('e', 'd')
348 else:
349 p[0] = ('%e' % float(p[1])).replace('e', 'd')
350
352 "expression : VARIABLE"
353 p[0] = p[1].lower()
354
356 'expression : expression POWER expression'
357 try:
358 p3 = float(p[3].replace('d','e'))
359
360 if p3 == int(p3):
361 p3 = str(int(p3))
362 p[0] = p[1] + "**" + p3
363 else:
364 p[0] = p[1] + "**" + p[3]
365 except Exception:
366 p[0] = p[1] + "**" + p[3]
367
369 "expression : expression IF boolexpression ELSE expression "
370 p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
371 self.to_define.add('condif')
372
374 "expression : expression IF expression ELSE expression "
375 p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\
376 %(p[3], p[1], p[5])
377 self.to_define.add('condif')
378
380 "expression : COND '(' expression ',' expression ',' expression ')'"
381 p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
382 self.to_define.add('cond')
383
385 "expression : RECMS '(' boolexpression ',' expression ')'"
386 p[0] = 'RECMS('+p[3]+',DCMPLX('+p[5]+'))'
387 self.to_define.add('recms')
388
390 "expression : COMPLEX '(' expression ',' expression ')'"
391 p[0] = 'DCMPLX(' + p[3] + ',' + p[5] + ')'
392
394 '''expression : CSC group
395 | SEC group
396 | ACSC group
397 | ASEC group
398 | RE group
399 | IM group
400 | ARG group
401 | SQRT group
402 | CONJ group
403 | REGLOG group
404 | REGLOGP group
405 | REGLOGM group
406 | TAN group
407 | ATAN group
408 | BUILTIN group'''
409
410 if p[1] == 'csc': p[0] = '1d0/sin' + p[2]
411 elif p[1] == 'sec': p[0] = '1d0/cos' + p[2]
412 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
413 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
414 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(dble' + p[2]+')'
415 elif p[1] in ['tan', 'cmath.tan'] : p[0] = 'tan(dble' + p[2]+')'
416 elif p[1] == 're': p[0] = 'dble' + p[2]
417 elif p[1] == 'im': p[0] = 'dimag' + p[2]
418 elif p[1] == 'arg': p[0] = 'arg(DCMPLX'+p[2]+')'
419 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(dcmplx' + p[2]+')'
420 elif p[1] == 'complexconjugate': p[0] = 'conjg(DCMPLX' + p[2]+')'
421 elif p[1] == 'reglog': p[0] = 'reglog(DCMPLX' + p[2] +')'
422 elif p[1] == 'reglogp': p[0] = 'reglogp(DCMPLX' + p[2] + ')'
423 elif p[1] == 'reglogm': p[0] = 'reglogm(DCMPLX' + p[2] + ')'
424 elif p[1] in self.builtin_equiv: p[0] = self.builtin_equiv[p[1]] + p[2]
425
426 if p[1] in ['reglog', 'reglogp', 'reglogm']:
427 self.to_define.add(p[1])
428
430 self.modelfct = dict([(f.name,f) for f in self.model.get('functions')])
431
433 "expression : FUNCTION '(' expression ')'"
434 p1 = p[1]
435 re_groups = self.re_cmath_function.match(p1)
436 if re_groups:
437 p1 = re_groups.group("name")
438 p[0] = p1 + '(' + p[3] + ')'
439 else:
440 if not hasattr(self, 'modelfct'):
441 self.create_modelfct()
442 if p1 in self.modelfct:
443 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
444 types = [self.types_def[complex] for _ in self.modelfct[p1].arguments]
445 else:
446 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
447
448 p[0] = p1 + '(' + types[0](p[3]) + ')'
449 else:
450 p[0] = p1 + '(' + p[3] + ')'
451
452
454 '''expression : FUNCTION '(' expression ',' expression ')'
455 | FUNCTION '(' boolexpression ',' expression ')' '''
456
457 p1 = p[1]
458 re_groups = self.re_cmath_function.match(p1)
459 if re_groups:
460 p1 = re_groups.group("name")
461 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
462 else:
463 if not hasattr(self, 'modelfct'):
464 self.create_modelfct()
465 if p1 in self.modelfct:
466 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
467 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
468 else:
469 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
470
471 p[0] = p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ')'
472 else:
473 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
474
476 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
477 p1 = p[1]
478 re_groups = self.re_cmath_function.match(p1)
479 if re_groups:
480 p1 = re_groups.group("name")
481 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
482 else:
483 if not hasattr(self, 'modelfct'):
484 self.create_modelfct()
485 if p1 in self.modelfct:
486 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
487 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
488 else:
489 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
490
491 p[0] = p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ')'
492 else:
493 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
494
496 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
497 p1 = p[1]
498 re_groups = self.re_cmath_function.match(p1)
499 if re_groups:
500 p1 = re_groups.group("name")
501 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
502 else:
503 if not hasattr(self, 'modelfct'):
504 self.create_modelfct()
505 if p1 in self.modelfct:
506 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
507 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
508 else:
509 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
510 p[0] = p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ' , ' + types[3](p[9]) + ')'
511
512 else:
513 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
514
516 ''' expression : expression RE2 '''
517
518 if p[2] == '.real':
519 if p[1].startswith('('):
520 p[0] = 'dble' +p[1]
521 else:
522 p[0] = 'dble(%s)' % p[1]
523 elif p[2] == '.imag':
524 if p[1].startswith('('):
525 p[0] = 'dimag' +p[1]
526 else:
527 p[0] = 'dimag(%s)' % p[1]
528 elif p[2] == '.conjugate()':
529 if p[1].startswith('('):
530 p[0] = 'conjg(DCMPLX%s)' % p[1]
531 else:
532 p[0] = 'conjg(DCMPLX(%s))' % p[1]
533
535 '''expression : PI'''
536 p[0] = 'pi'
537 self.to_define.add('pi')
538
539
541 """A parser for UFO algebraic expressions, outputting
542 Fortran-style code for quadruple precision computation."""
543
544 mp_prefix = check_param_card.ParamCard.mp_prefix
545 types_def = { bool: lambda v: v ,
546 int :lambda v: 'mp__%s' % v if not v.startswith(('(','mp__','1','2','3','4','5','6','7','8','9','0','-')) else v,
547 float: lambda v: 'mp__%s' % v if not v.startswith(('(','mp__','1','2','3','4','5','6','7','8','9','0','-')) else v,
548 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}
549
550 builtin_equiv = {'abs': lambda v: 'ABS' +v,
551 'bool': lambda v: 'LOGICAL' +v ,
552 'float': lambda v: 'REAL(' +v+", KIND=16)",
553 'complex': lambda v: 'COMPLEX(' +v+", KIND=16)",
554 'int': lambda v: 'INTEGER' +v ,
555 'min': lambda v: 'MIN' +v ,
556 'max': lambda v: 'MAX' +v
557 }
558
559
560
561
563 "expression : NUMBER"
564
565 if p[1].endswith('j'):
566 p[0] = 'CMPLX(0.000000e+00_16, %e_16 ,KIND=16)' % float(p[1][:-1])
567 else:
568 p[0] = '%e_16' % float(p[1])
569
571 "expression : VARIABLE"
572
573 p[0] = (self.mp_prefix+p[1]).lower()
574
576 'expression : expression POWER expression'
577 try:
578 p3 = float(p[3].replace('_16',''))
579
580 if p3 == int(p3):
581 p3 = str(int(p3))
582 p[0] = p[1] + "**" + p3
583 else:
584 p[0] = p[1] + "**" + p[3]
585 except Exception:
586 p[0] = p[1] + "**" + p[3]
587
589 "expression : FUNCTION '(' expression ')'"
590 p1 = p[1]
591 re_groups = self.re_cmath_function.match(p1)
592 if re_groups:
593 p1 = re_groups.group("name")
594 p[0] = p1 + '(' + p[3] + ')'
595 else:
596 if not hasattr(self, 'modelfct'):
597 self.create_modelfct()
598 if p1 in self.modelfct:
599 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
600 types = [self.types_def[complex] for _ in self.modelfct[p1].arguments]
601 else:
602 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
603
604 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ')'
605 else:
606 p[0] = 'MP_' + p1 + '(' + p[3] + ')'
607
608
610 '''expression : FUNCTION '(' expression ',' expression ')'
611 | FUNCTION '(' boolexpression ',' expression ')' '''
612
613 p1 = p[1]
614 re_groups = self.re_cmath_function.match(p1)
615 if re_groups:
616 p1 = re_groups.group("name")
617 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
618 else:
619 if not hasattr(self, 'modelfct'):
620 self.create_modelfct()
621 if p1 in self.modelfct:
622 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
623 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
624 else:
625 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
626
627 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ')'
628 else:
629 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ')'
630
632 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
633 p1 = p[1]
634 re_groups = self.re_cmath_function.match(p1)
635 if re_groups:
636 p1 = re_groups.group("name")
637 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
638 else:
639 if not hasattr(self, 'modelfct'):
640 self.create_modelfct()
641 if p1 in self.modelfct:
642 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
643 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
644 else:
645 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
646
647 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ')'
648 else:
649 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ')'
650
652 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
653 p1 = p[1]
654 re_groups = self.re_cmath_function.match(p1)
655 if re_groups:
656 p1 = re_groups.group("name")
657 p[0] = p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
658 else:
659 if not hasattr(self, 'modelfct'):
660 self.create_modelfct()
661 if p1 in self.modelfct:
662 if not hasattr(self.modelfct[p1], 'argstype') or not self.modelfct[p1].argstype:
663 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
664 else:
665 types = [self.types_def[t] for t in self.modelfct[p1].argstype]
666 misc.sprint(types)
667 p[0] = 'MP_' + p1 + '(' + types[0](p[3]) + ',' + types[1](p[5]) + ' , ' + types[2](p[7]) + ' , ' + types[3](p[9]) + ')'
668
669 else:
670 p[0] = 'MP_' + p1 + '(' + p[3] + ',' + p[5] + ' , ' + p[7] + ' , ' + p[9] + ')'
671
672
673
675 "expression : expression IF boolexpression ELSE expression "
676 p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
677 self.to_define.add('condif')
678
680 "expression : expression IF expression ELSE expression "
681 p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\
682 %(p[3], p[1], p[5])
683 self.to_define.add('condif')
684
686 "expression : COMPLEX '(' expression ',' expression ')'"
687 p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
688
690 "expression : COND '(' expression ',' expression ',' expression ')'"
691 p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\
692 ',KIND=16),CMPLX('+p[7]+',KIND=16))'
693 self.to_define.add('cond')
694
696 "expression : RECMS '(' boolexpression ',' expression ')'"
697 p[0] = 'MP_RECMS('+p[3]+',CMPLX('+p[5]+',KIND=16))'
698 self.to_define.add('recms')
699
701 '''expression : CSC group
702 | SEC group
703 | ACSC group
704 | ASEC group
705 | RE group
706 | IM group
707 | ARG group
708 | SQRT group
709 | CONJ group
710 | REGLOG group
711 | REGLOGP group
712 | REGLOGM group
713 | TAN group
714 | ATAN group
715 | BUILTIN group'''
716
717 if p[1] == 'csc': p[0] = '1e0_16/cos' + p[2]
718 elif p[1] == 'sec': p[0] = '1e0_16/sin' + p[2]
719 elif p[1] == 'acsc': p[0] = 'asin(1e0_16/' + p[2] + ')'
720 elif p[1] == 'asec': p[0] = 'acos(1e0_16/' + p[2] + ')'
721 elif p[1] in ['atan', 'cmath.atan'] : p[0] = 'atan(real' + p[2]+')'
722 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan(real' + p[2]+')'
723 elif p[1] == 're': p[0] = 'real' + p[2]
724 elif p[1] == 'im': p[0] = 'imag' + p[2]
725 elif p[1] == 'arg': p[0] = 'mp_arg(CMPLX(' + p[2] + ',KIND=16))'
726 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(CMPLX(' + p[2] + ',KIND=16))'
727 elif p[1] == 'complexconjugate': p[0] = 'conjg(CMPLX(' + p[2] + ',KIND=16))'
728 elif p[1] == 'reglog': p[0] = 'mp_reglog(CMPLX(' + p[2] +',KIND=16))'
729 elif p[1] == 'reglogp': p[0] = 'mp_reglogp(CMPLX(' + p[2] + ',KIND=16))'
730 elif p[1] == 'reglogm': p[0] = 'mp_reglogm(CMPLX(' + p[2] + ',KIND=16))'
731 elif p[1] in self.builtin_equiv: p[0] = self.builtin_equiv[p[1]](p[2])
732
733 if p[1] in ['reglog', 'reglogp', 'reglogm']:
734 self.to_define.add(p[1])
735
737 ''' expression : expression RE2 '''
738
739 if p[2] == '.real':
740 if p[1].startswith('('):
741 p[0] = 'real' +p[1]
742 else:
743 p[0] = 'real(%s)' % p[1]
744 elif p[2] == '.imag':
745 if p[1].startswith('('):
746 p[0] = 'imag' +p[1]
747 else:
748 p[0] = 'imag(%s)' % p[1]
749 elif p[2] == '.conjugate()':
750 p[0] = 'conjg(CMPLX(%s,KIND=16))' % p[1]
751
752
754 '''expression : PI'''
755 p[0] = self.mp_prefix+'pi'
756 self.to_define.add('pi')
757
758
760 """A parser for UFO algebraic expressions, outputting
761 C++-style code."""
762
763 logical_equiv = {'==':'==',
764 '>=':'>=',
765 '<=':'<=',
766 '!=':'!=',
767 '>':'>',
768 '<':'<',
769 'or':'||',
770 'and':'&&'}
771
772 builtin_equiv = {'abs': 'ABS',
773 'bool': 'bool',
774 'float': 'float',
775
776 'int': 'int',
777 'min': 'min',
778 'max': 'max'
779 }
780
781
782
783
785 'expression : NUMBER'
786
787 if p[1].endswith('j'):
788 p[0] = 'std::complex<double>(0., %e)' % float(p[1][:-1])
789 else:
790 p[0] = ('%e' % float(p[1])).replace('e', 'd')
791
792
793 p[0] = p[1]
794
795 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000:
796 p[0] = str(int(float(p[1]))) + '.'
797
799 'expression : VARIABLE'
800 p[0] = p[1]
801
803 "expression : expression IF boolexpression ELSE expression "
804 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
805
807 "expression : expression IF expression ELSE expression "
808 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
809
811 "expression : COND '(' expression ',' expression ',' expression ')'"
812 p[0] = 'COND('+p[3]+','+p[5]+','+p[7]+')'
813
815 "expression : RECMS '(' boolexpression ',' expression ')'"
816 p[0] = 'RECMS('+p[3]+','+p[5]+')'
817
819 'expression : expression POWER expression'
820 p1=p[1]
821 p3=p[3]
822 if p[1][0] == '(' and p[1][-1] == ')':
823 p1 = p[1][1:-1]
824 if p[3][0] == '(' and p[3][-1] == ')':
825 p3 = p[3][1:-1]
826 if float(p3) == 2:
827 p[0] = '((' + p1 + ')*(' + p1 + '))'
828 elif float(p3) == 3:
829 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
830 elif float(p3) == 4:
831 p[0] = '((' + p1 + ')*(' + p1 + ')*(' + p1 + ')*(' + p1 + '))'
832 elif float(p3) == 0.5 or p3 == '0.5' or p3 == '1./2' or p3 == '1/2.' or p3 == '1./2.':
833 p[0] = 'sqrt(' + p1 + ')'
834 elif float(p3) == 1./3 or p3 == '1./3' or p3 == '1/3.' or p3 == '1./3.':
835 p[0] = 'cbrt(' + p1 + ')'
836 else:
837 p[0] = 'pow(' + p1 + ',' + p3 + ')'
838
840 "expression : COMPLEX '(' expression ',' expression ')'"
841 p[0] = 'std::complex<double>(' + p[3] + ',' + p[5] + ')'
842
844 '''expression : CSC group
845 | SEC group
846 | ACSC group
847 | ASEC group
848 | TAN group
849 | ATAN group
850 | RE group
851 | IM group
852 | ARG group
853 | SQRT group
854 | CONJ group
855 | REGLOG group
856 | REGLOGP group
857 | REGLOGM group
858 | BUILTIN group '''
859 if p[1] == 'csc': p[0] = '1./cos' + p[2]
860 elif p[1] == 'sec': p[0] = '1./sin' + p[2]
861 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
862 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
863 elif p[1] in ['atan', 'cmath.atan']: p[0] = 'atan' +p[2]
864 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan' +p[2]
865 elif p[1] == 're': p[0] = 'real' + p[2]
866 elif p[1] == 'im': p[0] = 'imag' + p[2]
867 elif p[1] == 'arg':p[0] = 'arg' + p[2]
868 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt' + p[2]
869 elif p[1] == 'complexconjugate': p[0] = 'conj' + p[2]
870 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
871 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
872 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
873 elif p[1] in self.buitin_equiv: p[0] = self.builtin_equiv[p[1]] + p[2]
874
875
877 ''' expression : expression RE2 '''
878
879 if p[2] == '.real':
880 if p[1].startswith('('):
881 p[0] = 'real' +p[1]
882 else:
883 p[0] = 'real(%s)' % p[1]
884 elif p[2] == '.imag':
885 if p[1].startswith('('):
886 p[0] = 'imag' +p[1]
887 else:
888 p[0] = 'imag(%s)' % p[1]
889
890
892 '''expression : PI'''
893 p[0] = 'M_PI'
894
896 """An ad hoc parser for UFO algebraic expressions with if statement, outputting
897 Python-style code, with the conditional 'if' expressions simplified using
898 pre-defined set of variables specified when instanciating this parser."""
899
900 logical_equiv = {'==':'==',
901 '>=':'>=',
902 '<=':'<=',
903 '!=':'!=',
904 '>':'>',
905 '<':'<',
906 'or':' or ',
907 'and':' and '}
908
909 builtin_equiv = {'abs': 'abs',
910 'bool': 'bool',
911 'float': 'float',
912
913 'int': 'int',
914 'min': 'min',
915 'max': 'max'
916 }
917
919 """Initialize the lex and yacc"""
920
921 self.changes_performed = 0
922
923 if len(args) > 0:
924 if isinstance(args[0],dict):
925 self.defined_variables = copy.copy(args[0])
926 elif isinstance(args[0],str):
927 try:
928 self.defined_variables = eval(args[0])
929 except:
930 raise ModelError('The expression "%s"'%str(args[0])+\
931 " given as defined variables for the UFOExpressionParserPythonIF"+\
932 " does not have a correct syntax.")
933 if not isinstance(self.defined_variables, dict):
934 raise ModelError('The argument "%s"'%str(args[0])+\
935 " given as defined variables for the UFOExpressionParserPythonIF"+\
936 " is not a dictionary.")
937 else:
938 raise ModelError("The argument %s"%str(args[0])+\
939 " given as defined variables for the UFOExpressionParserPythonIF"+\
940 " must be either a dictionary or a string.")
941 args = args[1:]
942 for key, value in list(self.defined_variables.items()):
943 if not isinstance(key,str) or \
944 not any(isinstance(value,t) for t in [float,complex,int]):
945
946 del self.defined_variables[key]
947
948 else:
949
950
951
952 self.defined_variables = None
953
954 super(UFOExpressionParserPythonIF,self).__init__(*args, **kw)
955
956 - def parse(self, *args, **kw):
957 """ Wrapper around the parse function so as to also return the number
958 of if substitutions made."""
959 self.changes_performed = 0
960 new_expression = super(UFOExpressionParserPythonIF,self).parse(*args, **kw)
961 return new_expression, self.changes_performed
962
964 "expression : NUMBER"
965 p[0] = p[1]
966
968 "expression : VARIABLE"
969 p[0] = p[1]
970
972 'expression : expression POWER expression'
973 p[0] = p[1] + "**" + p[3]
974
976 "expression : expression IF boolexpression ELSE expression "
977 if self.defined_variables is None:
978 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
979 return
980 try:
981 p[0] = '%s'%p[1] if eval(p[3],self.defined_variables) else '%s'%p[5]
982 self.changes_performed += 1
983 except Exception:
984 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
985
987 "expression : expression IF expression ELSE expression "
988 if self.defined_variables is None:
989 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
990 return
991 try:
992 p[0] = '%s'%p[1] if eval(p[3]+'!= 0.0',self.defined_variables) else '%s'%p[5]
993 self.changes_performed += 1
994 except Exception:
995 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
996
998 "expression : COND '(' expression ',' expression ',' expression ')'"
999
1000
1001 p[0] = 'cond('+p[3]+','+p[5]+','+p[7]+')'
1002
1004 "expression : COMPLEX '(' expression ',' expression ')'"
1005 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
1006
1008 "expression : RECMS '(' boolexpression ',' expression ')'"
1009 p[0] = 'recms('+p[3]+','+p[5]+')'
1010
1012 '''expression : CSC group
1013 | SEC group
1014 | ACSC group
1015 | ASEC group
1016 | RE group
1017 | IM group
1018 | ARG group
1019 | SQRT group
1020 | TAN group
1021 | ATAN group
1022 | CONJ group
1023 | REGLOG group
1024 | REGLOGP group
1025 | REGLOGM group
1026 | BUILTIN group'''
1027 if p[1] == 'csc': p[0] = 'csc' + p[2]
1028 elif p[1] == 'sec': p[0] = 'sec' + p[2]
1029 elif p[1] == 'acsc': p[0] = 'acsc' + p[2]
1030 elif p[1] == 'asec': p[0] = 'asec' + p[2]
1031 elif p[1] in ['tan','cmath.tan']: p[0] = 'tan' + p[2]
1032 elif p[1] in ['atan','cmath.atan']: p[0] = 'atan' + p[2]
1033 elif p[1] == 're': p[0] = 're' + p[2]
1034 elif p[1] == 'im': p[0] = 'im' + p[2]
1035 elif p[1] == 'arg': p[0] = 'arg' + p[2]
1036 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'cmath.sqrt' + p[2]
1037 elif p[1] == 'complexconjugate': p[0] = 'complexconjugate' + p[2]
1038 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
1039 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
1040 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
1041 elif p[1] in self.builtin_equiv: p[0] = self.builtin_equiv[p[1]] + p[2]
1042
1044 ''' expression : expression RE2 '''
1045 p[0] = p[1]+p[2]
1046
1048 '''expression : PI'''
1049
1050 p[0] = 'cmath.pi'
1051
1052
1053
1054
1055 if __name__ == '__main__':
1056
1057 if len(sys.argv) == 1:
1058 print("Please specify a parser: fortran, mpfortran or c++")
1059 exit()
1060 if sys.argv[1] == "fortran":
1061 calc = UFOExpressionParserFortran()
1062 elif sys.argv[1] == "mpfortran":
1063 calc = UFOExpressionParserMPFortran()
1064 elif sys.argv[1] == "c++":
1065 calc = UFOExpressionParserCPP()
1066 elif sys.argv[1] == "aloha":
1067 calc = UFOExpressionParserCPP()
1068 elif sys.argv[1] == "pythonif":
1069 if len(sys.argv) > 2:
1070 calc = UFOExpressionParserPythonIF(sys.argv[2])
1071 else:
1072 calc = UFOExpressionParserPythonIF()
1073 else:
1074 print("Please specify a parser: fortran, mpfortran, c++ or pythonif")
1075 print("You gave", sys.argv[1])
1076 if len(sys.argv) > 2:
1077 print("with the second argument",sys.argv[2])
1078 exit()
1079
1080 while 1:
1081 try:
1082 s = input('calc > ')
1083 except EOFError:
1084 break
1085 if not s: continue
1086 print(calc.parse(s))
1087