module <%= @name %>
  extend self
  # This is the kind of thing which is:
  # - initially passed to `consume`
  # - passed to each
  alias Accumulator = <%= @accumulator %>
  # When we finish a pattern, we call its corresponding action.
  # The action should modify `Accumulator`.
  # The first `int` is the beginning index of the current pattern.
  # The second `int` is the ending index of the current pattern.
  alias Action = Proc(Accumulator, String, Int32, Int32, Nil)

  # Work through `input` according to this machine,
  # passing `acc` to each action. `acc` will be modified in-place
  # since this method returns nil.
  #
  # If there's a scanning error, an error is raised.
  <%= @consume_method %>

  def scan(input : String) : Accumulator
    acc = Accumulator.new
    consume(input, acc)
    acc
  end

  # An automaton built from the specified patterns
  TABLE = {
<% table.table.each do |start, transitions| %>    <%= start %> => {<% transitions.each do |char, end_state| %>
      <%= char ? char.inspect : "nil" %> => <%= end_state %>,<% end %>
    },
<% end %>  }

  # A map of state => Action pairs to call when machines are finished
  ACTIONS = {
<% @actions.each do |name, pattern, body| terminals = table.ending_states[name]; terminals.each do |terminal_state| %>    <%= terminal_state %> => Action.new <%= body %>,
<% end %><% end %>  }


  class Error < Exception
  end
  class UnexpectedEndError < Error
    getter position
    def initialize(position : Int32)
      @position = position
      super("Unexpected EOS")
    end
  end
  class UnexpectedInputError < Error
    getter char
    getter position
    def initialize(char : Char, position : Int32)
      @char = char
      @position = position
      super("Unexpected input: '#{char}'")
    end
  end
end
