lib/integral.js
function(expr, context, subIntegral) {
      if(expr.type === "OperatorNode" && expr.op === "*") {
        var factors = getFactors(expr);
        if(factors.length > expr.args.length) {
          return subIntegral(new OperatorNode('*', 'multiply', factors), context, "product flattening");
        }
      }

      function getFactors(expr) {
        if(expr.type === "OperatorNode" && expr.op === "*") {
          return expr.args.reduce(function(factors, expr) {
            return factors.concat(getFactors(expr));
          }, []);
        } else if (expr.type === "ParenthesisNode") {
          return getFactors(expr.content)
        } else {
          return [expr];
        }
      }
    }
function(expr, context, subIntegral) {
      if(expr.type === "OperatorNode" && expr.op === "*") {
        var factors = getFactors(expr);
        if(factors.length > expr.args.length) {
          return subIntegral(new OperatorNode('*', 'multiply', factors), context, "product flattening");
        }
      }

      function getFactors(expr) {
        if(expr.type === "OperatorNode" && expr.op === "*") {
          return expr.args.reduce(function(factors, expr) {
            return factors.concat(getFactors(expr));
          }, []);
        } else if (expr.type === "ParenthesisNode") {
          return getFactors(expr.content)
        } else {
          return [expr];
        }
      }
    }
integral(f(x) * (g(x) * h(x)), x) = integral(f(x) * g(x) * h(x), x)