Returns the valid actions in the current grammar state.  See the class docstring for a
        description of what we're returning here.

def get_valid_actions(self) -> Dict[str, Tuple[torch.Tensor, torch.Tensor, List[int]]]:
        """
        Returns the valid actions in the current grammar state.  See the class docstring for a
        description of what we're returning here.
        """
        actions = self._valid_actions[self._nonterminal_stack[-1]]
        context_actions = []
        for type_, variable in self._lambda_stacks:
            if self._nonterminal_stack[-1] == type_:
                production_string = f"{type_} -> {variable}"
                context_actions.append(self._context_actions[production_string])
        if context_actions:
            input_tensor, output_tensor, action_ids = actions['global']
            new_inputs = [input_tensor] + [x[0] for x in context_actions]
            input_tensor = torch.cat(new_inputs, dim=0)
            new_outputs = [output_tensor] + [x[1] for x in context_actions]
            output_tensor = torch.cat(new_outputs, dim=0)
            new_action_ids = action_ids + [x[2] for x in context_actions]
            # We can't just reassign to actions['global'], because that would modify the state of
            # self._valid_actions.  Instead, we need to construct a new actions dictionary.
            new_actions = {**actions}
            new_actions['global'] = (input_tensor, output_tensor, new_action_ids)
            actions = new_actions
        return actions