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