Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
101
Task/Arithmetic-evaluation/Icon/arithmetic-evaluation.icon
Normal file
101
Task/Arithmetic-evaluation/Icon/arithmetic-evaluation.icon
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
procedure main() #: simple arithmetical parser / evaluator
|
||||
write("Usage: Input expression = Abstract Syntax Tree = Value, ^Z to end.")
|
||||
repeat {
|
||||
writes("Input expression : ")
|
||||
if not writes(line := read()) then break
|
||||
if map(line) ? { (x := E()) & pos(0) } then
|
||||
write(" = ", showAST(x), " = ", evalAST(x))
|
||||
else
|
||||
write(" rejected")
|
||||
}
|
||||
end
|
||||
|
||||
procedure evalAST(X) #: return the evaluated AST
|
||||
local x
|
||||
|
||||
if type(X) == "list" then {
|
||||
x := evalAST(get(X))
|
||||
while x := get(X)(x, evalAST(get(X) | stop("Malformed AST.")))
|
||||
}
|
||||
return \x | X
|
||||
end
|
||||
|
||||
procedure showAST(X) #: return a string representing the AST
|
||||
local x,s
|
||||
|
||||
s := ""
|
||||
every x := !X do
|
||||
s ||:= if type(x) == "list" then "(" || showAST(x) || ")" else x
|
||||
return s
|
||||
end
|
||||
|
||||
########
|
||||
# When you're writing a big parser, a few utility recognisers are very useful
|
||||
#
|
||||
procedure ws() # skip optional whitespace
|
||||
suspend tab(many(' \t')) | ""
|
||||
end
|
||||
|
||||
procedure digits()
|
||||
suspend tab(many(&digits))
|
||||
end
|
||||
|
||||
procedure radixNum(r) # r sets the radix
|
||||
static chars
|
||||
initial chars := &digits || &lcase
|
||||
suspend tab(many(chars[1 +: r]))
|
||||
end
|
||||
########
|
||||
|
||||
global token
|
||||
record HansonsDevice(precedence,associativity)
|
||||
|
||||
procedure opinfo()
|
||||
static O
|
||||
initial {
|
||||
O := HansonsDevice([], table(&null)) # parsing table
|
||||
put(O.precedence, ["+", "-"], ["*", "/", "%"], ["^"]) # Lowest to Highest precedence
|
||||
every O.associativity[!!O.precedence] := 1 # default to 1 for LEFT associativity
|
||||
O.associativity["^"] := 0 # RIGHT associativity
|
||||
}
|
||||
return O
|
||||
end
|
||||
|
||||
procedure E(k) #: Expression
|
||||
local lex, pL
|
||||
static opT
|
||||
initial opT := opinfo()
|
||||
|
||||
/k := 1
|
||||
lex := []
|
||||
if not (pL := opT.precedence[k]) then # this op at this level?
|
||||
put(lex, F())
|
||||
else {
|
||||
put(lex, E(k + 1))
|
||||
while ws() & put(lex, token := =!pL) do
|
||||
put(lex, E(k + opT.associativity[token]))
|
||||
}
|
||||
suspend if *lex = 1 then lex[1] else lex # strip useless []
|
||||
end
|
||||
|
||||
procedure F() #: Factor
|
||||
suspend ws() & ( # skip optional whitespace, and ...
|
||||
(="+" & F()) | # unary + and a Factor, or ...
|
||||
(="-" || V()) | # unary - and a Value, or ...
|
||||
(="-" & [-1, "*", F()]) | # unary - and a Factor, or ...
|
||||
2(="(", E(), ws(), =")") | # parenthesized subexpression, or ...
|
||||
V() # just a value
|
||||
)
|
||||
end
|
||||
|
||||
procedure V() #: Value
|
||||
local r
|
||||
suspend ws() & numeric( # skip optional whitespace, and ...
|
||||
=(r := 1 to 36) || ="r" || radixNum(r) | # N-based number, or ...
|
||||
digits() || (="." || digits() | "") || exponent() # plain number with optional fraction
|
||||
)
|
||||
end
|
||||
|
||||
procedure exponent()
|
||||
suspend tab(any('eE')) || =("+" | "-" | "") || digits() | ""
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue