@Override public Node visitTree(@NotNull NewickParser.TreeContext ctx) { Node root = visit(ctx.node()); // Ensure tree is properly sorted in terms of node numbers. root.sort(); // Replace lengths read from Newick with heights. convertLengthToHeight(root); // Make sure internal nodes are numbered correctly numberUnnumberedNodes(root); // Check for duplicate taxa BitSet nodeNrSeen = new BitSet(); for (Node leaf : root.getAllLeafNodes()) { if (leaf.getNr() < 0) continue; // Skip unnumbered leaves if (nodeNrSeen.get(leaf.getNr())) throw new ParseCancellationException( "Duplicate taxon found: " + labels.get(leaf.getNr())); else nodeNrSeen.set(leaf.getNr()); } return root; }