“算术表达式”有两种形式:
'(op e1 e2)
这样的结构(其中 e1
和 e2
是两个“算术表达式”--chekck token is number
isnumber = (exp) -> tonumber(exp) ~= nil
isspace = (c) -> c == ' ' or c == '\t'
len = (exp) -> string.len(exp)
--trim space
trim = (exp ,pos) ->
while pos <= len(exp) and isspace string.sub(exp,pos,pos)
pos += 1
pos
--get token from pos and return next valid pos
token = (exp,pos) ->
pos = trim(exp,pos)
if pos > len(exp)
return nil,pos
lpos = pos
while pos <= len(exp) and not isspace string.sub(exp,pos,pos)
pos += 1
t = string.sub(exp,lpos,pos-1)
return t,pos
calc = (exp,pos)->
t ,pos = token(exp,pos)
if t == nil
return nil,pos
if isnumber t
return tonumber(t),pos
if t == '('
op,pos = token(exp,pos)
v1 ,pos = calc(exp,pos)
v2,pos = calc(exp,pos)
t ,pos = token(exp,pos)
if( t ~= ')')
return nil,pos
v = nil
switch op
when '+'
v = v1 + v2
when '-'
v = v1 - v2
when '/'
v = v1 / v2
when '*'
v = v1 / v2
else
v = nil
return v,pos
else
return nil,pos
run = (exp) ->
r,pos = calc(exp,1)
if r == nil
print('error exp ',exp,'at pos ',pos)
return r
print run '( / ( + 100 2 ) 3 )'
print run '( - ( + ( * 10.25 333 ) 999 ) 100 )'
print rum '(+ 1 2)' --failed
print run ' + 1 '
print run '( / ( + 1 2 3 )'
print run '( ^ 1 2 )'