class Ecu::LabParser

def add_header(str)

def add_header(str)
  @headers << str[1..].strip
end

def add_property(str)

def add_property(str)
  case @properties
  in { task:, description: } then @properties[:description] << " " << str
  in { task:               } then @properties[:description] = str.strip
  in { **                  } then @properties[:task] = str.split("&").first
  end
end

def add_subheader(str)

def add_subheader(str)
  @subheaders << str[1..].strip
end

def call

def call
  while tok = lexer.next_token(state)
    begin
      case state
      in :NO_SECTION
        case tok
        in :SETTINGS_HEADER then next_state(:SETTINGS)
        in :SIGNALS_HEADER  then next_state(:SIGNALS)
        in :LABELS_HEADER   then next_state(:LABELS)
        in :COMMENT         then add_header(lexer.token_value)
        in :NEWLINE         then # noop
        end
      in :SETTINGS
        case tok
        in :SIGNALS_HEADER then next_state(:SIGNALS)
        in :LABELS_HEADER  then next_state(:LABELS)
        in :COMMENT        then add_subheader(lexer.token_value)
        in :STRING         then # save that shit?
        in :SEPARATOR      then # now comes the value
        in :NEWLINE        then # next setting
        end
      in :LABELS
        case tok
        in :SIGNALS_HEADER then next_state(:SIGNALS)
        in :STRING         then start_label(lexer.token_value)
        in :COMMENT        then # noop
        in :NEWLINE        then # noop
        end
      in :SIGNALS
        case tok
        in :LABELS_HEADER  then next_state(:LABELS)
        in :STRING         then start_signal(lexer.token_value)
        in :COMMENT        then # noop
        in :NEWLINE        then # noop
        end
      in :LABEL
        case tok
        in :NEWLINE        then labels << finish_label
        in :SEPARATOR      then # noop, sometimes used as end separator
        end
      in :SIGNAL
        case tok
        in :STRING         then add_property(lexer.token_value)
        in :SEPARATOR      then # noop, next property
        in :NEWLINE        then signals << finish_signal
        end
      end
    rescue NoMatchingPatternError => e
      raise LabParserError.new("Unexpected token #{debug_token(tok)} (state: #{state})", lexer)
    rescue StandardError => e
      raise LabParserError.new("#{e.message} (state: #{@state})", lexer)
    end
  end
  [signals, labels, headers, subheaders]
end

def debug_token(tok)

def debug_token(tok)
  "#{tok}: \"#{lexer.token_value}\" - #{@properties.inspect}"
end

def finish_label

def finish_label
  Festwert.new(**@properties, value: nil).tap do
    reset_entry!
    next_state(:LABELS)
  end
end

def finish_signal

def finish_signal
  Signal.new(**@properties).tap do
    reset_entry!
    next_state(:SIGNALS)
  end
end

def initialize(doc)

def initialize(doc)
  @lexer      = LabLexer.new(doc)
  @state      = :NO_SECTION
  @signals    = []
  @labels     = []
  @headers    = []
  @subheaders = []
  reset_entry!
end

def next_state(newstate)

def next_state(newstate)
  @state = newstate
  yield if block_given?
end

def reset_entry!

def reset_entry!
  @properties = {}
end

def start_label(name)

def start_label(name)
  next_state(:LABEL) do
    @properties[:name] = name
  end
end

def start_signal(name)

def start_signal(name)
  next_state(:SIGNAL) do
    @properties[:name] = name
  end
end