gt:             depRel = d.name().toString();
context: package edu.stanford.nlp.trees; 
  import edu.stanford.nlp.util.logging.Redwood;
  
  import edu.stanford.nlp.ling.*;
  import edu.stanford.nlp.process.PTBTokenizer;
  import edu.stanford.nlp.trees.international.pennchinese.ChineseEnglishWordMap;
  import edu.stanford.nlp.util.*;
  import edu.stanford.nlp.util.XMLUtils;
  
  import java.io.*;
  import java.util.*;
  import java.util.function.Function;
  import java.util.function.Predicate;
  
  
  /**
   * A class for customizing the print method(s) for a
   * <code>edu.stanford.nlp.trees.Tree</code> as the output of the
   * parser.  This class supports printing in multiple ways and altering
   * behavior via properties specified at construction.
   *
   * @author Roger Levy
   * @author Christopher Manning
   * @author Galen Andrew
   */
  public class TreePrint  {
  
    /** A logger for this class */
    private static Redwood.RedwoodChannels log = Redwood.channels(TreePrint.class);
  
    // TODO: Add support for makeCopulaHead as an outputFormatOption here.
  
    public static final String rootLabelOnlyFormat = "rootSymbolOnly";
    public static final String headMark = "=H";
  
    /** The legal output tree formats. */
    public static final String[] outputTreeFormats = {
      "penn",
      "oneline",
      rootLabelOnlyFormat,
      "words",
      "wordsAndTags",
      "dependencies",
      "typedDependencies",
      "typedDependenciesCollapsed",
      "latexTree",
      "xmlTree",
      "collocations",
      "semanticGraph",
      "conllStyleDependencies",
      "conll2007"
    };
  
    private final Properties formats;
    private final Properties options;
  
    private final boolean markHeadNodes; // = false;
    private final boolean lexicalize; // = false;
    private final boolean removeEmpty;
    private final boolean ptb2text;
    private final boolean transChinese; // = false;
    private final boolean basicDependencies;
    private final boolean collapsedDependencies;
    private final boolean nonCollapsedDependencies;
    private final boolean nonCollapsedDependenciesSeparated;
    private final boolean CCPropagatedDependencies;
    private final boolean treeDependencies;
  
    private final boolean includeTags;
  
    private final HeadFinder hf;
    private final TreebankLanguagePack tlp;
    private final WordStemmer stemmer;
    private final Predicate<Dependency<Label, Label, Object>> dependencyFilter;
    private final Predicate<Dependency<Label, Label, Object>> dependencyWordFilter;
    private final GrammaticalStructureFactory gsf;
  
    /** Pool use of one WordNetConnection.  I don't really know if
     *  Dan Bikel's WordNet code is thread safe, but it definitely doesn't
     *  close its files, and too much of our code makes TreePrint objects and
     *  then drops them on the floor, and so we run out of file handles.
     *  That is, if this variable isn't static, code crashes.
     *  Maybe we should change this code to use jwnl(x)?
     *  CDM July 2006.
     */
    private static WordNetConnection wnc;
  
  
    /** This PrintWriter is used iff the user doesn't pass one in to a
     *  call to printTree().  It prints to System.out.
     */
    private final PrintWriter pw = new PrintWriter(System.out, true);
  
  
    /** Construct a new TreePrint that will print the given formats.
     *  Warning! This is the anglocentric constructor.
     *  It will work correctly only for English.
     *
     *  @param formats The formats to print the tree in.
     */
    public TreePrint(String formats) {
      this(formats, "", new PennTreebankLanguagePack());
    }
  
    /** Make a TreePrint instance with no options specified. */
    public TreePrint(String formats, TreebankLanguagePack tlp) {
      this(formats, "", tlp);
    }
  
    /** Make a TreePrint instance. This one uses the default tlp headFinder. */
    public TreePrint(String formats, String options, TreebankLanguagePack tlp) {
      this(formats, options, tlp, tlp.headFinder(), tlp.typedDependencyHeadFinder());
    }
  
    /**
     * Make a TreePrint instance.
     *
     * @param formatString A comma separated list of ways to print each Tree.
     *                For instance, "penn" or "words,typedDependencies".
     *                Known formats are: oneline, penn, latexTree, xmlTree, words,
     *                wordsAndTags, rootSymbolOnly, dependencies,
     *                typedDependencies, typedDependenciesCollapsed,
     *                collocations, semanticGraph, conllStyleDependencies,
     *                conll2007.  The last two are both tab-separated values
     *                formats.  The latter has a lot more columns filled with
     *                underscores. All of them print a blank line after
     *                the output except for oneline.  oneline is also not
     *                meaningful in XML output (it is ignored: use penn instead).
     *                (Use of typedDependenciesCollapsed is deprecated.  It
     *                works but we recommend instead selecting a type of
     *                dependencies using the optionsString argument.  Note in
     *                particular that typedDependenciesCollapsed does not do
     *                CC propagation, which we generally recommend.)
     * @param optionsString Options that additionally specify how trees are to
     *                be printed (for instance, whether stemming should be done).
     *                Known options are: <code>stem, lexicalize, markHeadNodes,
     *                xml, removeTopBracket, transChinese,
     *                includePunctuationDependencies, basicDependencies, treeDependencies,
     *                CCPropagatedDependencies, collapsedDependencies, nonCollapsedDependencies,
     *                nonCollapsedDependenciesSeparated, includeTags
     *                </code>.
     * @param tlp     The TreebankLanguagePack used to do things like delete
     *                or ignore punctuation in output
     * @param hf      The HeadFinder used in printing output
     */
    public TreePrint(String formatString, String optionsString, TreebankLanguagePack tlp, HeadFinder hf, HeadFinder typedDependencyHF) {
      formats = StringUtils.stringToProperties(formatString);
      options = StringUtils.stringToProperties(optionsString);
      List<String> okOutputs = Arrays.asList(outputTreeFormats);
      for (Object formObj : formats.keySet()) {
        String format = (String) formObj;
        if ( ! okOutputs.contains(format)) {
          throw new RuntimeException("Error: output tree format " + format + " not supported. Known formats are: " + okOutputs);
        }
      }
  
      this.hf = hf;
      this.tlp = tlp;
      boolean includePunctuationDependencies;
      includePunctuationDependencies = propertyToBoolean(this.options,
                                                         "includePunctuationDependencies");
  
      boolean generateOriginalDependencies = tlp.generateOriginalDependencies();
  
      Predicate<String> puncFilter;
      if (includePunctuationDependencies) {
        dependencyFilter = Filters.acceptFilter();
        dependencyWordFilter = Filters.acceptFilter();
        puncFilter = Filters.acceptFilter();
      } else {
        dependencyFilter = new Dependencies.DependentPuncTagRejectFilter<>(tlp.punctuationTagRejectFilter());
        dependencyWordFilter = new Dependencies.DependentPuncWordRejectFilter<>(tlp.punctuationWordRejectFilter());
        //Universal dependencies filter punction by tags
        puncFilter = generateOriginalDependencies ? tlp.punctuationWordRejectFilter() : tlp.punctuationTagRejectFilter();
      }
      if (propertyToBoolean(this.options, "stem")) {
        stemmer = new WordStemmer();
      } else {
        stemmer = null;
      }
      if (formats.containsKey("typedDependenciesCollapsed") ||
          formats.containsKey("typedDependencies") ||
          (formats.containsKey("conll2007") && tlp.supportsGrammaticalStructures())) {
        gsf = tlp.grammaticalStructureFactory(puncFilter, typedDependencyHF);
      } else {
        gsf = null;
      }
  
      lexicalize = propertyToBoolean(this.options, "lexicalize");
      markHeadNodes = propertyToBoolean(this.options, "markHeadNodes");
      transChinese = propertyToBoolean(this.options, "transChinese");
      ptb2text = propertyToBoolean(this.options, "ptb2text");
      removeEmpty = propertyToBoolean(this.options, "noempty") || ptb2text;
  
      basicDependencies =  propertyToBoolean(this.options, "basicDependencies");
      collapsedDependencies = propertyToBoolean(this.options, "collapsedDependencies");
      nonCollapsedDependencies = propertyToBoolean(this.options, "nonCollapsedDependencies");
      nonCollapsedDependenciesSeparated = propertyToBoolean(this.options, "nonCollapsedDependenciesSeparated");
      treeDependencies = propertyToBoolean(this.options, "treeDependencies");
  
      includeTags = propertyToBoolean(this.options, "includeTags");
  
      // if no option format for the dependencies is specified, CCPropagated is the default
      if ( ! basicDependencies && ! collapsedDependencies && ! nonCollapsedDependencies && ! nonCollapsedDependenciesSeparated && ! treeDependencies) {
        CCPropagatedDependencies = true;
      } else {
        CCPropagatedDependencies = propertyToBoolean(this.options, "CCPropagatedDependencies");
      }
    }
  
  
    private static boolean propertyToBoolean(Properties prop, String key) {
      return Boolean.parseBoolean(prop.getProperty(key));
    }
  
    /**
     * Prints the tree to the default PrintWriter.
     * @param t The tree to display
     */
    public void printTree(Tree t) {
      printTree(t, pw);
    }
  
    /**
     * Prints the tree, with an empty ID.
     * @param t The tree to display
     * @param pw The PrintWriter to print it to
     */
    public void printTree(final Tree t, PrintWriter pw) {
      printTree(t, "", pw);
    }
  
  
    /**
     * Prints the tree according to the options specified for this instance.
     * If the tree <code>t</code> is <code>null</code>, then the code prints
     * a line indicating a skipped tree.  Under the XML option this is
     * an <code>s</code> element with the <code>skipped</code> attribute having
     * value <code>true</code>, and, otherwise, it is the token
     * <code>SENTENCE_SKIPPED_OR_UNPARSABLE</code>.
     *
     * @param t The tree to display
     * @param id A name for this sentence
     * @param pw Where to display the tree
     */
    public void printTree(final Tree t, final String id, final PrintWriter pw) {
      final boolean inXml = propertyToBoolean(options, "xml");
      if (t == null) {
        // Parsing didn't succeed.
        if (inXml) {
          pw.print("<s");
          if (id != null && ! "".equals(id)) {
            pw.print(" id=\"" + XMLUtils.escapeXML(id) + '\"');
          }
          pw.println(" skipped=\"true\"/>");
          pw.println();
        } else {
          pw.println("SENTENCE_SKIPPED_OR_UNPARSABLE");
        }
      } else {
        if (inXml) {
          pw.print("<s");
          if (id != null && ! "".equals(id)) {
            pw.print(" id=\"" + XMLUtils.escapeXML(id) + '\"');
          }
          pw.println(">");
        }
        printTreeInternal(t, pw, inXml);
        if (inXml) {
          pw.println("</s>");
          pw.println();
        }
      }
    }
  
  
    /**
     * Prints the trees according to the options specified for this instance.
     * If the tree <code>t</code> is <code>null</code>, then the code prints
     * a line indicating a skipped tree.  Under the XML option this is
     * an <code>s</code> element with the <code>skipped</code> attribute having
     * value <code>true</code>, and, otherwise, it is the token
     * <code>SENTENCE_SKIPPED_OR_UNPARSABLE</code>.
     *
     * @param trees The list of trees to display
     * @param id A name for this sentence
     * @param pw Where to dislay the tree
     */
    public void printTrees(final List<ScoredObject<Tree>> trees, final String id, final PrintWriter pw) {
      final boolean inXml = propertyToBoolean(options, "xml");
      int ii = 0;  // incremented before used, so first tree is numbered 1
      for (ScoredObject<Tree> tp : trees) {
        ii++;
        Tree t = tp.object();
        double score = tp.score();
  
        if (t == null) {
          // Parsing didn't succeed.
          if (inXml) {
            pw.print("<s");
            if (id != null && ! "".equals(id)) {
              pw.print(" id=\"" + XMLUtils.escapeXML(id) + '\"');
            }
            pw.print(" n=\"");
            pw.print(ii);
            pw.print('\"');
            pw.print(" score=\"" + score + '\"');
            pw.println(" skipped=\"true\"/>");
            pw.println();
          } else {
            pw.println("SENTENCE_SKIPPED_OR_UNPARSABLE Parse #" + ii + " with score " + score);
          }
        } else {
          if (inXml) {
            pw.print("<s");
            if (id != null && ! "".equals(id)) {
              pw.print(" id=\"");
              pw.print(XMLUtils.escapeXML(id));
              pw.print('\"');
            }
            pw.print(" n=\"");
            pw.print(ii);
            pw.print('\"');
            pw.print(" score=\"");
            pw.print(score);
            pw.print('\"');
            pw.println(">");
          } else {
            pw.print("# Parse ");
            pw.print(ii);
            pw.print(" with score ");
            pw.println(score);
          }
          printTreeInternal(t, pw, inXml);
          if (inXml) {
            pw.println("</s>");
            pw.println();
          }
        }
      }
    }
  
  
    /** Print the internal part of a tree having already identified it.
     *  The ID and outer XML element is printed wrapping this method, but none
     *  of the internal content.
     *
     * @param t The tree to print. Now known to be non-null
     * @param pw Where to print it to
     * @param inXml Whether to use XML style printing
     */
    private void printTreeInternal(final Tree t, final PrintWriter pw, final boolean inXml) {
      Tree outputTree = t;
  
      if (formats.containsKey("conll2007") || removeEmpty) {
        outputTree = outputTree.prune(new BobChrisTreeNormalizer.EmptyFilter());
      }
  
      if (formats.containsKey("words")) {
        if (inXml) {
          ArrayList<Label> sentUnstemmed = outputTree.yield();
          pw.println("  <words>");
          int i = 1;
          for (Label w : sentUnstemmed) {
            pw.println("    <word ind=\"" + i + "\">" + XMLUtils.escapeXML(w.value()) + "</word>");
            i++;
          }
          pw.println("  </words>");
        } else {
          String sent = SentenceUtils.listToString(outputTree.yield(), false);
          if(ptb2text) {
            pw.println(PTBTokenizer.ptb2Text(sent));
          } else {
            pw.println(sent);
            pw.println();
          }
        }
      }
  
      if (propertyToBoolean(options, "removeTopBracket")) {
        String s = outputTree.label().value();
        if (tlp.isStartSymbol(s)) {
          if (outputTree.isUnaryRewrite()) {
            outputTree = outputTree.firstChild();
          } else {
            // It's not quite clear what to do if the tree isn't unary at the top
            // but we then don't strip the ROOT symbol, since that seems closer
            // than losing part of the tree altogether....
            log.info("TreePrint: can't remove top bracket: not unary");
          }
        }
        // Note that TreePrint is also called on dependency trees that have
        // a word as the root node, and so we don't error if there isn't
        // the root symbol at the top; rather we silently assume that this
        // is a dependency tree!!
      }
      if (stemmer != null) {
        stemmer.visitTree(outputTree);
      }
      if (lexicalize) {
        outputTree = Trees.lexicalize(outputTree, hf);
        Function<Tree, Tree> a =
          TreeFunctions.getLabeledToDescriptiveCoreLabelTreeFunction();
        outputTree = a.apply(outputTree);
      }
  
      if (formats.containsKey("collocations")) {
        outputTree = getCollocationProcessedTree(outputTree, hf);
      }
  
      if (!lexicalize) { // delexicalize the output tree
        Function<Tree, Tree> a =
          TreeFunctions.getLabeledTreeToStringLabeledTreeFunction();
        outputTree = a.apply(outputTree);
      }
  
      Tree outputPSTree = outputTree;  // variant with head-marking, translations
  
      if (markHeadNodes) {
        outputPSTree = markHeadNodes(outputPSTree);
      }
  
      if (transChinese) {
        TreeTransformer tt = t1 -> {
          t1 = t1.treeSkeletonCopy();
          for (Tree subtree : t1) {
            if (subtree.isLeaf()) {
              Label oldLabel = subtree.label();
              String translation = ChineseEnglishWordMap.getInstance().getFirstTranslation(oldLabel.value());
              if (translation == null) translation = "[UNK]";
              Label newLabel = new StringLabel(oldLabel.value() + ':' + translation);
              subtree.setLabel(newLabel);
            }
          }
          return t1;
        };
        outputPSTree = tt.transformTree(outputPSTree);
      }
  
      if (propertyToBoolean(options, "xml")) {
        if (formats.containsKey("wordsAndTags")) {
          ArrayList<TaggedWord> sent = outputTree.taggedYield();
          pw.println("  <words pos=\"true\">");
          int i = 1;
          for (TaggedWord tw : sent) {
            pw.println("    <word ind=\"" + i + "\" pos=\"" + XMLUtils.escapeXML(tw.tag()) + "\">" + XMLUtils.escapeXML(tw.word()) + "</word>");
            i++;
          }
          pw.println("  </words>");
        }
        if (formats.containsKey("penn")) {
          pw.println("  <tree style=\"penn\">");
          StringWriter sw = new StringWriter();
          PrintWriter psw = new PrintWriter(sw);
          outputPSTree.pennPrint(psw);
          pw.print(XMLUtils.escapeXML(sw.toString()));
          pw.println("  </tree>");
        }
        if (formats.containsKey("latexTree")) {
          pw.println("    <tree style=\"latexTrees\">");
          pw.println(".[");
          StringWriter sw = new StringWriter();
          PrintWriter psw = new PrintWriter(sw);
          outputTree.indentedListPrint(psw,false);
          pw.print(XMLUtils.escapeXML(sw.toString()));
          pw.println(".]");
          pw.println("  </tree>");
        }
        if (formats.containsKey("xmlTree")) {
          pw.println("<tree style=\"xml\">");
          outputTree.indentedXMLPrint(pw,false);
          pw.println("</tree>");
        }
        if (formats.containsKey("dependencies")) {
          Tree indexedTree = outputTree.deepCopy(outputTree.treeFactory(),
                                                   CoreLabel.factory());
          indexedTree.indexLeaves();
          Set<Dependency<Label, Label, Object>> depsSet = indexedTree.mapDependencies(dependencyWordFilter, hf);
          List<Dependency<Label, Label, Object>> sortedDeps = new ArrayList<>(depsSet);
          Collections.sort(sortedDeps, Dependencies.dependencyIndexComparator());
          pw.println("<dependencies style=\"untyped\">");
          for (Dependency<Label, Label, Object> d : sortedDeps) {
            pw.println(d.toString("xml"));
          }
          pw.println("</dependencies>");
        }
        if (formats.containsKey("conll2007") || formats.containsKey("conllStyleDependencies")) {
          log.info("The \"conll2007\" and \"conllStyleDependencies\" formats are ignored in xml.");
        }
        if (formats.containsKey("typedDependencies")) {
          GrammaticalStructure gs = gsf.newGrammaticalStructure(outputTree);
          if (basicDependencies) {
            print(gs.typedDependencies(), "xml", includeTags, pw);
          }
          if (nonCollapsedDependencies || nonCollapsedDependenciesSeparated) {
            print(gs.allTypedDependencies(), "xml", includeTags, pw);
          }
          if (collapsedDependencies) {
            print(gs.typedDependenciesCollapsed(GrammaticalStructure.Extras.MAXIMAL), "xml", includeTags, pw);
          }
          if (CCPropagatedDependencies) {
            print(gs.typedDependenciesCCprocessed(), "xml", includeTags, pw);
          }
          if(treeDependencies) {
            print(gs.typedDependenciesCollapsedTree(), "xml", includeTags, pw);
          }
        }
        if (formats.containsKey("typedDependenciesCollapsed")) {
          GrammaticalStructure gs = gsf.newGrammaticalStructure(outputTree);
          print(gs.typedDependenciesCCprocessed(), "xml", includeTags, pw);
        }
  
        // This makes parser require jgrapht.  Bad.
        // if (formats.containsKey("semanticGraph")) {
        //  SemanticGraph sg = SemanticGraph.makeFromTree(outputTree, true, false, false, null);
        //  pw.println(sg.toFormattedString());
        // }
      } else {
        // non-XML printing
        if (formats.containsKey("wordsAndTags")) {
          pw.println(SentenceUtils.listToString(outputTree.taggedYield(), false));
          pw.println();
        }
        if (formats.containsKey("oneline")) {
          pw.println(outputPSTree.toString());
        }
        if (formats.containsKey("penn")) {
          outputPSTree.pennPrint(pw);
          pw.println();
        }
        if (formats.containsKey(rootLabelOnlyFormat)) {
          pw.println(outputTree.label().value());
        }
        if (formats.containsKey("latexTree")) {
          pw.println(".[");
          outputTree.indentedListPrint(pw,false);
          pw.println(".]");
        }
        if (formats.containsKey("xmlTree")) {
          outputTree.indentedXMLPrint(pw,false);
        }
        if (formats.containsKey("dependencies")) {
          Tree indexedTree = outputTree.deepCopy(outputTree.treeFactory());
          indexedTree.indexLeaves();
          List<Dependency<Label, Label, Object>> sortedDeps = getSortedDeps(indexedTree, dependencyWordFilter);
          for (Dependency<Label, Label, Object> d : sortedDeps) {
            pw.println(d.toString("predicate"));
          }
          pw.println();
        }
        if (formats.containsKey("conll2007")) {
          // CoNLL-X 2007 format: http://ilk.uvt.nl/conll/#dataformat
          // wsg: This code should be retained (and not subsumed into EnglishGrammaticalStructure) so
          //      that dependencies for other languages can be printed.
          // wsg2011: This code currently ignores the dependency label since the present implementation
          //          of mapDependencies() returns UnnamedDependency objects.
          // TODO: if there is a GrammaticalStructureFactory available, use that instead of mapDependencies
          Tree it = outputTree.deepCopy(outputTree.treeFactory(), CoreLabel.factory());
          it.indexLeaves();
  
          List<CoreLabel> tagged = it.taggedLabeledYield();
          List<Dependency<Label, Label, Object>> sortedDeps = getSortedDeps(it, Filters.<Dependency<Label, Label, Object>>acceptFilter());
  
          for (Dependency<Label, Label, Object> d : sortedDeps) {
            if (!dependencyFilter.test(d)) {
              continue;
            }
            if (!(d.dependent() instanceof HasIndex) || !(d.governor() instanceof HasIndex)) {
              throw new IllegalArgumentException("Expected labels to have indices");
            }
            HasIndex dep = (HasIndex) d.dependent();
            HasIndex gov = (HasIndex) d.governor();
  
            int depi = dep.index();
            int govi = gov.index();
  
            CoreLabel w = tagged.get(depi - 1);
  
            // Used for both course and fine POS tag fields
            String tag = PTBTokenizer.ptbToken2Text(w.tag());
  
            String word = PTBTokenizer.ptbToken2Text(w.word());
            String lemma = "_";
            String feats = "_";
            String pHead = "_";
            String pDepRel = "_";
            String depRel;
            if (d.name() != null) {
  