Package aloha :: Module aloha_parsers
[hide private]
[frames] | no frames]

Source Code for Module aloha.aloha_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  from __future__ import division 
 21   
 22  import logging 
 23  import numbers 
 24  import os 
 25  import re 
 26  import sys 
 27   
 28   
 29  root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 
 30  sys.path.append(os.path.join(root_path)) 
 31   
 32  import aloha_lib 
 33  from aloha_object import * 
 34  import vendor.ply.lex as lex 
 35  import vendor.ply.yacc as yacc 
 36  from aloha.aloha_lib import KERNEL 
 37  logger = logging.getLogger('aloha.parsers') 
 38   
 39  try: 
 40      import madgraph.various.misc as misc 
 41  except Exception: 
 42      import aloha.misc as misc 
 43   
 44   
 45  # PLY lexer class 
46 -class UFOExpressionParser(object):
47 """A base class for parsers for algebraic expressions coming from UFO.""" 48 49 parsed_string = "" 50
51 - def __init__(self, **kw):
52 """Ininitialize the lex and yacc""" 53 54 modname = self.__class__.__name__ 55 self.debugfile = os.path.devnull 56 self.tabmodule = os.path.join(root_path, "iolibs", modname + "_" + "parsetab.py") 57 lex.lex(module=self, debug=0) 58 yacc.yacc(module=self, debug=0, debugfile=self.debugfile, 59 tabmodule=self.tabmodule)
60
61 - def parse(self, buf):
62 """Parse the string buf""" 63 yacc.parse(buf) 64 return self.parsed_string
65 66 # List of tokens and literals 67 tokens = ( 68 'POWER', 'CSC', 'SEC', 'ACSC', 'ASEC', 69 'SQRT', 'CONJ', 'RE', 'IM', 'PI', 'COMPLEX', 'FUNCTION', 70 'VARIABLE', 'NUMBER' 71 ) 72 literals = "=+-*/(),'" 73 74 # Definition of tokens 75
76 - def t_CSC(self, t):
77 r'(?<!\w)csc(?=\()' 78 return t
79 - def t_SEC(self, t):
80 r'(?<!\w)sec(?=\()' 81 return t
82 - def t_ACSC(self, t):
83 r'(?<!\w)acsc(?=\()' 84 return t
85 - def t_ASEC(self, t):
86 r'(?<!\w)asec(?=\()' 87 return t
88 - def t_SQRT(self, t):
89 r'cmath\.sqrt' 90 return t
91 - def t_PI(self, t):
92 r'cmath\.pi' 93 return t
94 - def t_CONJ(self, t):
95 r'complexconjugate' 96 return t
97 - def t_IM(self, t):
98 r'(?<!\w)im(?=\()' 99 return t
100 - def t_RE(self, t):
101 r'(?<!\w)re(?=\()' 102 return t
103 - def t_COMPLEX(self, t):
104 r'(?<!\w)complex(?=\()' 105 return t
106 - def t_FUNCTION(self, t):
107 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()' 108 return t
109 - def t_VARIABLE(self, t):
110 r'[a-zA-Z_][0-9a-zA-Z_]*' 111 return t
112 113 t_NUMBER = r'([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)([eE][+-]{0,1}[0-9]+){0,1}' 114 t_POWER = r'\*\*' 115 116 t_ignore = " \t" 117 118 re_cmath_function = re.compile("cmath\.(?P<name>[0-9a-zA-Z_]+)") 119
120 - def t_newline(self, t):
121 r'\n+' 122 t.lexer.lineno += t.value.count("\n")
123
124 - def t_error(self, t):
125 logger.error("Illegal character '%s'" % t.value[0]) 126 t.lexer.skip(1)
127 128 # Build the lexer
129 - def build(self,**kwargs):
130 self.lexer = lex.lex(module=self, **kwargs)
131 132 # Definitions for the PLY yacc parser 133 134 # Parsing rules 135 precedence = ( 136 ('left','='), 137 ('left','+','-'), 138 ('left','*','/'), 139 ('right','UMINUS'), 140 ('left','POWER'), 141 ('right','CSC'), 142 ('right','SEC'), 143 ('right','ACSC'), 144 ('right','ASEC'), 145 ('right','SQRT'), 146 ('right','CONJ'), 147 ('right','RE'), 148 ('right','IM'), 149 ('right','FUNCTION'), 150 ('right','COMPLEX') 151 ) 152 153 # Dictionary of parser expressions
154 - def p_statement_expr(self, p):
155 'statement : expression' 156 self.parsed_string = p[1]
157
158 - def p_expression_binop(self, p):
159 '''expression : expression '=' expression 160 | expression '+' expression 161 | expression '-' expression 162 | expression '*' expression 163 | expression '/' expression''' 164 p[0] = p[1] + p[2] + p[3]
165
166 - def p_expression_uminus(self, p):
167 "expression : '-' expression %prec UMINUS" 168 p[0] = '-' + p[2]
169
170 - def p_group_parentheses(self, p):
171 "group : '(' expression ')'" 172 p[0] = '(' + p[2] +')'
173
174 - def p_expression_group(self, p):
175 "expression : group" 176 p[0] = p[1]
177
178 - def p_expression_function1(self, p):
179 "expression : FUNCTION '(' expression ')'" 180 p1 = p[1] 181 re_groups = self.re_cmath_function.match(p1) 182 if re_groups: 183 p1 = re_groups.group("name") 184 p[0] = p1 + '(' + p[3] + ')'
185
186 - def p_expression_function2(self, p):
187 "expression : FUNCTION '(' expression ',' expression ')'" 188 p1 = p[1] 189 re_groups = self.re_cmath_function.match(p1) 190 if re_groups: 191 p1 = re_groups.group("name") 192 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
193
194 - def p_error(self, p):
195 if p: 196 print p[:] 197 raise Exception("Syntax error at '%s' in '%s'" % (p.value, self.f)) 198 else: 199 logger.error("Syntax error at EOF") 200 self.parsed_string = "Error"
201 202
203 -class ALOHAExpressionParser(UFOExpressionParser):
204 205 aloha_object = ['P','Gamma','Gamma5','Sigma','Mass','PSlash', 206 'OverMass2','Width','Scalar','Spinor','Vector', 207 'Spin2','Spin32','C','Epsilon','Metric','Identity', 208 'ProjM','ProjP','Coup'] 209
210 - def p_expression_pi(self, p):
211 '''expression : PI''' 212 KERNEL.has_pi = True 213 p[0] = 'Param(\'PI\')'
214
215 - def p_expression_power(self, p):
216 'expression : expression POWER expression' 217 218 obj = p[1] 219 if '(' in p[1]: 220 obj = p[1].split('(',1)[0] 221 222 if obj in self.aloha_object: 223 p[0] = ''.join(p[1:]) 224 else: 225 new = aloha_lib.KERNEL.add_function_expression('pow', eval(p[1]), eval(p[3])) 226 p[0] = str(new)
227 228
229 - def p_expression_variable(self, p):
230 "expression : VARIABLE" 231 p[0] = 'Param(\'%s\')' % p[1]
232
233 - def p_expression_variable2(self, p):
234 "expression : '\\'' VARIABLE '\\''" 235 p[0] = '\'%s\'' % p[2]
236
237 - def p_expression_expression(self, p):
238 "expression : '\\'' expression '\\''" 239 p[0] = '\'%s\'' % p[2]
240
241 - def p_expression_complex(self, p):
242 "expression : COMPLEX '(' expression ',' expression ')'" 243 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
244
245 - def p_expression_number(self, p):
246 "expression : NUMBER" 247 p[0] = p[1] 248 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000: 249 p[0] = str(int(float(p[1])))
250
251 - def p_expression_func(self, p):
252 '''expression : CSC group 253 | SEC group 254 | ACSC group 255 | ASEC group 256 | RE group 257 | IM group 258 | SQRT group 259 | CONJ group''' 260 261 new = aloha_lib.KERNEL.add_function_expression(p[1], eval(p[2])) 262 p[0] = str(new)
263
264 - def p_expression_function1(self, p):
265 "expression : FUNCTION '(' expression ')'" 266 267 p1 = p[1] 268 if p1 in self.aloha_object: 269 p[0] = p[1]+'('+p[3]+')' 270 return 271 re_groups = self.re_cmath_function.match(p1) 272 273 if re_groups: 274 p1 = re_groups.group("name") 275 new = aloha_lib.KERNEL.add_function_expression(p1, eval(p[3])) 276 p[0] = str(new)
277
278 - def p_expression_function2(self, p):
279 "expression : FUNCTION '(' expression ',' expression ')'" 280 281 if p[1] in self.aloha_object: 282 p[0] = p[1]+'('+p[3]+','+ p[5]+')' 283 return 284 285 p1 = p[1] 286 re_groups = self.re_cmath_function.match(p1) 287 if re_groups: 288 p1 = re_groups.group("name") 289 new = aloha_lib.KERNEL.add_function_expression(p1, eval(p[3]), eval(p[5])) 290 p[0] = str(new)
291
292 - def p_expression_function3(self, p):
293 "expression : FUNCTION '(' expression ',' expression ',' expression ')'" 294 295 if p[1] in self.aloha_object: 296 p[0] = p[1]+'('+p[3]+','+ p[5]+','+p[7]+')' 297 return 298 299 p1 = p[1] 300 re_groups = self.re_cmath_function.match(p1) 301 if re_groups: 302 p1 = re_groups.group("name") 303 304 new = aloha_lib.KERNEL.add_function_expression(p1, eval(p[3]), eval(p[5]),eval(p[7])) 305 p[0] = str(new)
306
307 - def p_expression_function4(self, p):
308 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'" 309 if p[1] in self.aloha_object: 310 p[0] = p[1]+'('+p[3]+','+ p[5]+','+ p[7]+','+ p[9]+')' 311 return 312 313 p1 = p[1] 314 re_groups = self.re_cmath_function.match(p1) 315 if re_groups: 316 p1 = re_groups.group("name") 317 args = [eval(p[2*i+1]) for i in [1,2,3,4]] 318 new = aloha_lib.KERNEL.add_function_expression(p1, *args) 319 p[0] = str(new)
320
321 - def p_expression_binop(self, p):
322 '''expression : expression '=' expression 323 | expression '+' expression 324 | expression '-' expression 325 | expression '*' expression 326 | expression '/' expression''' 327 if p[2] != '/' or p[3].isdigit() or p[3].endswith('.'): 328 p[0] = p[1] + p[2] + p[3] 329 else: 330 denom = eval(p[3]) 331 if isinstance(denom, numbers.Number): 332 p[0] = p[1] + '*' + str(1/denom) 333 else: 334 new = aloha_lib.KERNEL.add_function_expression('/', denom) 335 p[0] = p[1] + ' * ' + str(new)
336 337 338 339 340 # Main program, allows to interactively test the parser 341 if __name__ == '__main__': 342 343 344 calc = ALOHAExpressionParser() 345 while 1: 346 try: 347 s = raw_input('calc > ') 348 except EOFError: 349 break 350 if not s: continue 351 logger.info(calc.parse(s)) 352