docs: function makeGrammar (ParseTree, config) {
    var vars = config.vars || {}, root = config.root
    var cfg = {}
    return makeGrammarSymbol (ParseTree, config, cfg, [typeof(root) === 'string' ? ParseTree.parseRhs(root) : root], 'start')
      .then (function (start) {
        if (!start)
          return null
        var toposort = toposortSymbols (cfg, start.name)
        var sortOrder = toposort.sort || Object.keys(cfg).sort()
        var symbolRank = {}
        sortOrder.forEach (function (sym, n) { symbolRank[sym] = n })
        sortOrder.forEach (function (sym) {
          if (cfg[sym].opts)
            cfg[sym].opts.forEach (function (opt) {
              opt.rhs.forEach (function (node) {
                if (node.type === 'nonterm')
                  node.rank = symbolRank[node.name]
              })
            })
        })
        return { stateByName: cfg,
                 stateByRank: sortOrder.map (function (sym) { return cfg[sym] }),
                 rankByName: symbolRank,
  	       nameByRank: sortOrder,
  	       cyclic: toposort.cyclic,
  	       empties: toposort.empties,
  	       start: start.name }
      })
  }