private void processEdge(Edge edge) {
    // project unaries
    for (UnaryRule unaryRule : grammar.getUnaryRulesByChild(edge.getLabel())) {
      Edge resultEdge = makeEdge(unaryRule.getParent(), edge.getStart(), edge.getEnd());
      if (verbose) System.err.println("Using unary "+unaryRule+" on "+edge+" to create "+resultEdge);
      discoverEdge(resultEdge);
      resultEdge.addBacktrace(edge);
    }
    // project left siblings
    for (BinaryRule binaryRule : grammar.getBinaryRulesByRightChild(edge.getLabel())) {
      List<Edge> leftMatches = chart.getEdgesByRightIndex(binaryRule.getLeftChild(), edge.getStart());
      for (Edge leftMatch : leftMatches) {
        Edge resultEdge = makeEdge(binaryRule.getParent(), leftMatch.getStart(), edge.getEnd());
        if (verbose) System.err.println("Using binary "+binaryRule+" on "+leftMatch+" and "+edge+" to create "+resultEdge);
        discoverEdge(resultEdge);
        resultEdge.addBacktrace(leftMatch, edge);
      }
    }
    // project right siblings
    for (BinaryRule binaryRule : grammar.getBinaryRulesByLeftChild(edge.getLabel())) {
      List<Edge> rightMatches = chart.getEdgesByLeftIndex(binaryRule.getRightChild(), edge.getEnd());
      for (Edge rightMatch : rightMatches) {
        Edge resultEdge = makeEdge(binaryRule.getParent(), edge.getStart(), rightMatch.getEnd());
        if (verbose) System.err.println("Using binary "+binaryRule+" on "+edge+" and "+rightMatch+" to create "+resultEdge);
        discoverEdge(resultEdge);
        resultEdge.addBacktrace(edge, rightMatch);
      }
    }
  }