Package madgraph :: Package iolibs :: Module ufo_expression_parsers
[hide private]
[frames] | no frames]

Source Code for Module madgraph.iolibs.ufo_expression_parsers

  1  ################################################################################ 
  2  # 
  3  # Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors 
  4  # 
  5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
  6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
  7  # high-energy processes in the Standard Model and beyond. 
  8  # 
  9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
 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  # PLY lexer class 
 39   
40 -class ModelError(MadGraph5Error):
41 """Appropriate Error for a wrong parsing"""
42
43 -class UFOExpressionParser(object):
44 """A base class for parsers for algebraic expressions coming from UFO.""" 45 46 parsed_string = "" 47 logical_equiv = {} 48
49 - def __init__(self, **kw):
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
59 - def parse(self, buf):
60 """Parse the string buf""" 61 self.y.parse(buf) 62 return self.parsed_string
63 64 # List of tokens and literals 65 tokens = ( 66 'LOGICAL','LOGICALCOMB','POWER', 'CSC', 'SEC', 'ACSC', 'ASEC', 'TAN', 67 'SQRT', 'CONJ', 'RE', 'RE2', 'IM', 'PI', 'COMPLEX', 'FUNCTION', 'IF','ELSE', 68 'VARIABLE', 'NUMBER','COND','REGLOG', 'ARG' 69 ) 70 literals = "=+-*/()," 71 72 # Definition of tokens 73
74 - def t_CSC(self, t):
75 r'(?<!\w)csc(?=\()' 76 return t
77 - def t_SEC(self, t):
78 r'(?<!\w)sec(?=\()' 79 return t
80 - def t_ACSC(self, t):
81 r'(?<!\w)acsc(?=\()' 82 return t
83 - def t_TAN(self, t):
84 r'(?<!\w)tan(?=\()|(?<!\w)cmath.tan(?=\()' 85 return t
86 - def t_ASEC(self, t):
87 r'(?<!\w)asec(?=\()' 88 return t
89 - def t_REGLOG(self, t):
90 r'(?<!\w)reglog(?=\()' 91 return t
92 - def t_COND(self, t):
93 r'(?<!\w)cond(?=\()' 94 return t
95 - def t_ARG(self,t):
96 r'(?<!\w)arg(?=\()' 97 return t
98 - def t_IF(self, t):
99 r'(?<!\w)if\s' 100 return t
101 - def t_ELSE(self, t):
102 r'(?<!\w)else\s' 103 return t
104 - def t_LOGICAL(self, t):
105 r'==|!=|<=|>=|<|>' 106 return t
107 - def t_LOGICALCOMB(self, t):
108 r'(?<!\w)and(?=[\s\(])|(?<!\w)or(?=[\s\(])' 109 return t
110 - def t_SQRT(self, t):
111 r'cmath\.sqrt' 112 return t
113 - def t_PI(self, t):
114 r'cmath\.pi' 115 return t
116 - def t_CONJ(self, t):
117 r'complexconjugate' 118 return t
119 - def t_IM(self, t):
120 r'(?<!\w)im(?=\()' 121 return t
122 - def t_RE(self, t):
123 r'(?<!\w)re(?=\()' 124 return t
125 - def t_RE2(self, t):
126 r'\.real|\.imag' 127 return t
128
129 - def t_COMPLEX(self, t):
130 r'(?<!\w)complex(?=\()' 131 return t
132 - def t_FUNCTION(self, t):
133 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()' 134 return t
135 - def t_VARIABLE(self, t):
136 r'[a-zA-Z_][0-9a-zA-Z_]*' 137 return t
138 139 t_NUMBER = r'([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)([eE][+-]{0,1}[0-9]+){0,1}j{0,1}' 140 t_POWER = r'\*\*' 141 142 t_ignore = " \t" 143 144 re_cmath_function = re.compile("cmath\.(?P<name>[0-9a-zA-Z_]+)") 145
146 - def t_newline(self, t):
147 r'\n+' 148 t.lexer.lineno += t.value.count("\n")
149
150 - def t_error(self, t):
151 logger.error("Illegal character '%s'" % t.value[0]) 152 t.lexer.skip(1)
153 154 # Build the lexer
155 - def build(self,**kwargs):
156 self.lexer = lex.lex(module=self, **kwargs)
157 158 # Definitions for the PLY yacc parser 159 # Parsing rules 160 precedence = ( 161 ('right', 'LOGICALCOMB'), 162 ('right', 'LOGICAL'), 163 ('right','IF'), 164 ('right','ELSE'), 165 ('left','='), 166 ('left','+','-'), 167 ('left','*','/'), 168 ('left', 'RE2'), 169 ('right','UMINUS'), 170 ('left','POWER'), 171 ('right','REGLOG'), 172 ('right','ARG'), 173 ('right','CSC'), 174 ('right','SEC'), 175 ('right','ACSC'), 176 ('right','ASEC'), 177 ('right','SQRT'), 178 ('right','CONJ'), 179 ('right','RE'), 180 ('right','IM'), 181 ('right','FUNCTION'), 182 ('right','COMPLEX'), 183 ('right','COND'), 184 ) 185 186 # Dictionary of parser expressions
187 - def p_statement_expr(self, p):
188 'statement : expression' 189 self.parsed_string = p[1]
190
191 - def p_expression_binop(self, p):
192 '''expression : expression '=' expression 193 | expression '+' expression 194 | expression '-' expression 195 | expression '*' expression 196 | expression '/' expression''' 197 p[0] = p[1] + p[2] + p[3]
198
199 - def p_expression_logical(self, p):
200 '''boolexpression : expression LOGICAL expression''' 201 if p[2] not in self.logical_equiv: 202 p[0] = p[1] + p[2] + p[3] 203 else: 204 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
205
206 - def p_expression_logicalcomb(self, p):
207 '''boolexpression : boolexpression LOGICALCOMB boolexpression''' 208 if p[2] not in self.logical_equiv: 209 p[0] = p[1] + p[2] + p[3] 210 else: 211 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
212
213 - def p_expression_uminus(self, p):
214 "expression : '-' expression %prec UMINUS" 215 p[0] = '-' + p[2]
216
217 - def p_group_parentheses(self, p):
218 "group : '(' expression ')'" 219 p[0] = '(' + p[2] +')'
220
221 - def p_group_parentheses_boolexpr(self, p):
222 "boolexpression : '(' boolexpression ')'" 223 p[0] = '(' + p[2] +')'
224
225 - def p_expression_group(self, p):
226 "expression : group" 227 p[0] = p[1]
228
229 - def p_expression_function1(self, p):
230 "expression : FUNCTION '(' expression ')'" 231 p1 = p[1] 232 re_groups = self.re_cmath_function.match(p1) 233 if re_groups: 234 p1 = re_groups.group("name") 235 p[0] = p1 + '(' + p[3] + ')'
236
237 - def p_expression_function2(self, p):
238 "expression : FUNCTION '(' expression ',' expression ')'" 239 p1 = p[1] 240 re_groups = self.re_cmath_function.match(p1) 241 if re_groups: 242 p1 = re_groups.group("name") 243 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
244
245 - def p_error(self, p):
246 if p: 247 raise ModelError("Syntax error at '%s' (%s)." %(p.value,p)) 248 else: 249 logger.error("Syntax error at EOF") 250 self.parsed_string = "Error"
251
252 -class UFOExpressionParserFortran(UFOExpressionParser):
253 """A parser for UFO algebraic expressions, outputting 254 Fortran-style code.""" 255 256 # The following parser expressions need to be defined for each 257 # output language/framework 258 259 logical_equiv = {'==':'.EQ.', 260 '>=':'.GE.', 261 '<=':'.LE.', 262 '!=':'.NE.', 263 '>':'.GT.', 264 '<':'.LT.', 265 'or':'.OR.', 266 'and':'.AND.'} 267
268 - def p_expression_number(self, p):
269 "expression : NUMBER" 270 if p[1].endswith('j'): 271 p[0] = ('DCMPLX(0d0, %e)' % float(p[1][:-1])).replace('e', 'd') 272 else: 273 p[0] = ('%e' % float(p[1])).replace('e', 'd')
274
275 - def p_expression_variable(self, p):
276 "expression : VARIABLE" 277 p[0] = p[1].lower()
278
279 - def p_expression_power(self, p):
280 'expression : expression POWER expression' 281 try: 282 p3 = float(p[3].replace('d','e')) 283 # Chebck if exponent is an integer 284 if p3 == int(p3): 285 p3 = str(int(p3)) 286 p[0] = p[1] + "**" + p3 287 else: 288 p[0] = p[1] + "**" + p[3] 289 except Exception: 290 p[0] = p[1] + "**" + p[3]
291
292 - def p_expression_if(self,p):
293 "expression : expression IF boolexpression ELSE expression " 294 p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
295
296 - def p_expression_ifimplicit(self,p):
297 "expression : expression IF expression ELSE expression " 298 p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\ 299 %(p[3], p[1], p[5])
300
301 - def p_expression_cond(self, p):
302 "expression : COND '(' expression ',' expression ',' expression ')'" 303 p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
304
305 - def p_expression_complex(self, p):
306 "expression : COMPLEX '(' expression ',' expression ')'" 307 p[0] = 'DCMPLX(' + p[3] + ',' + p[5] + ')'
308
309 - def p_expression_func(self, p):
310 '''expression : CSC group 311 | SEC group 312 | ACSC group 313 | ASEC group 314 | RE group 315 | IM group 316 | ARG group 317 | SQRT group 318 | CONJ group 319 | REGLOG group 320 | TAN group''' 321 322 if p[1] == 'csc': p[0] = '1d0/cos' + p[2] 323 elif p[1] == 'sec': p[0] = '1d0/sin' + p[2] 324 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')' 325 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')' 326 elif p[1] in ['tan', 'cmath.tan'] : p[0] = 'tan(dble' + p[2]+')' 327 elif p[1] == 're': p[0] = 'dble' + p[2] 328 elif p[1] == 'im': p[0] = 'dimag' + p[2] 329 elif p[1] == 'arg': p[0] = 'arg(DCMPLX'+p[2]+')' 330 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(dcmplx' + p[2]+')' 331 elif p[1] == 'complexconjugate': p[0] = 'conjg(DCMPLX' + p[2]+')' 332 elif p[1] == 'reglog': p[0] = 'reglog(DCMPLX' + p[2] +')'
333 334
335 - def p_expression_real(self, p):
336 ''' expression : expression RE2 ''' 337 338 if p[2] == '.real': 339 if p[1].startswith('('): 340 p[0] = 'dble' +p[1] 341 else: 342 p[0] = 'dble(%s)' % p[1] 343 elif p[2] == '.imag': 344 if p[1].startswith('('): 345 p[0] = 'dimag' +p[1] 346 else: 347 p[0] = 'dimag(%s)' % p[1]
348
349 - def p_expression_pi(self, p):
350 '''expression : PI''' 351 p[0] = 'pi'
352
353 -class UFOExpressionParserMPFortran(UFOExpressionParserFortran):
354 """A parser for UFO algebraic expressions, outputting 355 Fortran-style code for quadruple precision computation.""" 356 357 mp_prefix = check_param_card.ParamCard.mp_prefix 358 359 # The following parser expressions need to be defined for each 360 # output language/framework 361
362 - def p_expression_number(self, p):
363 "expression : NUMBER" 364 365 if p[1].endswith('j'): 366 p[0] = 'CMPLX(0.000000e+00_16, %e_16 ,KIND=16)' % float(p[1][:-1]) 367 else: 368 p[0] = '%e_16' % float(p[1])
369
370 - def p_expression_variable(self, p):
371 "expression : VARIABLE" 372 # All the multiple_precision variables are defined with the prefix _MP_" 373 p[0] = (self.mp_prefix+p[1]).lower()
374
375 - def p_expression_power(self, p):
376 'expression : expression POWER expression' 377 try: 378 p3 = float(p[3].replace('_16','')) 379 # Check if exponent is an integer 380 if p3 == int(p3): 381 p3 = str(int(p3)) 382 p[0] = p[1] + "**" + p3 383 else: 384 p[0] = p[1] + "**" + p[3] 385 except Exception: 386 p[0] = p[1] + "**" + p[3]
387
388 - def p_expression_if(self,p):
389 "expression : expression IF boolexpression ELSE expression " 390 p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
391
392 - def p_expression_ifimplicit(self,p):
393 "expression : expression IF expression ELSE expression " 394 p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\ 395 %(p[3], p[1], p[5])
396
397 - def p_expression_complex(self, p):
398 "expression : COMPLEX '(' expression ',' expression ')'" 399 p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
400
401 - def p_expression_cond(self, p):
402 "expression : COND '(' expression ',' expression ',' expression ')'" 403 p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\ 404 ',KIND=16),CMPLX('+p[7]+',KIND=16))'
405
406 - def p_expression_func(self, p):
407 '''expression : CSC group 408 | SEC group 409 | ACSC group 410 | ASEC group 411 | RE group 412 | IM group 413 | ARG group 414 | SQRT group 415 | CONJ group 416 | TAN group 417 | REGLOG group''' 418 if p[1] == 'csc': p[0] = '1e0_16/cos' + p[2] 419 elif p[1] == 'sec': p[0] = '1e0_16/sin' + p[2] 420 elif p[1] == 'acsc': p[0] = 'asin(1e0_16/' + p[2] + ')' 421 elif p[1] == 'asec': p[0] = 'acos(1e0_16/' + p[2] + ')' 422 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan(real' + p[2]+')' 423 elif p[1] == 're': p[0] = 'real' + p[2] 424 elif p[1] == 'im': p[0] = 'imag' + p[2] 425 elif p[1] == 'arg': p[0] = 'mp_arg(CMPLX(' + p[2] + ',KIND=16))' 426 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(CMPLX(' + p[2] + ',KIND=16))' 427 elif p[1] == 'complexconjugate': p[0] = 'conjg(CMPLX(' + p[2] + ',KIND=16))' 428 elif p[1] == 'reglog': p[0] = 'mp_reglog(CMPLX(' + p[2] +',KIND=16))'
429
430 - def p_expression_real(self, p):
431 ''' expression : expression RE2 ''' 432 433 if p[2] == '.real': 434 if p[1].startswith('('): 435 p[0] = 'real' +p[1] 436 else: 437 p[0] = 'real(%s)' % p[1] 438 elif p[2] == '.imag': 439 if p[1].startswith('('): 440 p[0] = 'imag' +p[1] 441 else: 442 p[0] = 'imag(%s)' % p[1]
443 444
445 - def p_expression_pi(self, p):
446 '''expression : PI''' 447 p[0] = self.mp_prefix+'pi'
448
449 -class UFOExpressionParserCPP(UFOExpressionParser):
450 """A parser for UFO algebraic expressions, outputting 451 C++-style code.""" 452 453 logical_equiv = {'==':'==', 454 '>=':'>=', 455 '<=':'<=', 456 '!=':'!=', 457 '>':'>', 458 '<':'<', 459 'or':'||', 460 'and':'&&'} 461 462 # The following parser expressions need to be defined for each 463 # output language/framework 464
465 - def p_expression_number(self, p):
466 'expression : NUMBER' 467 468 if p[1].endswith('j'): 469 p[0] = 'std::complex<double>(0., %e)' % float(p[1][:-1]) 470 else: 471 p[0] = ('%e' % float(p[1])).replace('e', 'd') 472 473 474 p[0] = p[1] 475 # Check number is an integer, if so add "." 476 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000: 477 p[0] = str(int(float(p[1]))) + '.'
478
479 - def p_expression_variable(self, p):
480 'expression : VARIABLE' 481 p[0] = p[1]
482
483 - def p_expression_if(self,p):
484 "expression : expression IF boolexpression ELSE expression " 485 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
486
487 - def p_expression_ifimplicit(self,p):
488 "expression : expression IF expression ELSE expression " 489 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
490
491 - def p_expression_cond(self, p):
492 "expression : COND '(' expression ',' expression ',' expression ')'" 493 p[0] = 'COND('+p[3]+','+p[5]+','+p[7]+')'
494
495 - def p_expression_power(self, p):
496 'expression : expression POWER expression' 497 p1=p[1] 498 p3=p[3] 499 if p[1][0] == '(' and p[1][-1] == ')': 500 p1 = p[1][1:-1] 501 if p[3][0] == '(' and p[3][-1] == ')': 502 p3 = p[3][1:-1] 503 p[0] = 'pow(' + p1 + ',' + p3 + ')'
504
505 - def p_expression_complex(self, p):
506 "expression : COMPLEX '(' expression ',' expression ')'" 507 p[0] = 'std::complex<double>(' + p[3] + ',' + p[5] + ')'
508
509 - def p_expression_func(self, p):
510 '''expression : CSC group 511 | SEC group 512 | ACSC group 513 | ASEC group 514 | TAN group 515 | RE group 516 | IM group 517 | ARG group 518 | SQRT group 519 | CONJ group 520 | REGLOG group ''' 521 if p[1] == 'csc': p[0] = '1./cos' + p[2] 522 elif p[1] == 'sec': p[0] = '1./sin' + p[2] 523 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')' 524 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')' 525 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan' +p[2] 526 elif p[1] == 're': p[0] = 'real' + p[2] 527 elif p[1] == 'im': p[0] = 'imag' + p[2] 528 elif p[1] == 'arg':p[0] = 'arg' + p[2] 529 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt' + p[2] 530 elif p[1] == 'complexconjugate': p[0] = 'conj' + p[2] 531 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
532
533 - def p_expression_real(self, p):
534 ''' expression : expression RE2 ''' 535 536 if p[2] == '.real': 537 if p[1].startswith('('): 538 p[0] = 'real' +p[1] 539 else: 540 p[0] = 'real(%s)' % p[1] 541 elif p[2] == '.imag': 542 if p[1].startswith('('): 543 p[0] = 'imag' +p[1] 544 else: 545 p[0] = 'imag(%s)' % p[1]
546 547
548 - def p_expression_pi(self, p):
549 '''expression : PI''' 550 p[0] = 'M_PI'
551
552 -class UFOExpressionParserPythonIF(UFOExpressionParser):
553 """An ad hoc parser for UFO algebraic expressions with if statement, outputting 554 Python-style code, with the conditional 'if' expressions simplified using 555 pre-defined set of variables specified when instanciating this parser.""" 556 557 logical_equiv = {'==':'==', 558 '>=':'>=', 559 '<=':'<=', 560 '!=':'!=', 561 '>':'>', 562 '<':'<', 563 'or':' or ', 564 'and':' and '} 565
566 - def __init__(self, *args,**kw):
567 """Initialize the lex and yacc""" 568 569 self.changes_performed = 0 570 571 if len(args) > 0: 572 if isinstance(args[0],dict): 573 self.defined_variables = copy.copy(args[0]) 574 elif isinstance(args[0],str): 575 try: 576 self.defined_variables = eval(args[0]) 577 except: 578 raise ModelError, 'The expression "%s"'%str(args[0])+\ 579 " given as defined variables for the UFOExpressionParserPythonIF"+\ 580 " does not have a correct syntax." 581 if not isinstance(self.defined_variables, dict): 582 raise ModelError, 'The argument "%s"'%str(args[0])+\ 583 " given as defined variables for the UFOExpressionParserPythonIF"+\ 584 " is not a dictionary." 585 else: 586 raise ModelError, "The argument %s"%str(args[0])+\ 587 " given as defined variables for the UFOExpressionParserPythonIF"+\ 588 " must be either a dictionary or a string." 589 args = args[1:] 590 for key, value in self.defined_variables.items(): 591 if not isinstance(key,str) or \ 592 not any(isinstance(value,t) for t in [float,complex,int]): 593 # This is not a valid environment variable for the parser 594 del self.defined_variables[key] 595 596 else: 597 # If the user doesn't specify any defined variable for this parser, this means 598 # that it shouldn't do anything, not even simplify trivial conditional expressions 599 # such as '1 if True else 2' 600 self.defined_variables = None 601 602 super(UFOExpressionParserPythonIF,self).__init__(*args, **kw)
603
604 - def parse(self, *args, **kw):
605 """ Wrapper around the parse function so as to also return the number 606 of if substitutions made.""" 607 self.changes_performed = 0 608 new_expression = super(UFOExpressionParserPythonIF,self).parse(*args, **kw) 609 return new_expression, self.changes_performed
610
611 - def p_expression_number(self, p):
612 "expression : NUMBER" 613 p[0] = p[1]
614
615 - def p_expression_variable(self, p):
616 "expression : VARIABLE" 617 p[0] = p[1]
618
619 - def p_expression_power(self, p):
620 'expression : expression POWER expression' 621 p[0] = p[1] + "**" + p[3]
622
623 - def p_expression_if(self,p):
624 "expression : expression IF boolexpression ELSE expression " 625 if self.defined_variables is None: 626 p[0] = '%s if %s else %s'%(p[1],p[3],p[5]) 627 return 628 try: 629 p[0] = '%s'%p[1] if eval(p[3],self.defined_variables) else '%s'%p[5] 630 self.changes_performed += 1 631 except Exception: 632 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
633
634 - def p_expression_ifimplicit(self,p):
635 "expression : expression IF expression ELSE expression " 636 if self.defined_variables is None: 637 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5]) 638 return 639 try: 640 p[0] = '%s'%p[1] if eval(p[3]+'!= 0.0',self.defined_variables) else '%s'%p[5] 641 self.changes_performed += 1 642 except Exception: 643 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
644
645 - def p_expression_cond(self, p):
646 "expression : COND '(' expression ',' expression ',' expression ')'" 647 # We assume the cond syntax is used by the Model builder when he doesn't want it to 648 # get simplified, ever. 649 p[0] = 'cond('+p[3]+','+p[5]+','+p[7]+')'
650
651 - def p_expression_complex(self, p):
652 "expression : COMPLEX '(' expression ',' expression ')'" 653 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
654
655 - def p_expression_func(self, p):
656 '''expression : CSC group 657 | SEC group 658 | ACSC group 659 | ASEC group 660 | RE group 661 | IM group 662 | ARG group 663 | SQRT group 664 | TAN group 665 | CONJ group 666 | REGLOG group''' 667 if p[1] == 'csc': p[0] = 'csc' + p[2] 668 elif p[1] == 'sec': p[0] = 'sec' + p[2] 669 elif p[1] == 'acsc': p[0] = 'acsc' + p[2] 670 elif p[1] == 'asec': p[0] = 'asec' + p[2] 671 elif p[1] in ['tan','cmath.tan']: p[0] = 'tan' + p[2] 672 elif p[1] == 're': p[0] = 're' + p[2] 673 elif p[1] == 'im': p[0] = 'im' + p[2] 674 elif p[1] == 'arg': p[0] = 'arg' + p[2] 675 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'cmath.sqrt' + p[2] 676 elif p[1] == 'complexconjugate': p[0] = 'complexconjugate' + p[2] 677 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
678
679 - def p_expression_real(self, p):
680 ''' expression : expression RE2 ''' 681 p[0] = p[1]+p[2]
682
683 - def p_expression_pi(self, p):
684 '''expression : PI''' 685 p[0] = 'cmath.pi'
686 687 688 689 # Main program, allows to interactively test the parser 690 if __name__ == '__main__': 691 692 if len(sys.argv) == 1: 693 print "Please specify a parser: fortran, mpfortran or c++" 694 exit() 695 if sys.argv[1] == "fortran": 696 calc = UFOExpressionParserFortran() 697 elif sys.argv[1] == "mpfortran": 698 calc = UFOExpressionParserMPFortran() 699 elif sys.argv[1] == "c++": 700 calc = UFOExpressionParserCPP() 701 elif sys.argv[1] == "aloha": 702 calc = UFOExpressionParserCPP() 703 elif sys.argv[1] == "pythonif": 704 if len(sys.argv) > 2: 705 calc = UFOExpressionParserPythonIF(sys.argv[2]) 706 else: 707 calc = UFOExpressionParserPythonIF() 708 else: 709 print "Please specify a parser: fortran, mpfortran, c++ or pythonif" 710 print "You gave", sys.argv[1] 711 if len(sys.argv) > 2: 712 print "with the second argument",sys.argv[2] 713 exit() 714 715 while 1: 716 try: 717 s = raw_input('calc > ') 718 except EOFError: 719 break 720 if not s: continue 721 print calc.parse(s) 722