Diff of /experimental/trunk/graphing-calc/mathml.cc [r12394] .. [r12395] Maximize Restore

  Switch to side-by-side view

--- a/experimental/trunk/graphing-calc/mathml.cc
+++ b/experimental/trunk/graphing-calc/mathml.cc
@@ -35,6 +35,12 @@
     return xmlNewChild(node, ns, BAD_CAST "mi", BAD_CAST name);
 }
 
+xmlNodePtr Doc::add_number(xmlNodePtr node, int d) {
+    std::ostringstream s;
+    s << d;
+    return xmlNewChild(node, ns, BAD_CAST "mn", BAD_CAST s.str().c_str());
+}
+
 xmlNodePtr Doc::add_number(xmlNodePtr node, double d) {
     std::ostringstream s;
     s << d;
@@ -80,6 +86,10 @@
     return xmlNewChild(node, ns, BAD_CAST "mroot", NULL);
 }
 
+xmlNodePtr Doc::add_parenthesis(xmlNodePtr node) {
+    return add_row(xmlNewChild(node, ns, BAD_CAST "mfenced", NULL));
+}
+
 xmlNodePtr Doc::add_subscript(xmlNodePtr node) {
     return xmlNewChild(node, ns, BAD_CAST "msub", NULL);
 }
@@ -103,7 +113,7 @@
     else {
         add_identifier(n, name);
     }
-
+    add_operator(n, "&ApplyFunction;");
     return xmlNewChild(n, ns, BAD_CAST "mfenced", NULL);
 }
 
@@ -118,6 +128,55 @@
 }
 
 static void mathml_populate(Doc* d, xmlNodePtr n, Function f);
+
+//1     addition, subtraction
+//2     multiplication, negation
+//3     division
+//4     powers
+//5     functions, literals, variables
+static int get_precedence(Function f) {
+    if(f.f) {
+        switch(f.f->type()) {
+        case APPLY:
+            return get_precedence(get_operator(f));
+        case FLOAT:
+        case AFFINE:
+        case NAME:
+            return 5;
+        case UNARY_BUILTIN:
+            if(static_cast<UnaryBuiltin const *>(f.f)->function() == UnaryBuiltin::NEGATE)
+                return 2;
+            else
+                return 5;
+        case BINARY_BUILTIN: {
+            switch (static_cast<BinaryBuiltin const *>(f.f)->function()) {
+            case BinaryBuiltin::ADD:
+                return 1;
+            case BinaryBuiltin::SUB:
+                return 1;
+            case BinaryBuiltin::MUL:
+                return 2;
+            case BinaryBuiltin::DIV:
+                return 3;
+            case BinaryBuiltin::POW:
+                return 4;
+            case BinaryBuiltin::HYPOT:
+                return 5;
+            case BinaryBuiltin::ATAN2:
+                return 5;
+            }
+        }
+        }
+    }
+    return 0;
+}
+
+//Handles mrow, parenthesis
+static void add_operand(Doc* d, xmlNodePtr n, Function parent, Function f) {
+    if(get_precedence(parent) > get_precedence(f))
+        n = d->add_parenthesis(n);
+    mathml_populate(d, d->add_row(n), f);
+}
 
 static void handle_apply(Doc* d, xmlNodePtr n, Function f) {
     Apply const *apply = static_cast<Apply const *>(f.f);
@@ -139,7 +198,7 @@
             }
 
             while(!functions.empty()) {
-                mathml_populate(d, n, functions.top());
+                mathml_populate(d, d->add_row(n), functions.top());
                 functions.pop();
             }
 
@@ -163,8 +222,8 @@
             case UnaryBuiltin::ASIN: no = d->add_function(n, "sin", true); break;       //True makes it inverse notation
             case UnaryBuiltin::ACOS: no = d->add_function(n, "cos", true); break;
             case UnaryBuiltin::ATAN: no = d->add_function(n, "tan", true); break;
