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 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
47 """A base class for parsers for algebraic expressions coming from UFO."""
48
49 parsed_string = ""
50
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
65
66
67 tokens = (
68 'POWER', 'CSC', 'SEC', 'ACSC', 'ASEC',
69 'SQRT', 'CONJ', 'RE', 'IM', 'PI', 'COMPLEX', 'FUNCTION',
70 'VARIABLE', 'NUMBER'
71 )
72 literals = "=+-*/(),'"
73
74
75
77 r'(?<!\w)csc(?=\()'
78 return t
80 r'(?<!\w)sec(?=\()'
81 return t
83 r'(?<!\w)acsc(?=\()'
84 return t
86 r'(?<!\w)asec(?=\()'
87 return t
89 r'cmath\.sqrt'
90 return t
92 r'cmath\.pi'
93 return t
95 r'complexconjugate'
96 return t
98 r'(?<!\w)im(?=\()'
99 return t
101 r'(?<!\w)re(?=\()'
102 return t
104 r'(?<!\w)complex(?=\()'
105 return t
107 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
108 return 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
121 r'\n+'
122 t.lexer.lineno += t.value.count("\n")
123
125 logger.error("Illegal character '%s'" % t.value[0])
126 t.lexer.skip(1)
127
128
129 - def build(self,**kwargs):
130 self.lexer = lex.lex(module=self, **kwargs)
131
132
133
134
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
157
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
167 "expression : '-' expression %prec UMINUS"
168 p[0] = '-' + p[2]
169
171 "group : '(' expression ')'"
172 p[0] = '(' + p[2] +')'
173
175 "expression : group"
176 p[0] = p[1]
177
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
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
195 if p:
196 try:
197 print p
198 print p[:]
199 except:
200 pass
201 raise Exception("Syntax error at '%s' in '%s'" % (p.value, self.f))
202 else:
203 logger.error("Syntax error at EOF")
204 self.parsed_string = "Error"
205
206
208
209 aloha_object = ['P', 'PBar', 'PVec','Gamma','Gamma5','Sigma','Mass','PSlash',
210 'OverMass2','Width','Scalar','Spinor','Vector',
211 'Spin2','Spin32','C','Epsilon','Metric','Identity',
212 'ProjM','ProjP','Coup','Norm', 'EPSL', 'EPST1', 'EPST2', 'PT',
213 'UFP', 'UFM', 'UFPC', 'UFMC',
214 'VFP', 'VFM', 'VFPC', 'VFMC',
215 'Tnorm', 'TnormZ']
216
218 '''expression : PI'''
219 KERNEL.has_pi = True
220 p[0] = 'Param(\'PI\')'
221
223 'expression : expression POWER expression'
224
225 obj = p[1]
226 if '(' in p[1]:
227 obj = p[1].split('(',1)[0]
228
229 if obj in self.aloha_object:
230 p[0] = ''.join(p[1:])
231 else:
232 new = aloha_lib.KERNEL.add_function_expression('pow', eval(p[1]), eval(p[3]))
233 p[0] = str(new)
234
235
237 "expression : VARIABLE"
238 p[0] = 'Param(\'%s\')' % p[1]
239
241 "expression : '\\'' VARIABLE '\\''"
242 p[0] = '\'%s\'' % p[2]
243
245 "expression : '\\'' expression '\\''"
246 p[0] = '\'%s\'' % p[2]
247
249 "expression : COMPLEX '(' expression ',' expression ')'"
250 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
251
253 "expression : NUMBER"
254 p[0] = p[1]
255 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000:
256 p[0] = str(int(float(p[1])))
257
259 '''expression : CSC group
260 | SEC group
261 | ACSC group
262 | ASEC group
263 | RE group
264 | IM group
265 | SQRT group
266 | CONJ group'''
267
268 new = aloha_lib.KERNEL.add_function_expression(p[1], eval(p[2]))
269 p[0] = str(new)
270
284
286 "expression : FUNCTION '(' expression ',' expression ')'"
287
288 if p[1] in self.aloha_object:
289 p[0] = p[1]+'('+p[3]+','+ p[5]+')'
290 return
291
292 p1 = p[1]
293 re_groups = self.re_cmath_function.match(p1)
294 if re_groups:
295 p1 = re_groups.group("name")
296 new = aloha_lib.KERNEL.add_function_expression(p1, eval(p[3]), eval(p[5]))
297 p[0] = str(new)
298
300 "expression : FUNCTION '(' expression ',' expression ',' expression ')'"
301
302 if p[1] in self.aloha_object:
303 p[0] = p[1]+'('+p[3]+','+ p[5]+','+p[7]+')'
304 return
305
306 p1 = p[1]
307 re_groups = self.re_cmath_function.match(p1)
308 if re_groups:
309 p1 = re_groups.group("name")
310
311 new = aloha_lib.KERNEL.add_function_expression(p1, eval(p[3]), eval(p[5]),eval(p[7]))
312 p[0] = str(new)
313
315 "expression : FUNCTION '(' expression ',' expression ',' expression ',' expression ')'"
316 if p[1] in self.aloha_object:
317 p[0] = p[1]+'('+p[3]+','+ p[5]+','+ p[7]+','+ p[9]+')'
318 return
319
320 p1 = p[1]
321 re_groups = self.re_cmath_function.match(p1)
322 if re_groups:
323 p1 = re_groups.group("name")
324 args = [eval(p[2*i+1]) for i in [1,2,3,4]]
325 new = aloha_lib.KERNEL.add_function_expression(p1, *args)
326 p[0] = str(new)
327
329 '''expression : expression '=' expression
330 | expression '+' expression
331 | expression '-' expression
332 | expression '*' expression
333 | expression '/' expression'''
334 if p[2] != '/' or p[3].isdigit() or p[3].endswith('.'):
335 p[0] = p[1] + p[2] + p[3]
336 else:
337 denom = eval(p[3])
338 if isinstance(denom, numbers.Number):
339 p[0] = p[1] + '*' + str(1/denom)
340 else:
341 new = aloha_lib.KERNEL.add_function_expression('/', denom)
342 p[0] = p[1] + ' * ' + str(new)
343
344
345
346
347
348 if __name__ == '__main__':
349
350
351 calc = ALOHAExpressionParser()
352 while 1:
353 try:
354 s = raw_input('calc > ')
355 except EOFError:
356 break
357 if not s: continue
358 logger.info(calc.parse(s))
359