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
40
42 """A base class for parsers for algebraic expressions coming from UFO."""
43
44 parsed_string = ""
45
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
60
61
62 tokens = (
63 'POWER', 'CSC', 'SEC', 'ACSC', 'ASEC',
64 'SQRT', 'CONJ', 'RE', 'IM', 'PI', 'COMPLEX', 'FUNCTION',
65 'VARIABLE', 'NUMBER'
66 )
67 literals = "=+-*/(),'"
68
69
70
72 r'(?<!\w)csc(?=\()'
73 return t
75 r'(?<!\w)sec(?=\()'
76 return t
78 r'(?<!\w)acsc(?=\()'
79 return t
81 r'(?<!\w)asec(?=\()'
82 return t
84 r'cmath\.sqrt'
85 return t
87 r'cmath\.pi'
88 return t
90 r'complexconjugate'
91 return t
93 r'(?<!\w)im(?=\()'
94 return t
96 r'(?<!\w)re(?=\()'
97 return t
99 r'(?<!\w)complex(?=\()'
100 return t
102 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
103 return 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
116 r'\n+'
117 t.lexer.lineno += t.value.count("\n")
118
120 logger.error("Illegal character '%s'" % t.value[0])
121 t.lexer.skip(1)
122
123
124 - def build(self,**kwargs):
125 self.lexer = lex.lex(module=self, **kwargs)
126
127
128
129
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
152
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
162 "expression : '-' expression %prec UMINUS"
163 p[0] = '-' + p[2]
164
166 "group : '(' expression ')'"
167 p[0] = '(' + p[2] +')'
168
170 "expression : group"
171 p[0] = p[1]
172
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
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
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
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
206 '''expression : PI'''
207 KERNEL.has_pi = True
208 p[0] = 'Param(\'PI\')'
209
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
225 "expression : VARIABLE"
226 p[0] = 'Param(\'%s\')' % p[1]
227
229 "expression : '\\'' VARIABLE '\\''"
230 p[0] = '\'%s\'' % p[2]
231
233 "expression : '\\'' expression '\\''"
234 p[0] = '\'%s\'' % p[2]
235
237 "expression : COMPLEX '(' expression ',' expression ')'"
238 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
239
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
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
273
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
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
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
330
331
332
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
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