code: function first(FIRST, rule) {
    var terminals = new Set();
    var read = true;
    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;
  
    try {
      for (var _iterator = rule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var x = _step.value;
        if (!read) break;
        read = false;
  
        if (x.type === 'leaf') {
          terminals.add(x.terminal);
          break;
        }
  
        (0, _util.setaddall)(terminals, (0, _jsItertools.filter)(function (y) {
          return y !== _grammar.EW;
        }, FIRST.get(x.nonterminal)));
        read |= (0, _jsItertools.any)((0, _jsItertools.map)(function (y) {
          return y === _grammar.EW;
        }, FIRST.get(x.nonterminal)));
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion && _iterator.return != null) {
          _iterator.return();
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }
  
    if (read) terminals.add(_grammar.EW);
    return terminals;
  }
docs: Generate FIRST set for any rule given the FIRST sets for the nonterminals.
  
  @param {Map} FIRST
  @param {Array} rule
  @returns {Set}