zhangsongcui

Arithmetic formula with D

Mar 27th, 2012
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 2.75 KB | None | 0 0
  1. import std.stdio;
  2. import std.process;
  3. import std.container;
  4. import std.typecons;
  5. import std.conv;
  6. import std.array;
  7. import std.string;
  8.  
  9. alias double function(double, double) OpFn;
  10. alias Tuple!(uint, OpFn) Binder;
  11.  
  12. double Calculate(string Expression, in Binder[immutable char] Operators) {
  13.     alias Tuple!(double, char) Pair;
  14.     Pair[] stack;
  15.     stack.assumeSafeAppend();
  16.     double Result = 0, newNum;
  17.     char oldOperator = '\0', newOperator;
  18.  
  19.     while (true) {
  20.         try {
  21.             newNum = parse!double(Expression);
  22.         } catch (ConvException e) {
  23.             if (Expression.front == '(') {
  24.                 stack ~= Pair(Result, -oldOperator);
  25.                 oldOperator = '\0';
  26.                 Expression = Expression[1 .. Expression.length];
  27.                 continue;
  28.             } else {
  29.                 throw new Exception("Invaild charactor");
  30.             }
  31.         }
  32. NEXT:
  33.         if (Expression.empty)
  34.             break;
  35.         newOperator = parse!char(Expression);
  36.         if (!(newOperator in Operators)) {
  37.             if (newOperator == ')') {
  38.                 Result = Operators[oldOperator][1](Result, newNum);
  39.                 while (true) {
  40.                     if (stack.empty)
  41.                         throw new Exception("Unexpected ')'");
  42.                     if (stack.back[1] > 0) {
  43.                         Result = Operators[stack.back[1]][1](stack.back[0], Result);
  44.                         stack.popBack();
  45.                     } else {
  46.                         oldOperator = -stack.back[1];
  47.                         newNum = Result;
  48.                         Result = stack.back[0];
  49.                         stack.popBack();
  50.                         goto NEXT;
  51.                     }
  52.                 }
  53.                 Expression = Expression[1 .. Expression.length];
  54.             } else {
  55.                 throw new Exception("Invaild operator");
  56.             }
  57.         }
  58.         if (Operators[newOperator][0] > Operators[oldOperator][0]) {
  59.             stack ~= tuple(Result, oldOperator);
  60.             Result = newNum;
  61.         } else {
  62.             Result = Operators[oldOperator][1](Result, newNum);
  63.             if (Operators[newOperator][0] < Operators[oldOperator][0]) {
  64.                 while (!stack.empty &&  stack.back[1] > 0 &&
  65.                         Operators[newOperator][0] < Operators[stack.back[1]][0]) {
  66.                     Result = Operators[stack.back[1]][1](stack.back[0], Result);
  67.                     stack.popBack();
  68.                 }
  69.             }
  70.         }
  71.         oldOperator = newOperator;
  72.     }
  73.     Result = Operators[oldOperator][1](Result, newNum);
  74.     while (!stack.empty) {
  75.         if (stack.back[1] <= 0)
  76.             throw new Exception("No matching ')'");
  77.         Result = Operators[stack.back[1]][1](stack.back[0], Result);
  78.         stack.popBack();
  79.     }
  80.     return Result;
  81. }
  82.  
  83. void main(string[] argv) {
  84.     Binder[immutable char] Operators;
  85.     Operators['+'] = Binder(1u, (double x, double y) => x + y);
  86.     Operators['-'] = Binder(1u, (double x, double y) => x - y);
  87.     Operators['*'] = Binder(2u, (double x, double y) => x * y);
  88.     Operators['/'] = Binder(2u, (double x, double y) => x / y);
  89.     Operators['\0'] = Binder(uint.max, (double x, double y) => y);
  90.     string s = stdin.readln().chomp;
  91.     try {
  92.         stdout.writeln(Calculate(s, Operators));
  93.     } catch (Exception e) {
  94.         stderr.writeln(e.msg);
  95.     }
  96.     system("PAUSE");
  97. }
Advertisement
Add Comment
Please, Sign In to add comment