in pytext/data/data_structures/annotation.py [0:0]
def build_tree(self, accept_flat_intents_slots: bool = False):
root = Root()
node_stack: List[Any] = [root]
curr_chars: List[str] = []
token_count = 0
expecting_label = False
it = iter(self.seqlogical)
while True:
char = next(it, None)
if char is None:
break
if char.isspace() or char in (OPEN, CLOSE):
if curr_chars:
word = "".join(curr_chars)
curr_chars = []
parent = node_stack[-1]
if expecting_label:
if word.startswith(INTENT_PREFIX):
node: Union[Intent, Slot, Token] = Intent(word)
elif word.startswith(SLOT_PREFIX):
node = Slot(word)
elif word == OOD_TOKEN:
node = Intent(word)
elif accept_flat_intents_slots:
# Temporary, for compatibility with flat annotations that
# does not contain IN:, SL: prefixes. This assumes any child
# of ROOT or SLOT must be INTENT, and any child of INTENT
# must be SLOT.
if isinstance(parent, (Root, Slot)):
node = Intent(word)
elif isinstance(parent, Intent):
node = Slot(word)
else:
raise ValueError(
"The previous node in node_stack is not of type "
"Root, Intent or Slot."
)
else:
raise ValueError(f"Label {word} must start with IN: or SL:")
node_stack.append(node)
expecting_label = False
else:
if isinstance(parent, Root):
raise ValueError("Root cannot have a Token as child.")
node = Token(word, token_count)
token_count += 1
parent.children.append(node)
node.parent = parent
if char in (OPEN, CLOSE):
if expecting_label:
raise ValueError("Invalid tree. No label found after '['.")
if char == OPEN:
expecting_label = True
else:
node_stack.pop()
else:
if char == ESCAPE:
char = next(it, None)
if char not in (OPEN, CLOSE, ESCAPE):
raise ValueError(
f"Escape '{ESCAPE}' followed by none of '{OPEN}', "
f"'{CLOSE}', or '{ESCAPE}'."
)
curr_chars.append(char)
if len(node_stack) != 1:
raise ValueError("Invalid tree.")
if len(root.children) > 1 and self.combination_labels:
comb_intent = Intent(COMBINATION_INTENT_LABEL)
node_stack.insert(1, comb_intent)
for child in root.children:
if type(child) == Intent:
comb_slot = Slot(COMBINATION_SLOT_LABEL)
comb_slot.parent = comb_intent
comb_slot.children.append(child)
comb_intent.children.append(comb_slot)
child.parent = comb_slot
else:
child.parent = comb_intent
comb_intent.children.append(child)
comb_intent.parent = root
root.children = [comb_intent]
return root