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 import logging
21 import os
22 import re
23 import sys
24 import copy
25
26 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
27 sys.path.append(os.path.join(root_path, os.path.pardir))
28
29 import madgraph.various.misc as misc
30
31 from madgraph import MadGraph5Error
32 import vendor.ply.lex as lex
33 import vendor.ply.yacc as yacc
34 import models.check_param_card as check_param_card
35
36 logger = logging.getLogger('madgraph.ufo_parsers')
37
38
39
41 """Appropriate Error for a wrong parsing"""
42
44 """A base class for parsers for algebraic expressions coming from UFO."""
45
46 parsed_string = ""
47 logical_equiv = {}
48
50 """Initialize the lex and yacc"""
51
52 modname = self.__class__.__name__
53 self.debugfile = os.path.devnull
54 self.tabmodule = os.path.join(root_path, "iolibs", modname + "_" + "parsetab.py")
55 lex.lex(module=self, debug=0)
56 self.y=yacc.yacc(module=self, debug=0, debugfile=self.debugfile,
57 tabmodule=self.tabmodule)
58
63
64
65 tokens = (
66 'LOGICAL','LOGICALCOMB','POWER', 'CSC', 'SEC', 'ACSC', 'ASEC', 'TAN',
67 'SQRT', 'CONJ', 'RE', 'RE2', 'IM', 'PI', 'COMPLEX', 'FUNCTION', 'IF','ELSE',
68 'VARIABLE', 'NUMBER','COND','REGLOG', 'REGLOGP', 'REGLOGM','RECMS','ARG'
69 )
70 literals = "=+-*/(),"
71
72
73
75 r'(?<!\w)csc(?=\()'
76 return t
78 r'(?<!\w)sec(?=\()'
79 return t
81 r'(?<!\w)acsc(?=\()'
82 return t
84 r'(?<!\w)tan(?=\()|(?<!\w)cmath.tan(?=\()'
85 return t
87 r'(?<!\w)asec(?=\()'
88 return t
90 r'(?<!\w)reglog(?=\()'
91 return t
93 r'(?<!\w)reglogp(?=\()'
94 return t
96 r'(?<!\w)reglogm(?=\()'
97 return t
99 r'(?<!\w)recms(?=\()'
100 return t
102 r'(?<!\w)cond(?=\()'
103 return t
105 r'(?<!\w)arg(?=\()'
106 return t
108 r'(?<!\w)if\s'
109 return t
111 r'(?<!\w)else\s'
112 return t
114 r'==|!=|<=|>=|<|>'
115 return t
117 r'(?<!\w)and(?=[\s\(])|(?<!\w)or(?=[\s\(])'
118 return t
120 r'cmath\.sqrt'
121 return t
123 r'cmath\.pi'
124 return t
126 r'complexconjugate'
127 return t
129 r'(?<!\w)im(?=\()'
130 return t
132 r'(?<!\w)re(?=\()'
133 return t
135 r'\.real|\.imag'
136 return t
137
139 r'(?<!\w)complex(?=\()'
140 return t
142 r'(cmath\.){0,1}[a-zA-Z_][0-9a-zA-Z_]*(?=\()'
143 return t
145 r'[a-zA-Z_][0-9a-zA-Z_]*'
146 return t
147
148 t_NUMBER = r'([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)([eE][+-]{0,1}[0-9]+){0,1}j{0,1}'
149 t_POWER = r'\*\*'
150
151 t_ignore = " \t"
152
153 re_cmath_function = re.compile("cmath\.(?P<name>[0-9a-zA-Z_]+)")
154
156 r'\n+'
157 t.lexer.lineno += t.value.count("\n")
158
160 logger.error("Illegal character '%s'" % t.value[0])
161 t.lexer.skip(1)
162
163
164 - def build(self,**kwargs):
165 self.lexer = lex.lex(module=self, **kwargs)
166
167
168
169 precedence = (
170 ('right', 'LOGICALCOMB'),
171 ('right', 'LOGICAL'),
172 ('right','IF'),
173 ('right','ELSE'),
174 ('left','='),
175 ('left','+','-'),
176 ('left','*','/'),
177 ('left', 'RE2'),
178 ('right','UMINUS'),
179 ('left','POWER'),
180 ('right','REGLOG'),
181 ('right','REGLOGP'),
182 ('right','REGLOGM'),
183 ('right','RECMS'),
184 ('right','ARG'),
185 ('right','CSC'),
186 ('right','SEC'),
187 ('right','ACSC'),
188 ('right','ASEC'),
189 ('right','SQRT'),
190 ('right','CONJ'),
191 ('right','RE'),
192 ('right','IM'),
193 ('right','FUNCTION'),
194 ('right','COMPLEX'),
195 ('right','COND'),
196 )
197
198
202
204 '''expression : expression '=' expression
205 | expression '+' expression
206 | expression '-' expression
207 | expression '*' expression
208 | expression '/' expression'''
209 p[0] = p[1] + p[2] + p[3]
210
212 '''boolexpression : expression LOGICAL expression'''
213 if p[2] not in self.logical_equiv:
214 p[0] = p[1] + p[2] + p[3]
215 else:
216 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
217
219 '''boolexpression : boolexpression LOGICALCOMB boolexpression'''
220 if p[2] not in self.logical_equiv:
221 p[0] = p[1] + p[2] + p[3]
222 else:
223 p[0] = p[1] + self.logical_equiv[p[2]] + p[3]
224
226 "expression : '-' expression %prec UMINUS"
227 p[0] = '-' + p[2]
228
230 "group : '(' expression ')'"
231 p[0] = '(' + p[2] +')'
232
234 "boolexpression : '(' boolexpression ')'"
235 p[0] = '(' + p[2] +')'
236
238 "expression : group"
239 p[0] = p[1]
240
242 "expression : FUNCTION '(' expression ')'"
243 p1 = p[1]
244 re_groups = self.re_cmath_function.match(p1)
245 if re_groups:
246 p1 = re_groups.group("name")
247 p[0] = p1 + '(' + p[3] + ')'
248
250 "expression : FUNCTION '(' expression ',' expression ')'"
251 p1 = p[1]
252 re_groups = self.re_cmath_function.match(p1)
253 if re_groups:
254 p1 = re_groups.group("name")
255 p[0] = p1 + '(' + p[3] + ',' + p[5] + ')'
256
258 if p:
259 raise ModelError("Syntax error at '%s' (%s)." %(p.value,p))
260 else:
261 logger.error("Syntax error at EOF")
262 self.parsed_string = "Error"
263
265 """A parser for UFO algebraic expressions, outputting
266 Fortran-style code."""
267
268
269
270
271 logical_equiv = {'==':'.EQ.',
272 '>=':'.GE.',
273 '<=':'.LE.',
274 '!=':'.NE.',
275 '>':'.GT.',
276 '<':'.LT.',
277 'or':'.OR.',
278 'and':'.AND.'}
279
281 "expression : NUMBER"
282 if p[1].endswith('j'):
283 p[0] = ('DCMPLX(0d0, %e)' % float(p[1][:-1])).replace('e', 'd')
284 else:
285 p[0] = ('%e' % float(p[1])).replace('e', 'd')
286
288 "expression : VARIABLE"
289 p[0] = p[1].lower()
290
292 'expression : expression POWER expression'
293 try:
294 p3 = float(p[3].replace('d','e'))
295
296 if p3 == int(p3):
297 p3 = str(int(p3))
298 p[0] = p[1] + "**" + p3
299 else:
300 p[0] = p[1] + "**" + p[3]
301 except Exception:
302 p[0] = p[1] + "**" + p[3]
303
305 "expression : expression IF boolexpression ELSE expression "
306 p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
307
309 "expression : expression IF expression ELSE expression "
310 p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\
311 %(p[3], p[1], p[5])
312
314 "expression : COND '(' expression ',' expression ',' expression ')'"
315 p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
316
318 "expression : RECMS '(' boolexpression ',' expression ')'"
319 p[0] = 'RECMS('+p[3]+',DCMPLX('+p[5]+'))'
320
322 "expression : COMPLEX '(' expression ',' expression ')'"
323 p[0] = 'DCMPLX(' + p[3] + ',' + p[5] + ')'
324
326 '''expression : CSC group
327 | SEC group
328 | ACSC group
329 | ASEC group
330 | RE group
331 | IM group
332 | ARG group
333 | SQRT group
334 | CONJ group
335 | REGLOG group
336 | REGLOGP group
337 | REGLOGM group
338 | TAN group'''
339
340 if p[1] == 'csc': p[0] = '1d0/sin' + p[2]
341 elif p[1] == 'sec': p[0] = '1d0/cos' + p[2]
342 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
343 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
344 elif p[1] in ['tan', 'cmath.tan'] : p[0] = 'tan(dble' + p[2]+')'
345 elif p[1] == 're': p[0] = 'dble' + p[2]
346 elif p[1] == 'im': p[0] = 'dimag' + p[2]
347 elif p[1] == 'arg': p[0] = 'arg(DCMPLX'+p[2]+')'
348 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(dcmplx' + p[2]+')'
349 elif p[1] == 'complexconjugate': p[0] = 'conjg(DCMPLX' + p[2]+')'
350 elif p[1] == 'reglog': p[0] = 'reglog(DCMPLX' + p[2] +')'
351 elif p[1] == 'reglogp': p[0] = 'reglogp(DCMPLX' + p[2] + ')'
352 elif p[1] == 'reglogm': p[0] = 'reglogm(DCMPLX' + p[2] + ')'
353
354
356 ''' expression : expression RE2 '''
357
358 if p[2] == '.real':
359 if p[1].startswith('('):
360 p[0] = 'dble' +p[1]
361 else:
362 p[0] = 'dble(%s)' % p[1]
363 elif p[2] == '.imag':
364 if p[1].startswith('('):
365 p[0] = 'dimag' +p[1]
366 else:
367 p[0] = 'dimag(%s)' % p[1]
368
370 '''expression : PI'''
371 p[0] = 'pi'
372
374 """A parser for UFO algebraic expressions, outputting
375 Fortran-style code for quadruple precision computation."""
376
377 mp_prefix = check_param_card.ParamCard.mp_prefix
378
379
380
381
383 "expression : NUMBER"
384
385 if p[1].endswith('j'):
386 p[0] = 'CMPLX(0.000000e+00_16, %e_16 ,KIND=16)' % float(p[1][:-1])
387 else:
388 p[0] = '%e_16' % float(p[1])
389
391 "expression : VARIABLE"
392
393 p[0] = (self.mp_prefix+p[1]).lower()
394
396 'expression : expression POWER expression'
397 try:
398 p3 = float(p[3].replace('_16',''))
399
400 if p3 == int(p3):
401 p3 = str(int(p3))
402 p[0] = p[1] + "**" + p3
403 else:
404 p[0] = p[1] + "**" + p[3]
405 except Exception:
406 p[0] = p[1] + "**" + p[3]
407
409 "expression : expression IF boolexpression ELSE expression "
410 p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
411
413 "expression : expression IF expression ELSE expression "
414 p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\
415 %(p[3], p[1], p[5])
416
418 "expression : COMPLEX '(' expression ',' expression ')'"
419 p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
420
422 "expression : COND '(' expression ',' expression ',' expression ')'"
423 p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\
424 ',KIND=16),CMPLX('+p[7]+',KIND=16))'
425
427 "expression : RECMS '(' boolexpression ',' expression ')'"
428 p[0] = 'MP_RECMS('+p[3]+',CMPLX('+p[5]+',KIND=16))'
429
431 '''expression : CSC group
432 | SEC group
433 | ACSC group
434 | ASEC group
435 | RE group
436 | IM group
437 | ARG group
438 | SQRT group
439 | CONJ group
440 | REGLOG group
441 | REGLOGP group
442 | REGLOGM group
443 | TAN group'''
444
445 if p[1] == 'csc': p[0] = '1e0_16/cos' + p[2]
446 elif p[1] == 'sec': p[0] = '1e0_16/sin' + p[2]
447 elif p[1] == 'acsc': p[0] = 'asin(1e0_16/' + p[2] + ')'
448 elif p[1] == 'asec': p[0] = 'acos(1e0_16/' + p[2] + ')'
449 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan(real' + p[2]+')'
450 elif p[1] == 're': p[0] = 'real' + p[2]
451 elif p[1] == 'im': p[0] = 'imag' + p[2]
452 elif p[1] == 'arg': p[0] = 'mp_arg(CMPLX(' + p[2] + ',KIND=16))'
453 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt(CMPLX(' + p[2] + ',KIND=16))'
454 elif p[1] == 'complexconjugate': p[0] = 'conjg(CMPLX(' + p[2] + ',KIND=16))'
455 elif p[1] == 'reglog': p[0] = 'mp_reglog(CMPLX(' + p[2] +',KIND=16))'
456 elif p[1] == 'reglogp': p[0] = 'mp_reglogp(CMPLX(' + p[2] + ',KIND=16))'
457 elif p[1] == 'reglogm': p[0] = 'mp_reglogm(CMPLX(' + p[2] + ',KIND=16))'
458
460 ''' expression : expression RE2 '''
461
462 if p[2] == '.real':
463 if p[1].startswith('('):
464 p[0] = 'real' +p[1]
465 else:
466 p[0] = 'real(%s)' % p[1]
467 elif p[2] == '.imag':
468 if p[1].startswith('('):
469 p[0] = 'imag' +p[1]
470 else:
471 p[0] = 'imag(%s)' % p[1]
472
473
475 '''expression : PI'''
476 p[0] = self.mp_prefix+'pi'
477
479 """A parser for UFO algebraic expressions, outputting
480 C++-style code."""
481
482 logical_equiv = {'==':'==',
483 '>=':'>=',
484 '<=':'<=',
485 '!=':'!=',
486 '>':'>',
487 '<':'<',
488 'or':'||',
489 'and':'&&'}
490
491
492
493
495 'expression : NUMBER'
496
497 if p[1].endswith('j'):
498 p[0] = 'std::complex<double>(0., %e)' % float(p[1][:-1])
499 else:
500 p[0] = ('%e' % float(p[1])).replace('e', 'd')
501
502
503 p[0] = p[1]
504
505 if float(p[1]) == int(float(p[1])) and float(p[1]) < 1000:
506 p[0] = str(int(float(p[1]))) + '.'
507
509 'expression : VARIABLE'
510 p[0] = p[1]
511
513 "expression : expression IF boolexpression ELSE expression "
514 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
515
517 "expression : expression IF expression ELSE expression "
518 p[0] = '(%s ? %s : %s)' % (p[3], p[1], p[5])
519
521 "expression : COND '(' expression ',' expression ',' expression ')'"
522 p[0] = 'COND('+p[3]+','+p[5]+','+p[7]+')'
523
525 "expression : RECMS '(' boolexpression ',' expression ')'"
526 p[0] = 'RECMS('+p[3]+','+p[5]+')'
527
529 'expression : expression POWER expression'
530 p1=p[1]
531 p3=p[3]
532 if p[1][0] == '(' and p[1][-1] == ')':
533 p1 = p[1][1:-1]
534 if p[3][0] == '(' and p[3][-1] == ')':
535 p3 = p[3][1:-1]
536 p[0] = 'pow(' + p1 + ',' + p3 + ')'
537
539 "expression : COMPLEX '(' expression ',' expression ')'"
540 p[0] = 'std::complex<double>(' + p[3] + ',' + p[5] + ')'
541
543 '''expression : CSC group
544 | SEC group
545 | ACSC group
546 | ASEC group
547 | TAN group
548 | RE group
549 | IM group
550 | ARG group
551 | SQRT group
552 | CONJ group
553 | REGLOG group
554 | REGLOGP group
555 | REGLOGM group'''
556 if p[1] == 'csc': p[0] = '1./cos' + p[2]
557 elif p[1] == 'sec': p[0] = '1./sin' + p[2]
558 elif p[1] == 'acsc': p[0] = 'asin(1./' + p[2] + ')'
559 elif p[1] == 'asec': p[0] = 'acos(1./' + p[2] + ')'
560 elif p[1] in ['tan', 'cmath.tan']: p[0] = 'tan' +p[2]
561 elif p[1] == 're': p[0] = 'real' + p[2]
562 elif p[1] == 'im': p[0] = 'imag' + p[2]
563 elif p[1] == 'arg':p[0] = 'arg' + p[2]
564 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'sqrt' + p[2]
565 elif p[1] == 'complexconjugate': p[0] = 'conj' + p[2]
566 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
567 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
568 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
569
571 ''' expression : expression RE2 '''
572
573 if p[2] == '.real':
574 if p[1].startswith('('):
575 p[0] = 'real' +p[1]
576 else:
577 p[0] = 'real(%s)' % p[1]
578 elif p[2] == '.imag':
579 if p[1].startswith('('):
580 p[0] = 'imag' +p[1]
581 else:
582 p[0] = 'imag(%s)' % p[1]
583
584
586 '''expression : PI'''
587 p[0] = 'M_PI'
588
590 """An ad hoc parser for UFO algebraic expressions with if statement, outputting
591 Python-style code, with the conditional 'if' expressions simplified using
592 pre-defined set of variables specified when instanciating this parser."""
593
594 logical_equiv = {'==':'==',
595 '>=':'>=',
596 '<=':'<=',
597 '!=':'!=',
598 '>':'>',
599 '<':'<',
600 'or':' or ',
601 'and':' and '}
602
604 """Initialize the lex and yacc"""
605
606 self.changes_performed = 0
607
608 if len(args) > 0:
609 if isinstance(args[0],dict):
610 self.defined_variables = copy.copy(args[0])
611 elif isinstance(args[0],str):
612 try:
613 self.defined_variables = eval(args[0])
614 except:
615 raise ModelError, 'The expression "%s"'%str(args[0])+\
616 " given as defined variables for the UFOExpressionParserPythonIF"+\
617 " does not have a correct syntax."
618 if not isinstance(self.defined_variables, dict):
619 raise ModelError, 'The argument "%s"'%str(args[0])+\
620 " given as defined variables for the UFOExpressionParserPythonIF"+\
621 " is not a dictionary."
622 else:
623 raise ModelError, "The argument %s"%str(args[0])+\
624 " given as defined variables for the UFOExpressionParserPythonIF"+\
625 " must be either a dictionary or a string."
626 args = args[1:]
627 for key, value in self.defined_variables.items():
628 if not isinstance(key,str) or \
629 not any(isinstance(value,t) for t in [float,complex,int]):
630
631 del self.defined_variables[key]
632
633 else:
634
635
636
637 self.defined_variables = None
638
639 super(UFOExpressionParserPythonIF,self).__init__(*args, **kw)
640
641 - def parse(self, *args, **kw):
642 """ Wrapper around the parse function so as to also return the number
643 of if substitutions made."""
644 self.changes_performed = 0
645 new_expression = super(UFOExpressionParserPythonIF,self).parse(*args, **kw)
646 return new_expression, self.changes_performed
647
649 "expression : NUMBER"
650 p[0] = p[1]
651
653 "expression : VARIABLE"
654 p[0] = p[1]
655
657 'expression : expression POWER expression'
658 p[0] = p[1] + "**" + p[3]
659
661 "expression : expression IF boolexpression ELSE expression "
662 if self.defined_variables is None:
663 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
664 return
665 try:
666 p[0] = '%s'%p[1] if eval(p[3],self.defined_variables) else '%s'%p[5]
667 self.changes_performed += 1
668 except Exception:
669 p[0] = '%s if %s else %s'%(p[1],p[3],p[5])
670
672 "expression : expression IF expression ELSE expression "
673 if self.defined_variables is None:
674 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
675 return
676 try:
677 p[0] = '%s'%p[1] if eval(p[3]+'!= 0.0',self.defined_variables) else '%s'%p[5]
678 self.changes_performed += 1
679 except Exception:
680 p[0] = '%s if %s!=0.0 else %s'%(p[1],p[3],p[5])
681
683 "expression : COND '(' expression ',' expression ',' expression ')'"
684
685
686 p[0] = 'cond('+p[3]+','+p[5]+','+p[7]+')'
687
689 "expression : COMPLEX '(' expression ',' expression ')'"
690 p[0] = 'complex(' + p[3] + ',' + p[5] + ')'
691
693 "expression : RECMS '(' boolexpression ',' expression ')'"
694 p[0] = 'recms('+p[3]+','+p[5]+')'
695
697 '''expression : CSC group
698 | SEC group
699 | ACSC group
700 | ASEC group
701 | RE group
702 | IM group
703 | ARG group
704 | SQRT group
705 | TAN group
706 | CONJ group
707 | REGLOG group
708 | REGLOGP group
709 | REGLOGM group'''
710 if p[1] == 'csc': p[0] = 'csc' + p[2]
711 elif p[1] == 'sec': p[0] = 'sec' + p[2]
712 elif p[1] == 'acsc': p[0] = 'acsc' + p[2]
713 elif p[1] == 'asec': p[0] = 'asec' + p[2]
714 elif p[1] in ['tan','cmath.tan']: p[0] = 'tan' + p[2]
715 elif p[1] == 're': p[0] = 're' + p[2]
716 elif p[1] == 'im': p[0] = 'im' + p[2]
717 elif p[1] == 'arg': p[0] = 'arg' + p[2]
718 elif p[1] == 'cmath.sqrt' or p[1] == 'sqrt': p[0] = 'cmath.sqrt' + p[2]
719 elif p[1] == 'complexconjugate': p[0] = 'complexconjugate' + p[2]
720 elif p[1] == 'reglog': p[0] = 'reglog' + p[2]
721 elif p[1] == 'reglogp': p[0] = 'reglogp' + p[2]
722 elif p[1] == 'reglogm': p[0] = 'reglogm' + p[2]
723
725 ''' expression : expression RE2 '''
726 p[0] = p[1]+p[2]
727
729 '''expression : PI'''
730 p[0] = 'cmath.pi'
731
732
733
734
735 if __name__ == '__main__':
736
737 if len(sys.argv) == 1:
738 print "Please specify a parser: fortran, mpfortran or c++"
739 exit()
740 if sys.argv[1] == "fortran":
741 calc = UFOExpressionParserFortran()
742 elif sys.argv[1] == "mpfortran":
743 calc = UFOExpressionParserMPFortran()
744 elif sys.argv[1] == "c++":
745 calc = UFOExpressionParserCPP()
746 elif sys.argv[1] == "aloha":
747 calc = UFOExpressionParserCPP()
748 elif sys.argv[1] == "pythonif":
749 if len(sys.argv) > 2:
750 calc = UFOExpressionParserPythonIF(sys.argv[2])
751 else:
752 calc = UFOExpressionParserPythonIF()
753 else:
754 print "Please specify a parser: fortran, mpfortran, c++ or pythonif"
755 print "You gave", sys.argv[1]
756 if len(sys.argv) > 2:
757 print "with the second argument",sys.argv[2]
758 exit()
759
760 while 1:
761 try:
762 s = raw_input('calc > ')
763 except EOFError:
764 break
765 if not s: continue
766 print calc.parse(s)
767