Arithmetic evaluation: Difference between revisions

Content added Content deleted
(→‎{{header|D}}: Just because it needs attention doesn't mean it's listening in.)
m (→‎{{header|D}}: removed bug code and set incorrect tag, for no AST build)
Line 327: Line 327:


=={{header|D}}==
=={{header|D}}==
{{incorrect}}

{{needs-review}}

module test;
import std.stdio;
int calculate(string expr)
{
string take(int count)
{
auto res = expr[0 .. count];
expr = expr[count .. $];
return res;
}
string peek(int count)
{
if (expr.length < count) count = expr.length;
return expr [0 .. count];
}
int delegate(int level) descent;
// grab the next number from the input expression
int getNumber()
{
int res;
// if our "number" is a parantheses-wrapped expression, evaluate it
if (peek(1) == "(") { take(1); return descent(0); }
while (expr.length)
{
auto next = peek(1)[0];
// if the next character is a digit ...
if (next >= '0' && next <= '9')
{
res = res * 10 + (next-'0');
take(1);
} else return res;
}
return res;
}
// descent evaluates a level-l expression (1: multiplication and division, 0: also addition and subtraction)
descent = (int l) {
auto num = getNumber; // get the first number of our expression
while (expr.length)
{
auto op = take(1)[0];
if (op == ')') return num; // expression end
if (op == '*') num *= getNumber;
if (op == '/') num /= getNumber;
if (l == 1) return num;
if (op == '+') num += descent(1);
if (op == '-') num -= descent(1);
}
return num;
};
return descent(0);
}
void main()
{
writefln(calculate("(3+50)*7-9"), ", ", (3+50)*7-9);
}

{{works with|DMD|2.007}}
I'm a D newbie, hope this D code reveals some D unique features.
<pre>module eval;
<pre>module eval;
import std.stdio;
import std.stdio;
Line 398: Line 336:
// simple stack template
// simple stack template
void push(U)(inout U[] stk, U top) {
void push(U)(inout U[] stk, U top) {
stk = stk ~ top ;
stk = stk ~ top ;
}
}


U pop(U)(inout U[] stk, bool peektop = false) {
U pop(U)(inout U[] stk, bool peektop = false) {
U top ;
U top ;
if (stk.length > 0) {
if (stk.length > 0) {
top = stk[$ - 1] ;
top = stk[$ - 1] ;
if (!peektop)
if (!peektop)
stk.length = stk.length - 1 ;
stk.length = stk.length - 1 ;
} else
} else
throw new Exception("Invalid Expression") ; // or Empty Stack
throw new Exception("Invalid Expression") ; // or Empty Stack
return top ;
return top ;
}
}


// evalutor function
// evalutor function
T eval(T = long)(string expression) {
T eval(T = long)(string expression) {
string[] opr ; // operator stack
string[] opr ; // operator stack
T[] num ; // number stack
T[] num ; // number stack


uint tokensum = 0 ;
uint tokensum = 0 ;
int[char[]] prece = ["=":0, "(":1, ")":1,"+":2,"-":2,"*":3,"/":3] ;
int[char[]] prece = ["=":0, "(":1, ")":1,"+":2,"-":2,"*":3,"/":3] ;
void doMath(string op) { // operator executor
void doMath(string op) { // operator executor
T valR = num.pop() ;
T valR = num.pop() ;
T valL = num.pop() ;
T valL = num.pop() ;
switch (op) {
switch (op) {
case "+": return num.push(valL + valR) ;
case "+": return num.push(valL + valR) ;
case "-": return num.push(valL - valR) ;
case "-": return num.push(valL - valR) ;
case "*": return num.push(valL * valR) ;
case "*": return num.push(valL * valR) ;
case "/": return num.push(valL / valR) ;
case "/": return num.push(valL / valR) ;
}
}
}
}
opr.push("=") ;
opr.push("=") ;


foreach(m ; RegExp(r"[+*-/()]|\d+").search(expression)) {
foreach(m ; RegExp(r"[+*-/()]|\d+").search(expression)) {
string token = m.match(0) ;
string token = m.match(0) ;
tokensum += token.length ;
tokensum += token.length ;
if (token[0] >= '0' && token[0] <= '9')
if (token[0] >= '0' && token[0] <= '9')
num.push(to!(T)(token)) ;
num.push(to!(T)(token)) ;
else if (token == "(")
else if (token == "(")
opr.push(token) ;
opr.push(token) ;
else if (token == ")") {
else if (token == ")") {
while(opr.pop(true) != "(")
while(opr.pop(true) != "(")
doMath(opr.pop()) ;
doMath(opr.pop()) ;
opr.pop() ;
opr.pop() ;
} else {
} else {
while (prece[opr.pop(true)] >= prece[token])
while (prece[opr.pop(true)] >= prece[token])
doMath(opr.pop()) ;
doMath(opr.pop()) ;
opr.push(token) ;
opr.push(token) ;
}
}
}
}


if (tokensum + count(expression, " ") != expression.length)
if (tokensum + count(expression, " ") != expression.length)
throw new Exception("Invalid Tokens") ;
throw new Exception("Invalid Tokens") ;


while (opr.length > 1)
while (opr.length > 1)
doMath(opr.pop()) ;
doMath(opr.pop()) ;
if (num.length != 1)
if (num.length != 1)
throw new Exception("Invalid Expression") ;
throw new Exception("Invalid Expression") ;
return num.pop() ;
return num.pop() ;
}
}


void main(string[] args) {
void main(string[] args) {
foreach(xpr ; std.string.split(join(args[1..$], " "),",")) {
foreach(xpr ; std.string.split(join(args[1..$], " "),",")) {
try{
try{
writefln("long: %s = %d", xpr, eval(xpr)) ;
writefln("long: %s = %d", xpr, eval(xpr)) ;
writefln("int : %s = %d", xpr, eval!(int)(xpr)) ;
writefln("int : %s = %d", xpr, eval!(int)(xpr)) ;
}
}
catch (Exception e) {
catch (Exception e) {
writefln("%s : %s", e.msg, xpr) ;
writefln("%s : %s", e.msg, xpr) ;
}
}
}
}
}</pre>
}

/*** sample output
D:\00MY\dmd>dmd eval
h:\dmd\bin\..\..\dm\bin\link.exe eval,,,user32+kernel32/noi;

D:\00MY\dmd>eval 1 + * 2, 4*5-3*2, a1 + b,4*(5-3)*2, 128*256*256*256+1
Invalid Expression : 1 + * 2
long: 4*5-3*2 = 14
int : 4*5-3*2 = 14
Invalid Tokens : a1 + b
long: 4*(5-3)*2 = 16
int : 4*(5-3)*2 = 16
long: 128*256*256*256+1 = 2147483649
int : 128*256*256*256+1 = -2147483647
***/</pre>


=={{header|Haskell}}==
=={{header|Haskell}}==