def actions_to_reach_reduce(state_idx, target)
      rule = target.heads.map(&:rule).min_by do |r|
        r.symbols.flat_map(&:shortest_production).size
      end

      actions, cur_state = [], state_idx
      rule.symbols.each do |sym|
        if sym.terminal?
          actions << sym
        else
          actions.concat(actions_to_reach_reduce(cur_state, sym))
        end
        cur_state = transition_graph[cur_state][sym]
      end
      cur_state = transition_graph[state_idx][target]

      actions << ReduceStep.new(state_idx, cur_state, rule, target)
    end
def actions_to_reach_reduce(state_idx, target)
      rule = target.heads.map(&:rule).min_by do |r|
        r.symbols.flat_map(&:shortest_production).size
      end

      actions, cur_state = [], state_idx
      rule.symbols.each do |sym|
        if sym.terminal?
          actions << sym
        else
          actions.concat(actions_to_reach_reduce(cur_state, sym))
        end
        cur_state = transition_graph[cur_state][sym]
      end
      cur_state = transition_graph[state_idx][target]

      actions << ReduceStep.new(state_idx, cur_state, rule, target)
    end
What series of shifts/reduces can produce `target`, starting from state
 `state_idx`?