code: function rpnToTree(values) {
      let ii, len, op, stack, slice, count;
  
      stack = [];
      // result = [];
      for (ii = 0, len = values.length; ii < len; ii++) {
          op = values[ii];
  
          if (op === LEFT_PAREN) {
              // cut out this sub and convert it to a tree
              slice = findMatchingRightParam(values, ii);
  
              if (!slice || slice.length === 0) {
                  throw new Error('mismatch parentheses');
              }
  
              ii += slice.length + 1;
  
              // evaluate this sub command before pushing it to the stack
              slice = rpnToTree(slice);
  
              stack.push(slice);
          } else {
              if (Array.isArray(op)) {
                  stack.push(op);
              } else {
                  // figure out how many arguments to take from the stack
                  count = argCount(op);
  
                  slice = stack.splice(stack.length - count, count);
  
                  if (Array.isArray(slice) && slice.length === 1) {
                      slice = arrayFlatten(slice, true);
                  }
  
                  // TODO: ugh, occasionally args will get flattened too much
                  if (slice[0] === VALUE) {
                      // note only happens with ALIAS_GET
                      // log.debug('overly flat ' + JSON.stringify([op].concat(slice)));
                      slice = [slice];
                  }
                  stack.push([op].concat(slice));
              }
          }
      }
  
      return stack;
  }
docs: Converts an RPN expression into an AST