public Grammar(BufferedReader in) throws IOException {
      Pattern linePattern = Pattern.compile("^\\s*(\\S+)\\s*-*>\\s*(.*\\S+)\\s*$");
      while (in.ready()) {
        String line = in.readLine();
        Matcher matcher = linePattern.matcher(line);
        if (!matcher.matches()) throw new RuntimeException("Bad line in grammar: "+line);
        String parent = matcher.group(1);
        String children = matcher.group(2);
        String[] childArray = children.split("\\s+");
        if (childArray.length == 1) {
          // unary rule
          addUnary(new UnaryRule(parent, childArray[0]));
        } else if (childArray.length == 2) {
          // binary rule
          addBinary(new BinaryRule(parent, childArray[0], childArray[1]));
        } else {
          // left-trie binarize an n-ary rule
          StringBuilder intermediateSymbol = new StringBuilder("@NP->");
          String lastRight = childArray[0];
          intermediateSymbol.append(lastRight);
          int pos = 1;
          while (pos < childArray.length) {
            String leftChild = intermediateSymbol.toString();
            if (pos == 1) leftChild = childArray[0];
            String rightChild = childArray[pos];
            intermediateSymbol.append("_");
            intermediateSymbol.append(rightChild);
            String intermediateParent = intermediateSymbol.toString();
            if (pos == childArray.length-1) intermediateParent = parent;
            addBinary(new BinaryRule(intermediateParent, leftChild, rightChild));
            pos++;
          }
        }
      }
    }