code: def raw_tree(text):
      """
      A sentence will look like this:
         #ID=sent_00001  fc-[f3-[sn-[art-le, n-infrastrutture, sc-[ccom-come, sn-[n-fattore, spd-[pd-di,
                         sn-[n-competitività]]]]]], f3-[spd-[pd-di, sn-[mw-Angela, nh-Airoldi]]], punto-.]
      Non-preterminal nodes have tags, followed by the stuff under the node, -[
      The node is closed by the ]
      """
      pieces = []
      open_pieces = text.split(OPEN)
      for open_idx, open_piece in enumerate(open_pieces):
          if open_idx > 0:
              pieces[-1] = pieces[-1] + OPEN
          open_piece = open_piece.strip()
          if not open_piece:
              raise ValueError("Unexpected empty node!")
          close_pieces = open_piece.split(CLOSE)
          for close_idx, close_piece in enumerate(close_pieces):
              if close_idx > 0:
                  pieces.append(CLOSE)
              close_piece = close_piece.strip()
              if not close_piece:
                  # this is okay - multiple closes at the end of a deep bracket
                  continue
              word_pieces = close_piece.split(", ")
              pieces.extend(
                  [x.strip() for x in word_pieces if x.strip()]
              )
  
      # at this point, pieces is a list with:
      #   tag-[     for opens
      #   tag-word  for words
      #   ]         for closes
      # this structure converts pretty well to reading using the tree reader
  
      PIECE_MAPPING = {
          "agn-/ter'": "(agn ter)",
          "cong-'&'": "(cong &)",
          "da_riempire-'...'": "(da_riempire ...)",
          "date-1992_1993": "(date 1992/1993)",
          "date-'31-12-95'": "(date 31-12-95)",
          "date-'novantaquattro-95'": "(date novantaquattro-95)",
          "date-'novantaquattro-95": "(date novantaquattro-95)",
          "date-'novantaquattro-novantacinque'": "(date novantaquattro-novantacinque)",
          "dirs-':'": "(dirs :)",
          "dirs-'\"'": '(dirs ")',
          "mw-'&'": "(mw &)",
          "mw-'Presunto'": "(mw Presunto)",
          "nh-'Alain-Gauze'": "(nh Alain-Gauze)",
          "np-'porto_Marghera'": "(np Porto) (np Marghera)",
          "np-'roma-l_aquila'": "(np Roma-L'Aquila)",
          "np-'L_Aquila-Villa_Vomano'": "(np L'Aquila) (np -) (np Villa) (np Vomano)",
          "npro-'Avanti_!'": "(npro Avanti_!)",
          "npro-'Viacom-Paramount'": "(npro Viacom-Paramount)",
          "npro-'Rhone-Poulenc'": "(npro Rhone-Poulenc)",
          "npro-'Itar-Tass'": "(npro Itar-Tass)",
          "par-(-)": "(par -)",
          "par-','": "(par ,)",
          "par-'<'": "(par <)",
          "par-'>'": "(par >)",
          "par-'-'": "(par -)",
          "par-'\"'": '(par ")',
          "par-'('": "(par -LRB-)",
          "par-')'": "(par -RRB-)",
          "par-'&&'": "(par &&)",
          "punt-','": "(punt ,)",
          "punt-'-'": "(punt -)",
          "punt-';'": "(punt ;)",
          "punto-':'": "(punto :)",
          "punto-';'": "(punto ;)",
          "puntint-'!'": "(puntint !)",
          "puntint-'?'": "(puntint !)",
          "num-'2plus2'": "(num 2+2)",
          "num-/bis'": "(num bis)",
          "num-/ter'": "(num ter)",
          "num-18_00/1_00": "(num 18:00/1:00)",
          "num-1/500_2/000": "(num 1.500-2.000)",
          "num-16_1": "(num 16,1)",
          "num-0_1": "(num 0,1)",
          "num-0_3": "(num 0,3)",
          "num-2_7": "(num 2,7)",
          "num-455_68": "(num 455/68)",
          "num-437_5": "(num 437,5)",
          "num-4708_82": "(num 4708,82)",
          "num-16EQ517_7": "(num 16EQ517/7)",
          "num-2=184_90": "(num 2=184/90)",
          "num-3EQ429_20": "(num 3eq429/20)",
          "num-'1990-EQU-100'": "(num 1990-EQU-100)",
          "num-'500-EQU-250'": "(num 500-EQU-250)",
          "num-0_39%minus": "(num 0,39%-)",
          "num-1_88/76": "(num 1-88/76)",
          "num-'70/80'": "(num 70,80)",
          "num-'18/20'": "(num 18:20)",
          "num-295/mila'": "(num 295mila)",
          "num-'295/mila'": "(num 295mila)",
          "num-0/07%plus": "(num 0,07%) (num plus)",
          "num-0/69%minus": "(num 0,69%) (num minus)",
          "num-0_39%minus": "(num 0,39%) (num minus)",
          "num-9_11/16": "(num 9-11,16)",
          "num-2/184_90": "(num 2=184/90)",
          "num-3/429_20": "(num 3eq429/20)",
          # TODO: remove the following num conversions if possible
          # this would require editing either constituency or UD
          "num-1:28_124": "(num 1=8/1242)",
          "num-1:28_397": "(num 1=8/3972)",
          "num-1:28_947": "(num 1=8/9472)",
          "num-1:29_657": "(num 1=9/6572)",
          "num-1:29_867": "(num 1=9/8672)",
          "num-1:29_874": "(num 1=9/8742)",
          "num-1:30_083": "(num 1=0/0833)",
          "num-1:30_140": "(num 1=0/1403)",
          "num-1:30_354": "(num 1=0/3543)",
          "num-1:30_453": "(num 1=0/4533)",
          "num-1:30_946": "(num 1=0/9463)",
          "num-1:31_602": "(num 1=1/6023)",
          "num-1:31_842": "(num 1=1/8423)",
          "num-1:32_087": "(num 1=2/0873)",
          "num-1:32_259": "(num 1=2/2593)",
          "num-1:33_166": "(num 1=3/1663)",
          "num-1:34_154": "(num 1=4/1543)",
          "num-1:34_556": "(num 1=4/5563)",
          "num-1:35_323": "(num 1=5/3233)",
          "num-1:36_023": "(num 1=6/0233)",
          "num-1:36_076": "(num 1=6/0763)",
          "num-1:36_651": "(num 1=6/6513)",
          "n-giga_flop/s": "(n giga_flop/s)",
          "sect-'g-1'": "(sect g-1)",
          "sect-'h-1'": "(sect h-1)",
          "sect-'h-2'": "(sect h-2)",
          "sect-'h-3'": "(sect h-3)",
          "abbr-'a-b-c'": "(abbr a-b-c)",
          "abbr-d_o_a_": "(abbr DOA)",
          "abbr-d_l_": "(abbr DL)",
          "abbr-i_s_e_f_": "(abbr ISEF)",
          "abbr-d_p_r_": "(abbr DPR)",
          "abbr-D_P_R_": "(abbr DPR)",
          "abbr-d_m_": "(abbr dm)",
          "abbr-T_U_": "(abbr TU)",
          "abbr-F_A_M_E_": "(abbr Fame)",
          "dots-'...'": "(dots ...)",
      }
      new_pieces = ["(ROOT "]
      for piece in pieces:
          if piece.endswith(OPEN):
              new_pieces.append("(" + piece[:-2])
          elif piece == CLOSE:
              new_pieces.append(")")
          elif piece in PIECE_MAPPING:
              new_pieces.append(PIECE_MAPPING[piece])
          else:
              # maxsplit=1 because of words like 1990-EQU-100
              tag, word = piece.split("-", maxsplit=1)
              if (
                  word.find("'") >= 0
                  or word.find("(") >= 0
                  or word.find(")") >= 0
              ):
                  raise ValueError(
                      "Unhandled weird node: {}".format(piece)
                  )
              if word.endswith("_"):
                  word = word[:-1] + "'"
              date_match = DATE_RE.match(word)
              if date_match:
                  # 10_30 special case sent_07072
                  # 16_30 special case sent_07098
                  # 21_15 special case sent_07099 and others
                  word = date_match.group(1) + ":" + date_match.group(2)
              percent = PERCENT_RE.match(word)
              if percent:
                  word = percent.group(1) + "," + percent.group(2)
              decimal = DECIMAL_RE.match(word)
              if decimal:
                  word = decimal.group(1) + "," + decimal.group(2)
              # there are words which are multiple words mashed together
              # with _ for some reason
              # also, words which end in ' are replaced with _
              # fortunately, no words seem to have both
              # splitting like this means the tags are likely wrong,
              # but the conparser needs to retag anyway, so it shouldn't matter
              word_pieces = word.split("_")
              for word_piece in word_pieces:
                  new_pieces.append("(%s %s)" % (tag, word_piece))
      new_pieces.append(")")
  
      text = " ".join(new_pieces)
      trees = read_trees(text)
      if len(trees) > 1:
          raise ValueError("Unexpected number of trees!")
      return trees[0]
  
imports: from collections import defaultdict, deque, namedtuple
  import itertools
  import os
  import re
  import sys
  from tqdm import tqdm
  from stanza.models.constituency.tree_reader import read_trees, UnclosedTreeError, ExtraCloseTreeError
  from stanza.server import tsurgeon
  from stanza.utils.conll import CoNLL
  from stanza.utils.datasets.constituency.utils import SHARDS, write_dataset
  import stanza.utils.default_paths
label_desc: Use image node_id 3 for calling a global function with example usage: raw_tree(text) and returns: trees