-            //case UnaryBuiltin::GAMMA: std::cout << "#gamma"; break;
-            //case UnaryBuiltin::LNGAMMA: std::cout << "#lngamma"; break;
+            case UnaryBuiltin::GAMMA: no = d->add_function(n, "&Gamma;"); break;
+            case UnaryBuiltin::LNGAMMA: d->add_identifier(n, "ln"); no = d->add_function(n, "&Gamma;"); break;
             //case UnaryBuiltin::ZETA: std::cout << "#zeta"; break;
             case UnaryBuiltin::NEGATE: no = d->add_operator(n, "-", true); break;       //True makes it prefix notation
             //case UnaryBuiltin::CENTER: std::cout << "#center"; break;
@@ -173,7 +232,7 @@
             //default: std::cout << "#unary:" << (int)builtin->function();
             }
 
-            mathml_populate(d, d->add_row(n), apply->argument());
+            add_operand(d, no, f, apply->argument());
             break;
         }
         case BINARY_BUILTIN: {
@@ -188,53 +247,53 @@
 
             switch (bop->function()) {
             case BinaryBuiltin::ADD: {
-                mathml_populate(d, d->add_row(r), o1);
+                add_operand(d, r, op, o1);
                 d->add_operator(r, "+");
-                mathml_populate(d, d->add_row(r), o2);
+                add_operand(d, r, op, o2);
                 break;
             }
             case BinaryBuiltin::SUB: {
-                mathml_populate(d, d->add_row(r), o1);
+                add_operand(d, r, op, o1);
                 d->add_operator(r, "-"); 
-                mathml_populate(d, d->add_row(r), o2);
+                add_operand(d, r, op, o2);
                 break;
             }
             case BinaryBuiltin::MUL:
             {
                 //TODO: intelligent juxtaposition multiply
-                mathml_populate(d, d->add_row(r), o1);
+                add_operand(d, r, op, o1);
                 d->add_operator(r, "*"); 
-                mathml_populate(d, d->add_row(r), o2);
+                add_operand(d, r, op, o2);
                 break;
             }
             case BinaryBuiltin::DIV: {
                 n = d->add_fraction(r);
-                mathml_populate(d, d->add_row(n), o1);
-                mathml_populate(d, d->add_row(n), o2);
+                add_operand(d, n, op, o1);
+                add_operand(d, n, op, o2);
                 break;
             }
             case BinaryBuiltin::POW: {
                 n = d->add_superscript(r);
-                mathml_populate(d, d->add_row(n), o1);
-                mathml_populate(d, d->add_row(n), o2);
+                add_operand(d, n, op, o1);
+                add_operand(d, n, op, o2);
                 break;
             }
             case BinaryBuiltin::HYPOT: {
                 n = d->add_sqrt(r);
                   xmlNodePtr p = d->add_superscript(n);
-                    mathml_populate(d, d->add_row(p), o1);
+                    add_operand(d, p, op, o1);
                     d->add_number(p, 2);
                   d->add_operator(n, "+");
                   p = d->add_superscript(n);
-                    mathml_populate(d, d->add_row(p), o2);
+                    add_operand(d, p, op, o2);
                     d->add_number(p, 2);
                 break;
             }
             case BinaryBuiltin::ATAN2: {
                 n = d->add_function(r, "tan", true);
                 n = d->add_fraction(n);
-                mathml_populate(d, d->add_row(n), o1);
-                mathml_populate(d, d->add_row(n), o2);
+                add_operand(d, n, op, o1);
+                add_operand(d, n, op, o2);
                 break;
             }
             //case BinaryBuiltin::INTERVAL: std::cout << "#interval"; break;
@@ -242,6 +301,11 @@
             }
             break;
           }
+        default:
+            //TODO: Better error stuff
+            std::cout << "Invalid eval tree - Unexpected literal function used as operator: ";
+            dump_sexp(op);
+            std::cout << "\n";
         }
     }
 }
@@ -267,6 +331,11 @@
             interval i=f2->value().convert();
             break;
         }
+        default:
+            //TODO: Better error stuff
+            std::cout << "Invalid eval tree - Unexpected operator function";
+            dump_sexp(f);
+            std::cout << "\n";
         }
     }
 }