begin
realfn eval {evaluate sub-expression}
routinespec pushopd(real val)
routinespec pushop(integer op)
realfnspec popopd
integerfnspec popop
realfnspec nextopd
integerfnspec nextop
routinespec operate
constinteger plus=1,minus=2,times=3,divide=4,exp=5,assign=6,end=7,space=' '
constintegerarray prec(plus:assign)=1,1,2,2,3,0
realarray opds(0:4) {operand stack}
integerarray ops(0:3) {operator stack}
ownrealarray vars('a':'z')=0(*)
ownintegerarray vara('a':'z')=0(*)
integer op,opdsp,opsp,var
opdsp=0 ; opsp=0 {init stack pointers}
pushopd(nextopd) {first operand}
cycle {for each operator}
op=nextop
if op=end then exit
operate while opsp>0 and prec(ops(opsp))>=prec(op)
if op=assign then start
read symbol(var)
unless 'a'<=var<='z' or 'A'<=var<='Z' then print symbol(var) c
and print string(" variable") and signal 15
if 'A'<=var<='Z' then var=var-'A'+'a'
vars(var)=opds(opdsp)
vara(var)=1 {assigned}
continue
finish
pushop(op)
pushopd(nextopd)
repeat
operate while opsp>0
result=popopd
!
routine pushopd(real val)
opdsp=opdsp+1
opds(opdsp)=val
end
!
routine pushop(integer op)
opsp=opsp+1
ops(opsp)=op
end
!
realfn popopd
real val
val=opds(opdsp)
opdsp=opdsp-1
result=val
end
!
integerfn popop
integer op
op=ops(opsp)
opsp=opsp-1
result=op
end
!
realfn nextopd
integer var
real opd
skip symbol while next symbol=space or next symbol=nl
if '0'<=next symbol<='9' or next symbol='-' or next symbol='.' c
then read(opd) and result=opd
if next symbol='(' then skip symbol and result=eval
if 'a'<=next symbol<='z' or 'A'<=next symbol<='Z' then start
read symbol(var)
if 'A'<=var<='Z' then var=var-'A'+'a'
if vara(var)=0 then print symbol(var) and c
print string(" unassigned") and signal 15
result=vars(var)
finish
read symbol(var)
print symbol(var)
print string(" operand")
signal 15
end
!
integerfn nextop
integer sym
skip symbol while next symbol=space
read symbol(sym)
if sym='+' then result=plus
if sym='-' then result=minus
if sym='*' then result=times
if sym='/' then result=divide
if sym='^' then result=exp
if sym=':' then result=assign
if sym=')' or sym=nl then result=end
print symbol(sym)
print string(" operator")
signal 15
end
!
routine operate
real opd1,opd2
switch opn(plus:exp)
opd2=popopd
opd1=popopd
->opn(popop)
opn(plus):pushopd(opd1+opd2) ; return
opn(minus):pushopd(opd1-opd2) ; return
opn(times):pushopd(opd1*opd2) ; return
opn(divide):if opd2=0 then print string("divide by zero") and signal 15
pushopd(opd1/opd2) ; return
opn(exp):pushopd(opd1^int(opd2))
end
!
end {of eval}
real val
on event 9,15 start {to trap everything}
{*} stop if Event_Event = 9
print string("?
")
->again ; finish
select input(0); select output(0)
prompt("eval:")
again:val=eval
if val=int(val) then write(int(val),0) { imp77 perms missing} {%else print(val,0,4)}
newline
->again
endofprogram