class Racc::LogFileGenerator

def action_out(f, state)

def action_out(f, state)
  sr = state.srconf && state.srconf.dup
  rr = state.rrconf && state.rrconf.dup
  acts = state.action
  keys = acts.keys
  keys.sort! {|a,b| a.ident <=> b.ident }
  [ Shift, Reduce, Error, Accept ].each do |klass|
    keys.delete_if do |tok|
      act = acts[tok]
      if act.kind_of?(klass)
        outact f, tok, act
        if sr and c = sr.delete(tok)
          outsrconf f, c
        end
        if rr and c = rr.delete(tok)
          outrrconf f, c
        end
        true
      else
        false
      end
    end
  end
  sr.each {|tok, c| outsrconf f, c } if sr
  rr.each {|tok, c| outrrconf f, c } if rr
  act = state.defact
  if not act.kind_of?(Error) or @debug_flags.any?
    outact f, '$default', act
  end
  f.puts
  state.goto_table.each do |t, st|
    if t.nonterminal?
      f.printf "  %-12s  go to state %d\n", t.to_s, st.ident
    end
  end
end

def initialize(states, debug_flags = DebugFlags.new)

def initialize(states, debug_flags = DebugFlags.new)
  @states = states
  @grammar = states.grammar
  @debug_flags = debug_flags
end

def outact(f, t, act)

def outact(f, t, act)
  case act
  when Shift
    f.printf "  %-12s  shift, and go to state %d\n",
             t.to_s, act.goto_id
  when Reduce
    f.printf "  %-12s  reduce using rule %d (%s)\n",
             t.to_s, act.ruleid, act.rule.target.to_s
  when Accept
    f.printf "  %-12s  accept\n", t.to_s
  when Error
    f.printf "  %-12s  error\n", t.to_s
  else
    raise "racc: fatal: wrong act for outact: act=#{act}(#{act.class})"
  end
end

def output(out)

def output(out)
  output_conflict out; out.puts
  output_useless  out; out.puts
  output_rule     out; out.puts
  output_token    out; out.puts
  output_state    out
end

def output_conflict(out)

def output_conflict(out)
  @states.each do |state|
    if state.srconf
      out.printf "state %d contains %d shift/reduce conflicts\n",
                 state.stateid, state.srconf.size
    end
    if state.rrconf
      out.printf "state %d contains %d reduce/reduce conflicts\n",
                 state.stateid, state.rrconf.size
    end
  end
end

def output_rule(out)

def output_rule(out)
  out.print "-------- Grammar --------\n\n"
  @grammar.each do |rl|
    if @debug_flags.any? or rl.ident != 0
      out.printf "rule %d %s: %s\n",
                 rl.ident, rl.target.to_s, rl.symbols.join(' ')
    end
  end
end

def output_state(out)

def output_state(out)
  out << "--------- State ---------\n"
  showall = @debug_flags.la || @debug_flags.state
  @states.each do |state|
    out << "\nstate #{state.ident}\n\n"
    (showall ? state.closure : state.core).each do |ptr|
      pointer_out(out, ptr) if ptr.rule.ident != 0 or showall
    end
    out << "\n"
    action_out out, state
  end
end

def output_token(out)

def output_token(out)
  out.print "------- Symbols -------\n\n"
  out.print "**Nonterminals, with rules where they appear\n\n"
  @grammar.each_nonterminal do |t|
    tmp = <<SRC
 (%d)
on right: %s
on left : %s
    out.printf tmp, t.to_s, t.ident,
               symbol_locations(t.locate).join(' '),
               symbol_locations(t.heads).join(' ')
  end
  out.print "\n**Terminals, with rules where they appear\n\n"
  @grammar.each_terminal do |t|
    out.printf "  %s (%d) %s\n",
               t.to_s, t.ident, symbol_locations(t.locate).join(' ')
  end
end

def output_useless(out)

def output_useless(out)
  @grammar.each do |rl|
    if rl.useless?
      out.printf "rule %d (%s) never reduced\n",
                 rl.ident, rl.target.to_s
    end
  end
  @grammar.each_nonterminal do |t|
    if t.useless?
      out.printf "useless nonterminal %s\n", t.to_s
    end
  end
end

def outrrconf(f, confs)

def outrrconf(f, confs)
  confs.each do |c|
    r = c.low_prec
    f.printf "  %-12s  [reduce using rule %d (%s)]\n",
             c.token.to_s, r.ident, r.target.to_s
  end
end

def outsrconf(f, confs)

def outsrconf(f, confs)
  confs.each do |c|
    r = c.reduce
    f.printf "  %-12s  [reduce using rule %d (%s)]\n",
             c.shift.to_s, r.ident, r.target.to_s
  end
end

def pointer_out(out, ptr)

def pointer_out(out, ptr)
  buf = sprintf("%4d) %s :", ptr.rule.ident, ptr.rule.target.to_s)
  ptr.rule.symbols.each_with_index do |tok, idx|
    buf << ' _' if idx == ptr.index
    buf << ' ' << tok.to_s
  end
  buf << ' _' if ptr.reduce?
  out.puts buf
end

def symbol_locations(locs)

def symbol_locations(locs)
  locs.map {|loc| loc.rule.ident }.reject {|n| n == 0 }.uniq
end