-
Notifications
You must be signed in to change notification settings - Fork 8
/
caalc.py
89 lines (74 loc) · 2.32 KB
/
caalc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/python
# coding: utf
import readline
import sys
import tpg
import itertools
def make_op(s):
return {
'+': lambda x,y: x+y,
'-': lambda x,y: x-y,
'*': lambda x,y: x*y,
'/': lambda x,y: x/y,
'&': lambda x,y: x&y,
'|': lambda x,y: x|y,
}[s]
class Vector(list):
def __init__(self, *argp, **argn):
list.__init__(self, *argp, **argn)
def __str__(self):
return "[" + " ".join(str(c) for c in self) + "]"
def __op(self, a, op):
try:
return self.__class__(op(s,e) for s,e in zip(self, a))
except TypeError:
return self.__class__(op(c,a) for c in self)
def __add__(self, a): return self.__op(a, lambda c,d: c+d)
def __sub__(self, a): return self.__op(a, lambda c,d: c-d)
def __div__(self, a): return self.__op(a, lambda c,d: c/d)
def __mul__(self, a): return self.__op(a, lambda c,d: c*d)
def __and__(self, a):
try:
return reduce(lambda s, (c,d): s+c*d, zip(self, a), 0)
except TypeError:
return self.__class__(c and a for c in self)
def __or__(self, a):
try:
return self.__class__(itertools.chain(self, a))
except TypeError:
return self.__class__(c or a for c in self)
class Calc(tpg.Parser):
r"""
separator spaces: '\s+' ;
separator comment: '#.*' ;
token fnumber: '\d+[.]\d*' float ;
token number: '\d+' int ;
token op1: '[|&+-]' make_op ;
token op2: '[*/]' make_op ;
token id: '\w+' ;
START/e -> Operator $e=None$ | Expr/e | $e=None$ ;
Operator -> Assign ;
Assign -> id/i '=' Expr/e $Vars[i]=e$ ;
Expr/t -> Fact/t ( op1/op Fact/f $t=op(t,f)$ )* ;
Fact/f -> Atom/f ( op2/op Atom/a $f=op(f,a)$ )* ;
Atom/a -> Vector/a
| id/i ( check $i in Vars$ | error $"Undefined variable '{}'".format(i)$ ) $a=Vars[i]$
| fnumber/a
| number/a
| '\(' Expr/a '\)' ;
Vector/$Vector(a)$ -> '\[' '\]' $a=[]$ | '\[' Atoms/a '\]' ;
Atoms/v -> Atom/a Atoms/t $v=[a]+t$ | Atom/a $v=[a]$ ;
"""
calc = Calc()
Vars={}
PS1='--> '
Stop=False
while not Stop:
line = raw_input(PS1)
try:
res = calc(line)
except tpg.Error as exc:
print >> sys.stderr, exc
res = None
if res != None:
print res