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