Add tasks for all the new languages
This commit is contained in:
parent
9dc3c2bb62
commit
bba7bfd280
13208 changed files with 134745 additions and 0 deletions
233
Task/Arithmetic-evaluation/ERRE/arithmetic-evaluation.erre
Normal file
233
Task/Arithmetic-evaluation/ERRE/arithmetic-evaluation.erre
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
PROGRAM EVAL
|
||||
|
||||
!
|
||||
! arithmetic expression evaluator
|
||||
!
|
||||
|
||||
!$KEY
|
||||
|
||||
LABEL 98,100,110
|
||||
|
||||
DIM STACK$[50]
|
||||
|
||||
PROCEDURE DISEGNA_STACK
|
||||
!$RCODE="LOCATE 3,1"
|
||||
!$RCODE="COLOR 0,7"
|
||||
PRINT(TAB(35);"S T A C K";TAB(79);)
|
||||
!$RCODE="COLOR 7,0"
|
||||
FOR TT=1 TO 38 DO
|
||||
IF TT>=20 THEN
|
||||
!$RCODE="LOCATE 3+TT-19,40"
|
||||
ELSE
|
||||
!$RCODE="LOCATE 3+TT,1"
|
||||
END IF
|
||||
IF TT=NS THEN PRINT(">";) ELSE PRINT(" ";) END IF
|
||||
PRINT(RIGHT$(STR$(TT),2);"³ ";STACK$[TT];" ")
|
||||
END FOR
|
||||
REPEAT
|
||||
GET(Z$)
|
||||
UNTIL LEN(Z$)<>0
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE COMPATTA_STACK
|
||||
IF NS>1 THEN
|
||||
R=1
|
||||
WHILE R<NS DO
|
||||
IF INSTR(OP_LIST$,STACK$[R])=0 AND INSTR(OP_LIST$,STACK$[R+1])=0 THEN
|
||||
FOR R1=R TO NS-1 DO
|
||||
STACK$[R1]=STACK$[R1+1]
|
||||
END FOR
|
||||
NS=NS-1
|
||||
END IF
|
||||
R=R+1
|
||||
END WHILE
|
||||
END IF
|
||||
DISEGNA_STACK
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE CALC_ARITM
|
||||
L=NS1
|
||||
WHILE L<=NS2 DO
|
||||
IF STACK$[L]="^" THEN
|
||||
IF L>=NS2 THEN GOTO 100 END IF
|
||||
N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
|
||||
IF STACK$[L]="^" THEN
|
||||
RI#=N1#^N2#
|
||||
END IF
|
||||
STACK$[L-1]=STR$(RI#)
|
||||
N=L
|
||||
WHILE N<=NS2-2 DO
|
||||
STACK$[N]=STACK$[N+2]
|
||||
N=N+1
|
||||
END WHILE
|
||||
NS2=NS2-2
|
||||
L=NS1-1
|
||||
END IF
|
||||
L=L+1
|
||||
END WHILE
|
||||
|
||||
L=NS1
|
||||
WHILE L<=NS2 DO
|
||||
IF STACK$[L]="*" OR STACK$[L]="/" THEN
|
||||
IF L>=NS2 THEN GOTO 100 END IF
|
||||
N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
|
||||
IF STACK$[L]="*" THEN RI#=N1#*N2# ELSE RI#=N1#/N2# END IF
|
||||
STACK$[L-1]=STR$(RI#)
|
||||
N=L
|
||||
WHILE N<=NS2-2 DO
|
||||
STACK$[N]=STACK$[N+2]
|
||||
N=N+1
|
||||
END WHILE
|
||||
NS2=NS2-2
|
||||
L=NS1-1
|
||||
END IF
|
||||
L=L+1
|
||||
END WHILE
|
||||
|
||||
L=NS1
|
||||
WHILE L<=NS2 DO
|
||||
IF STACK$[L]="+" OR STACK$[L]="-" THEN
|
||||
EXIT IF L>=NS2
|
||||
N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
|
||||
IF STACK$[L]="+" THEN RI#=N1#+N2# ELSE RI#=N1#-N2# END IF
|
||||
STACK$[L-1]=STR$(RI#)
|
||||
N=L
|
||||
WHILE N<=NS2-2 DO
|
||||
STACK$[N]=STACK$[N+2]
|
||||
N=N+1
|
||||
END WHILE
|
||||
NS2=NS2-2
|
||||
L=NS1-1
|
||||
END IF
|
||||
L=L+1
|
||||
END WHILE
|
||||
100:
|
||||
IF NOP<2 THEN ! operator priority
|
||||
DB#=VAL(STACK$[NS1])
|
||||
ELSE
|
||||
IF NOP<3 THEN
|
||||
DB#=VAL(STACK$[NS1+2])
|
||||
ELSE
|
||||
DB#=VAL(STACK$[NS1+4])
|
||||
END IF
|
||||
END IF
|
||||
END PROCEDURE
|
||||
|
||||
PROCEDURE SVOLGI_PAR
|
||||
NPA=NPA-1
|
||||
FOR J=NS TO 1 STEP -1 DO
|
||||
EXIT IF STACK$[J]="("
|
||||
END FOR
|
||||
IF J=0 THEN
|
||||
NS1=1 NS2=NS CALC_ARITM
|
||||
NERR=7
|
||||
ELSE
|
||||
FOR R=J TO NS-1 DO
|
||||
STACK$[R]=STACK$[R+1]
|
||||
END FOR
|
||||
NS1=J NS2=NS-1 CALC_ARITM
|
||||
IF NS1=2 THEN NS1=1 STACK$[1]=STACK$[2] END IF
|
||||
NS=NS1
|
||||
COMPATTA_STACK
|
||||
END IF
|
||||
END PROCEDURE
|
||||
|
||||
BEGIN
|
||||
OP_LIST$="+-*/^("
|
||||
NOP=0 NPA=0 NS=1 K$=""
|
||||
STACK$[1]="@" ! init stack
|
||||
|
||||
PRINT(CHR$(12);)
|
||||
INPUT(LINE,EXPRESSION$)
|
||||
|
||||
FOR W=1 TO LEN(EXPRESSION$) DO
|
||||
LOOP
|
||||
CODE=ASC(MID$(EXPRESSION$,W,1))
|
||||
IF (CODE>=48 AND CODE<=57) OR CODE=46 THEN
|
||||
K$=K$+CHR$(CODE)
|
||||
W=W+1 IF W>LEN(EXPRESSION$) THEN GOTO 98 END IF
|
||||
ELSE
|
||||
EXIT IF K$=""
|
||||
IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
|
||||
IF FLAG=0 THEN STACK$[NS]=K$ ELSE STACK$[NS]=STR$(VAL(K$)*FLAG) END IF
|
||||
K$="" FLAG=0
|
||||
EXIT
|
||||
END IF
|
||||
END LOOP
|
||||
IF CODE=43 THEN K$="+" END IF
|
||||
IF CODE=45 THEN K$="-" END IF
|
||||
IF CODE=42 THEN K$="*" END IF
|
||||
IF CODE=47 THEN K$="/" END IF
|
||||
IF CODE=94 THEN K$="^" END IF
|
||||
|
||||
CASE CODE OF
|
||||
43,45,42,47,94->
|
||||
IF MID$(EXPRESSION$,W+1,1)="-" THEN FLAG=-1 W=W+1 END IF
|
||||
IF INSTR(OP_LIST$,STACK$[NS])<>0 THEN
|
||||
NERR=5
|
||||
ELSE
|
||||
NS=NS+1 STACK$[NS]=K$ NOP=NOP+1
|
||||
IF NOP>=2 THEN
|
||||
FOR J=NS TO 1 STEP -1 DO
|
||||
IF STACK$[J]<>"(" THEN
|
||||
CONTINUE FOR
|
||||
END IF
|
||||
IF J<NS-2 THEN
|
||||
EXIT
|
||||
ELSE
|
||||
GOTO 110
|
||||
END IF
|
||||
END FOR
|
||||
NS1=J+1 NS2=NS CALC_ARITM
|
||||
NS=NS2 STACK$[NS]=K$
|
||||
REGISTRO_X#=VAL(STACK$[NS-1])
|
||||
END IF
|
||||
END IF
|
||||
110:
|
||||
END ->
|
||||
|
||||
40->
|
||||
IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
|
||||
STACK$[NS]="(" NPA=NPA+1
|
||||
IF MID$(EXPRESSION$,W+1,1)="-" THEN FLAG=-1 W=W+1 END IF
|
||||
END ->
|
||||
|
||||
41->
|
||||
SVOLGI_PAR
|
||||
IF NERR=7 THEN
|
||||
NERR=0 NOP=0 NPA=0 NS=1
|
||||
ELSE
|
||||
IF NERR=0 OR NERR=1 THEN
|
||||
DB#=VAL(STACK$[NS])
|
||||
REGISTRO_X#=DB#
|
||||
ELSE
|
||||
NOP=0 NPA=0 NS=1
|
||||
END IF
|
||||
END IF
|
||||
END ->
|
||||
|
||||
OTHERWISE
|
||||
NERR=8
|
||||
END CASE
|
||||
K$=""
|
||||
DISEGNA_STACK
|
||||
END FOR
|
||||
|
||||
98:
|
||||
IF K$<>"" THEN
|
||||
IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
|
||||
IF FLAG=0 THEN STACK$[NS]=K$ ELSE STACK$[NS]=STR$(VAL(K$)*FLAG) END IF
|
||||
END IF
|
||||
DISEGNA_STACK
|
||||
IF INSTR(OP_LIST$,STACK$[NS])<>0 THEN
|
||||
NERR=6
|
||||
ELSE
|
||||
WHILE NPA<>0 DO
|
||||
SVOLGI_PAR
|
||||
END WHILE
|
||||
IF NERR<>7 THEN NS1=1 NS2=NS CALC_ARITM END IF
|
||||
END IF
|
||||
NS=1 NOP=0 NPA=0
|
||||
!$RCODE="LOCATE 23,1"
|
||||
IF NERR>0 THEN PRINT("Internal Error #";NERR) ELSE PRINT("Value is ";DB#) END IF
|
||||
END PROGRAM
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
'Arithmetic evaluation
|
||||
'
|
||||
'Create a program which parses and evaluates arithmetic expressions.
|
||||
'
|
||||
'Requirements
|
||||
'
|
||||
' * An abstract-syntax tree (AST) for the expression must be created from parsing the
|
||||
' input.
|
||||
' * The AST must be used in evaluation, also, so the input may not be directly evaluated
|
||||
' (e.g. by calling eval or a similar language feature.)
|
||||
' * The expression will be a string or list of symbols like "(1+3)*7".
|
||||
' * The four symbols + - * / must be supported as binary operators with conventional
|
||||
' precedence rules.
|
||||
' * Precedence-control parentheses must also be supported.
|
||||
'
|
||||
'Standard mathematical precedence should be followed:
|
||||
'
|
||||
' Parentheses
|
||||
' Multiplication/Division (left to right)
|
||||
' Addition/Subtraction (left to right)
|
||||
'
|
||||
' test cases:
|
||||
' 2*-3--4+-0.25 : returns -2.25
|
||||
' 1 + 2 * (3 + (4 * 5 + 6 * 7 * 8) - 9) / 10 : returns 71
|
||||
|
||||
enum
|
||||
false = 0
|
||||
true = -1
|
||||
end enum
|
||||
|
||||
enum Symbol
|
||||
unknown_sym
|
||||
minus_sym
|
||||
plus_sym
|
||||
lparen_sym
|
||||
rparen_sym
|
||||
number_sym
|
||||
mul_sym
|
||||
div_sym
|
||||
unary_minus_sym
|
||||
unary_plus_sym
|
||||
done_sym
|
||||
eof_sym
|
||||
end enum
|
||||
|
||||
type Tree
|
||||
as Tree ptr leftp, rightp
|
||||
op as Symbol
|
||||
value as double
|
||||
end type
|
||||
|
||||
dim shared sym as Symbol
|
||||
dim shared tokenval as double
|
||||
dim shared usr_input as string
|
||||
|
||||
declare function expr(byval p as integer) as Tree ptr
|
||||
|
||||
function isdigit(byval ch as string) as long
|
||||
return ch <> "" and Asc(ch) >= Asc("0") and Asc(ch) <= Asc("9")
|
||||
end function
|
||||
|
||||
sub error_msg(byval msg as string)
|
||||
print msg
|
||||
system
|
||||
end sub
|
||||
|
||||
' tokenize the input string
|
||||
sub getsym()
|
||||
do
|
||||
if usr_input = "" then
|
||||
line input usr_input
|
||||
usr_input += chr(10)
|
||||
endif
|
||||
dim as string ch = mid(usr_input, 1, 1) ' get the next char
|
||||
usr_input = mid(usr_input, 2) ' remove it from input
|
||||
|
||||
sym = unknown_sym
|
||||
select case ch
|
||||
case " ": continue do
|
||||
case chr(10), "": sym = done_sym: return
|
||||
case "+": sym = plus_sym: return
|
||||
case "-": sym = minus_sym: return
|
||||
case "*": sym = mul_sym: return
|
||||
case "/": sym = div_sym: return
|
||||
case "(": sym = lparen_sym: return
|
||||
case ")": sym = rparen_sym: return
|
||||
case else
|
||||
if isdigit(ch) then
|
||||
dim s as string = ""
|
||||
dim dot as integer = 0
|
||||
do
|
||||
s += ch
|
||||
if ch = "." then dot += 1
|
||||
ch = mid(usr_input, 1, 1) ' get the next char
|
||||
usr_input = mid(usr_input, 2) ' remove it from input
|
||||
loop while isdigit(ch) orelse ch = "."
|
||||
if ch = "." or dot > 1 then error_msg("bogus number")
|
||||
usr_input = ch + usr_input ' prepend the char to input
|
||||
tokenval = val(s)
|
||||
sym = number_sym
|
||||
end if
|
||||
return
|
||||
end select
|
||||
loop
|
||||
end sub
|
||||
|
||||
function make_node(byval op as Symbol, byval leftp as Tree ptr, byval rightp as Tree ptr) as Tree ptr
|
||||
dim t as Tree ptr
|
||||
|
||||
t = callocate(len(Tree))
|
||||
t->op = op
|
||||
t->leftp = leftp
|
||||
t->rightp = rightp
|
||||
return t
|
||||
end function
|
||||
|
||||
function is_binary(byval op as Symbol) as integer
|
||||
select case op
|
||||
case mul_sym, div_sym, plus_sym, minus_sym: return true
|
||||
case else: return false
|
||||
end select
|
||||
end function
|
||||
|
||||
function prec(byval op as Symbol) as integer
|
||||
select case op
|
||||
case unary_minus_sym, unary_plus_sym: return 100
|
||||
case mul_sym, div_sym: return 90
|
||||
case plus_sym, minus_sym: return 80
|
||||
case else: return 0
|
||||
end select
|
||||
end function
|
||||
|
||||
function primary as Tree ptr
|
||||
dim t as Tree ptr = 0
|
||||
|
||||
select case sym
|
||||
case minus_sym, plus_sym
|
||||
dim op as Symbol = sym
|
||||
getsym()
|
||||
t = expr(prec(unary_minus_sym))
|
||||
if op = minus_sym then return make_node(unary_minus_sym, t, 0)
|
||||
if op = plus_sym then return make_node(unary_plus_sym, t, 0)
|
||||
case lparen_sym
|
||||
getsym()
|
||||
t = expr(0)
|
||||
if sym <> rparen_sym then error_msg("expecting rparen")
|
||||
getsym()
|
||||
return t
|
||||
case number_sym
|
||||
t = make_node(sym, 0, 0)
|
||||
t->value = tokenval
|
||||
getsym()
|
||||
return t
|
||||
case else: error_msg("expecting a primary")
|
||||
end select
|
||||
end function
|
||||
|
||||
function expr(byval p as integer) as Tree ptr
|
||||
dim t as Tree ptr = primary()
|
||||
|
||||
while is_binary(sym) andalso prec(sym) >= p
|
||||
dim t1 as Tree ptr
|
||||
dim op as Symbol = sym
|
||||
getsym()
|
||||
t1 = expr(prec(op) + 1)
|
||||
t = make_node(op, t, t1)
|
||||
wend
|
||||
return t
|
||||
end function
|
||||
|
||||
function eval(byval t as Tree ptr) as double
|
||||
if t <> 0 then
|
||||
select case t->op
|
||||
case minus_sym: return eval(t->leftp) - eval(t->rightp)
|
||||
case plus_sym: return eval(t->leftp) + eval(t->rightp)
|
||||
case mul_sym: return eval(t->leftp) * eval(t->rightp)
|
||||
case div_sym: return eval(t->leftp) / eval(t->rightp)
|
||||
case unary_minus_sym: return -eval(t->leftp)
|
||||
case unary_plus_sym: return eval(t->leftp)
|
||||
case number_sym: return t->value
|
||||
case else: error_msg("unexpected tree node")
|
||||
end select
|
||||
end if
|
||||
return 0
|
||||
end function
|
||||
|
||||
do
|
||||
getsym()
|
||||
if sym = eof_sym then exit do
|
||||
if sym = done_sym then continue do
|
||||
dim t as Tree ptr = expr(0)
|
||||
print"> "; eval(t)
|
||||
if sym = eof_sym then exit do
|
||||
if sym <> done_sym then error_msg("unexpected input")
|
||||
loop
|
||||
218
Task/Arithmetic-evaluation/Phix/arithmetic-evaluation.phix
Normal file
218
Task/Arithmetic-evaluation/Phix/arithmetic-evaluation.phix
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
sequence opstack = {} -- atom elements are literals,
|
||||
-- sequence elements are subexpressions
|
||||
-- on completion length(opstack) should be 1
|
||||
object token
|
||||
|
||||
constant op_p_p = 0 -- 1: expressions stored as op,p1,p2
|
||||
-- p_op_p -- 0: expressions stored as p1,op,p2
|
||||
-- p_p_op -- -1: expressions stored as p1,p2,op
|
||||
|
||||
object op = 0 -- 0 if none, else "+", "-", "*", "/", "^", "%", or "u-"
|
||||
|
||||
string s -- the expression being parsed
|
||||
integer ch
|
||||
integer sidx
|
||||
|
||||
procedure err(string msg)
|
||||
printf(1,"%s\n%s^ %s\n\nPressEnter...",{s,repeat(' ',sidx-1),msg})
|
||||
{} = wait_key()
|
||||
abort(0)
|
||||
end procedure
|
||||
|
||||
procedure nxtch(object msg="eof")
|
||||
sidx += 1
|
||||
if sidx>length(s) then
|
||||
if string(msg) then err(msg) end if
|
||||
ch = -1
|
||||
else
|
||||
ch = s[sidx]
|
||||
end if
|
||||
end procedure
|
||||
|
||||
procedure skipspaces()
|
||||
while find(ch," \t\r\n")!=0 do nxtch(0) end while
|
||||
end procedure
|
||||
|
||||
procedure get_token()
|
||||
atom n, fraction
|
||||
integer dec
|
||||
skipspaces()
|
||||
if ch=-1 then token = "eof" return end if
|
||||
if ch>='0' and ch<='9' then
|
||||
n = ch-'0'
|
||||
while 1 do
|
||||
nxtch(0)
|
||||
if ch<'0' or ch>'9' then exit end if
|
||||
n = n*10+ch-'0'
|
||||
end while
|
||||
if ch='.' then
|
||||
dec = 1
|
||||
fraction = 0
|
||||
while 1 do
|
||||
nxtch(0)
|
||||
if ch<'0' or ch>'9' then exit end if
|
||||
fraction = fraction*10 + ch-'0'
|
||||
dec *= 10
|
||||
end while
|
||||
n += fraction/dec
|
||||
end if
|
||||
-- if find(ch,"eE") then -- you get the idea
|
||||
-- end if
|
||||
token = n
|
||||
return
|
||||
end if
|
||||
if find(ch,"+-/*()^%")=0 then err("syntax error") end if
|
||||
token = s[sidx..sidx]
|
||||
nxtch(0)
|
||||
return
|
||||
end procedure
|
||||
|
||||
procedure Match(string t)
|
||||
if token!=t then err(t&" expected") end if
|
||||
get_token()
|
||||
end procedure
|
||||
|
||||
procedure PopFactor()
|
||||
object p2 = opstack[$]
|
||||
if op="u-" then
|
||||
if op_p_p=1 then -- op_p_p
|
||||
opstack[$] = {op,0,p2}
|
||||
elsif op_p_p=0 then -- p_op_p
|
||||
opstack[$] = {0,op,p2}
|
||||
else -- -1 -- p_p_op
|
||||
opstack[$] = {0,p2,op}
|
||||
end if
|
||||
else
|
||||
opstack = opstack[1..$-1]
|
||||
if op_p_p=1 then -- op_p_p
|
||||
opstack[$] = {op,opstack[$],p2}
|
||||
elsif op_p_p=0 then -- p_op_p
|
||||
opstack[$] = {opstack[$],op,p2}
|
||||
else -- -1 -- p_p_op
|
||||
opstack[$] = {opstack[$],p2,op}
|
||||
end if
|
||||
end if
|
||||
op = 0
|
||||
end procedure
|
||||
|
||||
procedure PushFactor(atom t)
|
||||
if op!=0 then PopFactor() end if
|
||||
opstack = append(opstack,t)
|
||||
end procedure
|
||||
|
||||
procedure PushOp(string t)
|
||||
if op!=0 then PopFactor() end if
|
||||
op = t
|
||||
end procedure
|
||||
|
||||
procedure Factor()
|
||||
if atom(token) then
|
||||
PushFactor(token)
|
||||
if ch!=-1 then
|
||||
get_token()
|
||||
end if
|
||||
elsif token="-" then
|
||||
get_token()
|
||||
-- Factor()
|
||||
Expr(3) -- makes "-3^2" yield -9 (ie -(3^2)) not 9 (ie (-3)^2).
|
||||
if op!=0 then PopFactor() end if
|
||||
if integer(opstack[$]) then
|
||||
opstack[$] = -opstack[$]
|
||||
else
|
||||
PushOp("u-")
|
||||
end if
|
||||
elsif token="(" then
|
||||
get_token()
|
||||
Expr(0)
|
||||
Match(")")
|
||||
elsif token="+" then -- (ignore)
|
||||
nxtch()
|
||||
Factor()
|
||||
else
|
||||
err("syntax error")
|
||||
end if
|
||||
end procedure
|
||||
|
||||
constant {operators,
|
||||
precedence,
|
||||
associativity} = columnize({{"^",3,0},
|
||||
{"%",2,1},
|
||||
{"*",2,1},
|
||||
{"/",2,1},
|
||||
{"+",1,1},
|
||||
{"-",1,1},
|
||||
$})
|
||||
|
||||
procedure Expr(integer p)
|
||||
--
|
||||
-- Parse an expression, using precedence climbing.
|
||||
--
|
||||
-- p is the precedence level we should parse to, eg/ie
|
||||
-- 4: Factor only (may as well just call Factor)
|
||||
-- 3: "" and ^
|
||||
-- 2: "" and *,/,%
|
||||
-- 1: "" and +,-
|
||||
-- 0: full expression (effectively the same as 1)
|
||||
-- obviously, parentheses override any setting of p.
|
||||
--
|
||||
integer k, thisp
|
||||
Factor()
|
||||
while 1 do
|
||||
k = find(token,operators) -- *,/,+,-
|
||||
if k=0 then exit end if
|
||||
thisp = precedence[k]
|
||||
if thisp<p then exit end if
|
||||
get_token()
|
||||
Expr(thisp+associativity[k])
|
||||
PushOp(operators[k])
|
||||
end while
|
||||
end procedure
|
||||
|
||||
function eval(object s)
|
||||
object lhs, rhs
|
||||
string op
|
||||
if atom(s) then
|
||||
return s
|
||||
end if
|
||||
if op_p_p=1 then -- op_p_p
|
||||
{op,lhs,rhs} = s
|
||||
elsif op_p_p=0 then -- p_op_p
|
||||
{lhs,op,rhs} = s
|
||||
else -- -1 -- p_p_op
|
||||
{lhs,rhs,op} = s
|
||||
end if
|
||||
if sequence(lhs) then lhs = eval(lhs) end if
|
||||
if sequence(rhs) then rhs = eval(rhs) end if
|
||||
if op="+" then
|
||||
return lhs+rhs
|
||||
elsif op="-" then
|
||||
return lhs-rhs
|
||||
elsif op="*" then
|
||||
return lhs*rhs
|
||||
elsif op="/" then
|
||||
return lhs/rhs
|
||||
elsif op="^" then
|
||||
return power(lhs,rhs)
|
||||
elsif op="%" then
|
||||
return remainder(lhs,rhs)
|
||||
elsif op="u-" then
|
||||
return -rhs
|
||||
else
|
||||
?9/0
|
||||
end if
|
||||
end function
|
||||
|
||||
s = "3+4+5+6*7/1*5^2^3"
|
||||
sidx = 0
|
||||
nxtch()
|
||||
get_token()
|
||||
Expr(0)
|
||||
if op!=0 then PopFactor() end if
|
||||
if length(opstack)!=1 then err("some error") end if
|
||||
puts(1,"AST (flat): ")
|
||||
?opstack[1]
|
||||
puts(1,"AST (tree):\n")
|
||||
ppEx(opstack[1],{pp_Nest,6})
|
||||
puts(1,"result: ")
|
||||
?eval(opstack[1])
|
||||
{} = wait_key()
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
func evalArithmeticExp(s) {
|
||||
|
||||
func evalExp(s) {
|
||||
|
||||
func operate(s, op) {
|
||||
s.split(op).map{|c| c.to_num }.reduce(op);
|
||||
}
|
||||
|
||||
func add(s) {
|
||||
operate(s.sub(/^\+/,'').sub(/\++/,'+'), '+');
|
||||
}
|
||||
|
||||
func subtract(s) {
|
||||
s.gsub!(/(\+-|-\+)/,'-');
|
||||
|
||||
if (s ~~ /--/) {
|
||||
return(add(s.sub(/--/,'+')));
|
||||
}
|
||||
|
||||
var b = s.split('-');
|
||||
b.len == 3 ? (-1*b[1].to_num - b[2].to_num)
|
||||
: operate(s, '-');
|
||||
}
|
||||
|
||||
s.gsub!(/[()]/,'').gsub!(/-\+/, '-');
|
||||
|
||||
var reM = /\*/;
|
||||
var reMD = %r"(\d+\.?\d*\s*[*/]\s*[+-]?\d+\.?\d*)";
|
||||
|
||||
var reA = /\d\+/;
|
||||
var reAS = /(-?\d+\.?\d*\s*[+-]\s*[+-]?\d+\.?\d*)/;
|
||||
|
||||
while (var match = reMD.match(s)) {
|
||||
match[0] ~~ reM
|
||||
? s.sub!(reMD, operate(match[0], '*').to_s)
|
||||
: s.sub!(reMD, operate(match[0], '/').to_s);
|
||||
}
|
||||
|
||||
while (var match = reAS.match(s)) {
|
||||
match[0] ~~ reA
|
||||
? s.sub!(reAS, add(match[0]).to_s)
|
||||
: s.sub!(reAS, subtract(match[0]).to_s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
var rePara = /(\([^\(\)]*\))/;
|
||||
s.split!.join!('').sub!(/^\+/,'');
|
||||
|
||||
while (var match = s.match(rePara)) {
|
||||
s.sub!(rePara, evalExp(match[0]));
|
||||
}
|
||||
|
||||
return evalExp(s).to_num;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
for expr,res in [
|
||||
['2+3' => 5],
|
||||
['-4-3' => -7],
|
||||
['-+2+3/4' => -1.25],
|
||||
['2*3-4' => 2],
|
||||
['2*(3+4)+2/4' => 2/4 + 14],
|
||||
['2*-3--4+-0.25' => -2.25],
|
||||
['2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10' => 7000],
|
||||
] {
|
||||
var num = evalArithmeticExp(expr);
|
||||
assert_eq(num, res);
|
||||
"%-45s == %10g\n".printf(expr, num);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue