document.observe('dom:loaded', function() {
  function NewDoEnter(left, right) {
    return function() {
      left.setAttribute("class", "paren-highlight");
      right.setAttribute("class", "paren-highlight");
    };
  };
  function NewDoLeave(left, right) {
    return function () {
      left.setAttribute("class", "paren-normal");
      right.setAttribute("class", "paren-normal");
    };
  };
  var resolver = { // implements XPathNSResolver
    lookupNamespaceURI: function(ns) {
      return "http://www.w3.org/1999/xhtml";
    }
  };
  $$('code').each(function(code) {
    var nodestack = new Array();
    var nodes = document.evaluate(".//text()", code, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var j = 0; j < nodes.snapshotLength; ++j) {
      var node = nodes.snapshotItem(j);
      var nodetext = node.nodeValue;
      var ms = nodetext.match(/[\[\]\(\)]|[^\[\]\(\)]+/g);
      if (ms.length) {
        var newnodes = ms.collect(function(text) {
          var textnode = document.createTextNode(text);
          switch (text) {
            default:
              return textnode;
            case '(':
            case '[':
              var leftnode = new Element('span').update(text);
              nodestack.push(leftnode);
              return leftnode;
            case ')':
            case ']':
              if (nodestack.length <= 0)
                return textnode;
              var leftnode = nodestack.pop();
              var rightnode = new Element('span').update(text);
              var doenter = NewDoEnter(leftnode, rightnode);
              var doleave = NewDoLeave(leftnode, rightnode);
              [leftnode, rightnode].invoke('observe', 'mouseover', doenter).invoke('observe', 'mouseout', doleave);
              doleave();
              return rightnode;
          }
        });
        newnodes.each(function(newnode) {
          node.parentNode.insertBefore(newnode, node);
        });
        node.parentNode.removeChild(node);
      }
    }
  });
});
