public virtual void ProcessResults(IParserQuery pq, Tree goldTree, PrintWriter pwErr, PrintWriter pwOut, PrintWriter pwFileOut, PrintWriter pwStats, TreePrint treePrint)
        {
            if (pq.SaidMemMessage())
            {
                saidMemMessage = true;
            }
            Tree             tree;
            IList <IHasWord> sentence = pq.OriginalSentence();

            try
            {
                tree = pq.GetBestParse();
            }
            catch (NoSuchParseException)
            {
                tree = null;
            }
            IList <ScoredObject <Tree> > kbestPCFGTrees = null;

            if (tree != null && kbestPCFG > 0)
            {
                kbestPCFGTrees = pq.GetKBestPCFGParses(kbestPCFG);
            }
            //combo parse goes to pwOut (System.out)
            if (op.testOptions.verbose)
            {
                pwOut.Println("ComboParser best");
                Tree ot = tree;
                if (ot != null && !op.tlpParams.TreebankLanguagePack().IsStartSymbol(ot.Value()))
                {
                    ot = ot.TreeFactory().NewTreeNode(op.tlpParams.TreebankLanguagePack().StartSymbol(), Java.Util.Collections.SingletonList(ot));
                }
                treePrint.PrintTree(ot, pwOut);
            }
            else
            {
                treePrint.PrintTree(tree, pwOut);
            }
            // **OUTPUT**
            // print various n-best like outputs (including 1-best)
            // print various statistics
            if (tree != null)
            {
                if (op.testOptions.printAllBestParses)
                {
                    IList <ScoredObject <Tree> > parses = pq.GetBestPCFGParses();
                    int sz = parses.Count;
                    if (sz > 1)
                    {
                        pwOut.Println("There were " + sz + " best PCFG parses with score " + parses[0].Score() + '.');
                        Tree transGoldTree = collinizer.TransformTree(goldTree);
                        int  iii           = 0;
                        foreach (ScoredObject <Tree> sot in parses)
                        {
                            iii++;
                            Tree tb  = sot.Object();
                            Tree tbd = debinarizer.TransformTree(tb);
                            tbd = subcategoryStripper.TransformTree(tbd);
                            pq.RestoreOriginalWords(tbd);
                            pwOut.Println("PCFG Parse #" + iii + " with score " + tbd.Score());
                            tbd.PennPrint(pwOut);
                            Tree tbtr = collinizer.TransformTree(tbd);
                            // pwOut.println("Tree size = " + tbtr.size() + "; depth = " + tbtr.depth());
                            kGoodLB.Evaluate(tbtr, transGoldTree, pwErr);
                        }
                    }
                }
                else
                {
                    // Huang and Chiang (2006) Algorithm 3 output from the PCFG parser
                    if (op.testOptions.printPCFGkBest > 0 && op.testOptions.outputkBestEquivocation == null)
                    {
                        IList <ScoredObject <Tree> > trees = kbestPCFGTrees.SubList(0, op.testOptions.printPCFGkBest);
                        Tree transGoldTree = collinizer.TransformTree(goldTree);
                        int  i             = 0;
                        foreach (ScoredObject <Tree> tp in trees)
                        {
                            i++;
                            pwOut.Println("PCFG Parse #" + i + " with score " + tp.Score());
                            Tree tbd = tp.Object();
                            tbd.PennPrint(pwOut);
                            Tree tbtr = collinizer.TransformTree(tbd);
                            kGoodLB.Evaluate(tbtr, transGoldTree, pwErr);
                        }
                    }
                    else
                    {
                        // Chart parser (factored) n-best list
                        if (op.testOptions.printFactoredKGood > 0 && pq.HasFactoredParse())
                        {
                            // DZ: debug n best trees
                            IList <ScoredObject <Tree> > trees = pq.GetKGoodFactoredParses(op.testOptions.printFactoredKGood);
                            Tree transGoldTree = collinizer.TransformTree(goldTree);
                            int  ii            = 0;
                            foreach (ScoredObject <Tree> tp in trees)
                            {
                                ii++;
                                pwOut.Println("Factored Parse #" + ii + " with score " + tp.Score());
                                Tree tbd = tp.Object();
                                tbd.PennPrint(pwOut);
                                Tree tbtr = collinizer.TransformTree(tbd);
                                kGoodLB.Evaluate(tbtr, transGoldTree, pwOut);
                            }
                        }
                        else
                        {
                            //1-best output
                            if (pwFileOut != null)
                            {
                                pwFileOut.Println(tree.ToString());
                            }
                        }
                    }
                }
                //Print the derivational entropy
                if (op.testOptions.outputkBestEquivocation != null && op.testOptions.printPCFGkBest > 0)
                {
                    IList <ScoredObject <Tree> > trees = kbestPCFGTrees.SubList(0, op.testOptions.printPCFGkBest);
                    double[] logScores = new double[trees.Count];
                    int      treeId    = 0;
                    foreach (ScoredObject <Tree> kBestTree in trees)
                    {
                        logScores[treeId++] = kBestTree.Score();
                    }
                    //Re-normalize
                    double entropy = 0.0;
                    double denom   = ArrayMath.LogSum(logScores);
                    foreach (double logScore in logScores)
                    {
                        double logPr = logScore - denom;
                        entropy += System.Math.Exp(logPr) * (logPr / System.Math.Log(2));
                    }
                    entropy *= -1;
                    //Convert to bits
                    pwStats.Printf("%f\t%d\t%d\n", entropy, trees.Count, sentence.Count);
                }
            }
            // **EVALUATION**
            // Perform various evaluations specified by the user
            if (tree != null)
            {
                //Strip subcategories and remove punctuation for evaluation
                tree = subcategoryStripper.TransformTree(tree);
                Tree treeFact = collinizer.TransformTree(tree);
                //Setup the gold tree
                if (op.testOptions.verbose)
                {
                    pwOut.Println("Correct parse");
                    treePrint.PrintTree(goldTree, pwOut);
                }
                Tree transGoldTree = collinizer.TransformTree(goldTree);
                if (transGoldTree != null)
                {
                    transGoldTree = subcategoryStripper.TransformTree(transGoldTree);
                }
                //Can't do evaluation in these two cases
                if (transGoldTree == null)
                {
                    pwErr.Println("Couldn't transform gold tree for evaluation, skipping eval. Gold tree was:");
                    goldTree.PennPrint(pwErr);
                    numSkippedEvals++;
                    return;
                }
                else
                {
                    if (treeFact == null)
                    {
                        pwErr.Println("Couldn't transform hypothesis tree for evaluation, skipping eval. Tree was:");
                        tree.PennPrint(pwErr);
                        numSkippedEvals++;
                        return;
                    }
                    else
                    {
                        if (treeFact.Yield().Count != transGoldTree.Yield().Count)
                        {
                            IList <ILabel> fYield = treeFact.Yield();
                            IList <ILabel> gYield = transGoldTree.Yield();
                            pwErr.Println("WARNING: Evaluation could not be performed due to gold/parsed yield mismatch.");
                            pwErr.Printf("  sizes: gold: %d (transf) %d (orig); parsed: %d (transf) %d (orig).%n", gYield.Count, goldTree.Yield().Count, fYield.Count, tree.Yield().Count);
                            pwErr.Println("  gold: " + SentenceUtils.ListToString(gYield, true));
                            pwErr.Println("  pars: " + SentenceUtils.ListToString(fYield, true));
                            numSkippedEvals++;
                            return;
                        }
                    }
                }
                if (topKEvals.Count > 0)
                {
                    IList <Tree> transGuesses = new List <Tree>();
                    int          kbest        = System.Math.Min(op.testOptions.evalPCFGkBest, kbestPCFGTrees.Count);
                    foreach (ScoredObject <Tree> guess in kbestPCFGTrees.SubList(0, kbest))
                    {
                        transGuesses.Add(collinizer.TransformTree(guess.Object()));
                    }
                    foreach (BestOfTopKEval eval in topKEvals)
                    {
                        eval.Evaluate(transGuesses, transGoldTree, pwErr);
                    }
                }
                //PCFG eval
                Tree treePCFG = pq.GetBestPCFGParse();
                if (treePCFG != null)
                {
                    Tree treePCFGeval = collinizer.TransformTree(treePCFG);
                    if (pcfgLB != null)
                    {
                        pcfgLB.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgChildSpecific != null)
                    {
                        pcfgChildSpecific.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgLA != null)
                    {
                        pcfgLA.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgCB != null)
                    {
                        pcfgCB.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgDA != null)
                    {
                        // Re-index the leaves after Collinization, stripping traces, etc.
                        treePCFGeval.IndexLeaves(true);
                        transGoldTree.IndexLeaves(true);
                        pcfgDA.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgTA != null)
                    {
                        pcfgTA.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgLL != null && pq.GetPCFGParser() != null)
                    {
                        pcfgLL.RecordScore(pq.GetPCFGParser(), pwErr);
                    }
                    if (pcfgRUO != null)
                    {
                        pcfgRUO.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgCUO != null)
                    {
                        pcfgCUO.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                    if (pcfgCatE != null)
                    {
                        pcfgCatE.Evaluate(treePCFGeval, transGoldTree, pwErr);
                    }
                }
                //Dependency eval
                // todo: is treeDep really useful here, or should we really use depDAEval tree (debinarized) throughout? We use it for parse, and it sure seems like we could use it for tag eval, but maybe not factDA?
                Tree treeDep = pq.GetBestDependencyParse(false);
                if (treeDep != null)
                {
                    Tree goldTreeB    = binarizerOnly.TransformTree(goldTree);
                    Tree goldTreeEval = goldTree.DeepCopy();
                    goldTreeEval.IndexLeaves(true);
                    goldTreeEval.PercolateHeads(op.Langpack().HeadFinder());
                    Tree depDAEval = pq.GetBestDependencyParse(true);
                    depDAEval.IndexLeaves(true);
                    depDAEval.PercolateHeadIndices();
                    if (depDA != null)
                    {
                        depDA.Evaluate(depDAEval, goldTreeEval, pwErr);
                    }
                    if (depTA != null)
                    {
                        Tree undoneTree = debinarizer.TransformTree(treeDep);
                        undoneTree = subcategoryStripper.TransformTree(undoneTree);
                        pq.RestoreOriginalWords(undoneTree);
                        // pwErr.println("subcategoryStripped tree: " + undoneTree.toStructureDebugString());
                        depTA.Evaluate(undoneTree, goldTree, pwErr);
                    }
                    if (depLL != null && pq.GetDependencyParser() != null)
                    {
                        depLL.RecordScore(pq.GetDependencyParser(), pwErr);
                    }
                    Tree factTreeB;
                    if (pq.HasFactoredParse())
                    {
                        factTreeB = pq.GetBestFactoredParse();
                    }
                    else
                    {
                        factTreeB = treeDep;
                    }
                    if (factDA != null)
                    {
                        factDA.Evaluate(factTreeB, goldTreeB, pwErr);
                    }
                }
                //Factored parser (1best) eval
                if (factLB != null)
                {
                    factLB.Evaluate(treeFact, transGoldTree, pwErr);
                }
                if (factChildSpecific != null)
                {
                    factChildSpecific.Evaluate(treeFact, transGoldTree, pwErr);
                }
                if (factLA != null)
                {
                    factLA.Evaluate(treeFact, transGoldTree, pwErr);
                }
                if (factTA != null)
                {
                    factTA.Evaluate(tree, boundaryRemover.TransformTree(goldTree), pwErr);
                }
                if (factLL != null && pq.GetFactoredParser() != null)
                {
                    factLL.RecordScore(pq.GetFactoredParser(), pwErr);
                }
                if (factCB != null)
                {
                    factCB.Evaluate(treeFact, transGoldTree, pwErr);
                }
                foreach (IEval eval_1 in evals)
                {
                    eval_1.Evaluate(treeFact, transGoldTree, pwErr);
                }
                if (parserQueryEvals != null)
                {
                    foreach (IParserQueryEval eval in parserQueryEvals)
                    {
                        eval_1.Evaluate(pq, transGoldTree, pwErr);
                    }
                }
                if (op.testOptions.evalb)
                {
                    // empty out scores just in case
                    NanScores(tree);
                    EvalbFormatWriter.WriteEVALBline(treeFact, transGoldTree);
                }
            }
            pwErr.Println();
        }
            // end parseFiles
            public virtual void ProcessResults(IParserQuery parserQuery, int num, PrintWriter pwo)
        {
            if (parserQuery.ParseSkipped())
            {
                IList <IHasWord> sentence = parserQuery.OriginalSentence();
                if (sentence != null)
                {
                    numWords -= sentence.Count;
                }
                numSkipped++;
            }
            if (parserQuery.ParseNoMemory())
            {
                numNoMemory++;
            }
            if (parserQuery.ParseUnparsable())
            {
                numUnparsable++;
            }
            if (parserQuery.ParseFallback())
            {
                numFallback++;
            }
            saidMemMessage = saidMemMessage || parserQuery.SaidMemMessage();
            Tree ansTree = parserQuery.GetBestParse();

            if (ansTree == null)
            {
                pwo.Println("(())");
                return;
            }
            if (pcfgLL != null && parserQuery.GetPCFGParser() != null)
            {
                pcfgLL.RecordScore(parserQuery.GetPCFGParser(), pwErr);
            }
            if (depLL != null && parserQuery.GetDependencyParser() != null)
            {
                depLL.RecordScore(parserQuery.GetDependencyParser(), pwErr);
            }
            if (factLL != null && parserQuery.GetFactoredParser() != null)
            {
                factLL.RecordScore(parserQuery.GetFactoredParser(), pwErr);
            }
            try
            {
                treePrint.PrintTree(ansTree, int.ToString(num), pwo);
            }
            catch (Exception re)
            {
                pwErr.Println("TreePrint.printTree skipped: out of memory (or other error)");
                Sharpen.Runtime.PrintStackTrace(re, pwErr);
                numNoMemory++;
                try
                {
                    treePrint.PrintTree(null, int.ToString(num), pwo);
                }
                catch (Exception e)
                {
                    pwErr.Println("Sentence skipped: out of memory or error calling TreePrint.");
                    pwo.Println("(())");
                    Sharpen.Runtime.PrintStackTrace(e, pwErr);
                }
            }
            // crude addition of k-best tree printing
            // TODO: interface with the RerankingParserQuery
            if (op.testOptions.printPCFGkBest > 0 && parserQuery.GetPCFGParser() != null && parserQuery.GetPCFGParser().HasParse())
            {
                IList <ScoredObject <Tree> > trees = parserQuery.GetKBestPCFGParses(op.testOptions.printPCFGkBest);
                treePrint.PrintTrees(trees, int.ToString(num), pwo);
            }
            else
            {
                if (op.testOptions.printFactoredKGood > 0 && parserQuery.GetFactoredParser() != null && parserQuery.GetFactoredParser().HasParse())
                {
                    // DZ: debug n best trees
                    IList <ScoredObject <Tree> > trees = parserQuery.GetKGoodFactoredParses(op.testOptions.printFactoredKGood);
                    treePrint.PrintTrees(trees, int.ToString(num), pwo);
                }
            }
        }