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 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
41 """A base class for parsers for algebraic expressions coming from UFO."""
42
43 parsed_string = ""
44
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
59
60
61 tokens = (
62 'POWER', 'CSC', 'SEC', 'ACSC', 'ASEC',
63 'SQRT', 'CONJ', 'RE', 'IM', 'PI', 'COMPLEX', 'FUNCTION',
64 'VARIABLE', 'NUMBER'
65 )
66 literals = "=+-*/(),'"
67
68
69
71 r'(?<!\w)csc(?=\()'
72 return t
74 r'(?<!\w)sec(?=\()'
75 return t
77 r'(?<!\w)acsc(?=\()'
78 return t
80 r'(?<!\w)asec(?=\()'
81 return t
83 r'cmath\.sqrt'
84 return t
86 r'cmath\.pi'
87 return t
89 r'complexconjugate'
90 return t
92 r'(?<!\w)im(?=\()'
93 return t
95 r'(?<!\w)re(?=\()'
96 return t
98 r'(?<!\w)complex(?=\()'
99 return t
101 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
102 return 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
115 r'\n+'
116 t.lexer.lineno += t.value.count("\n")
117
119 logger.error("Illegal character '%s'" % t.value[0])
120 t.lexer.skip(1)
121
122
123 - def build(self,**kwargs):
124 self.lexer = lex.lex(module=self, **kwargs)
125
126
127
128
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
151
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
161 "expression : '-' expression %prec UMINUS"
162 p[0] = '-' + p[2]
163
165 "group : '(' expression ')'"
166 p[0] = '(' + p[2] +')'
167
169 "expression : group"
170 p[0] = p[1]
171
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
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
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
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
205 '''expression : PI'''
206 KERNEL.has_pi = True
207 p[0] = 'Param(\'PI\')'
208
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
224 "expression : VARIABLE"
225 p[0] = 'Param(\'%s\')' % p[1]
226
228 "expression : '\\'' VARIABLE '\\''"
229 p[0] = '\'%s\'' % p[2]
230
232 "expression : '\\'' expression '\\''"
233 p[0] = '\'%s\'' % p[2]
234
236 "expression : COMPLEX '(' expression ',' expression ')'"
237 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
238
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
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
272
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
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
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
325
326
327
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
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