docs: function countWords (text, ParseTree, isWord) {
    isWord = isWord || {};
    function countWord (word) {
      if (word)
        isWord[word.toLowerCase()] = true;
    }
    function countWordsAtNodes (nodes) {
      if (nodes)
        nodes.forEach (countWordsAtNode);
    }
    function countWordsAtNode (node) {
      if (typeof(node) === 'object') {
        if (node.functag)
  	countWord (ParseTree.funcChar + node.functag);
        switch (node.type) {
        case 'lookup':
  	countWord (ParseTree.varChar + node.varname);
          break
        case 'assign':
  	countWord (ParseTree.varChar + node.varname);
          countWordsAtNodes (node.value);
          countWordsAtNodes (node.local);
          break
        case 'alt':
          node.opts.forEach (countWordsAtNodes);
          break
        case 'rep':
          countWordsAtNodes (node.unit);
          break
        case 'func':
  	countWord (ParseTree.funcChar + node.funcname);
  	switch (node.funcname) {
  	case 'eval':
            countWordsAtNodes (node.value);
            countWordsAtNodes (node.args);
  	  break
  	case 'strictquote':
  	case 'quote':
  	case 'unquote':
          default:
            countWordsAtNodes (node.args);
            break
  	}
          break
        case 'cond':
          if (ParseTree.isTraceryExpr (node))
  	  countWord (ParseTree.traceryChar + ParseTree.traceryVarName(node) + ParseTree.traceryChar);
          countWordsAtNodes (node.test);
          countWordsAtNodes (node.t);
          countWordsAtNodes (node.f);
          break
        case 'root':
        case 'alt_sampled':
          countWordsAtNodes (node.rhs);
          break
        case 'rep_sampled':
          node.reps.forEach (countWordsAtNodes);
          break
        case 'sym':
  	countWord (ParseTree.symChar + ParseTree.leftBraceChar + (node.user || ParseTree.defaultUser) + '/' + node.name + ParseTree.rightBraceChar);
          countWordsAtNodes (node.rhs);
          countWordsAtNodes (node.bind);
          break
        default:
  	break
        }
      } else if (typeof(node) === 'string')
        node
        .replace(/[^a-zA-Z0-9_]/g,' ')  // these are the characters we keep
        .replace(/\s+/g,' ').replace(/^ /,'').replace(/ $/,'')  // collapse all runs of space & remove start/end space
        .split(' ')
        .forEach (countWord);
    }
    
    var parsed = ParseTree.parseRhs (text);
    countWordsAtNodes (parsed);
  
    return isWord;
  }