Anonymous user
Arithmetic evaluation: Difference between revisions
→Icon and Unicon
m (→{{header|Ruby}}: slight rewording of explanation.) |
|||
Line 957:
* handles left and right associativity and different precedences,
* accepts integers, reals, and radix constants (e.g. 3r10 is 3 in base 3), but not E notation
* accepts the Icon operators + - * / % (remainder) and ^ (exponentiation) and unary operators + and -
* string invocation is used to evaluate binary operators hence other Icon binary operators (including handle multiple character ones) can be easily added
* uses Icon style type coercion on operands
* represents the AST is a nested list eliminating unneeded parenthesis.
==={{header|Icon}}===
<lang Icon>procedure main() #: simple arithmetical parser / evaluator
write("Usage: Input expression = Abstract Syntax Tree = Value, ^Z to end.")▼
repeat {▼
▲write("Usage: Input expression = Abstract Syntax Tree = Value, ^Z to end.")
writes("Input expression : ")
▲repeat {
if not writes(
else
}
end
procedure evalAST(X) #: return the evaluated AST
local x
if type(X) == "list" then {
Line 986 ⟶ 985:
procedure showAST(X) #: return a string representing the AST
local x,s
s := ""
Line 993 ⟶ 992:
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
Line 998 ⟶ 1,015:
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
Line 1,019 ⟶ 1,036:
else {
put( lex, E(k+1) )
while ws() & put( lex, token := =!pL ) do
put( lex, E(k+opT.associativity[token]) )
}
Line 1,026 ⟶ 1,043:
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() & ( # skip optional whitespace, and ...
( =(r := 1 to 36) || ="r" || radixNum(r) ) | # N-based number, or ...
(digits() || ((="." || digits() ) | "")) # plain number with optional fraction
)
end</lang>
|