class Haml::Parser

def call(template)

def call(template)
  template = Haml::Util.check_haml_encoding(template) do |msg, line|
    raise Haml::Error.new(msg, line)
  end
  match = template.rstrip.scan(/(([ \t]+)?(.*?))(?:\Z|\r\n|\r|\n)/m)
  # discard the last match which is always blank
  match.pop
  @template = match.each_with_index.map do |(full, whitespace, text), index|
    Line.new(whitespace, text.rstrip, full, index, self, false)
  end
  # Append special end-of-document marker
  @template << Line.new(nil, '-#', '-#', @template.size, self, true)
  @root = @parent = ParseNode.new(:root)
  @flat = false
  @filter_buffer = nil
  @indentation = nil
  @line = next_line
  raise SyntaxError.new(Error.message(:indenting_at_start), @line.index) if @line.tabs != 0
  loop do
    next_line
    process_indent(@line) unless @line.text.empty?
    if flat?
      text = @line.full.dup
      text = "" unless text.gsub!(/^#{@flat_spaces}/, '')
      @filter_buffer << "#{text}\n"
      @line = @next_line
      next
    end
    @tab_up = nil
    process_line(@line) unless @line.text.empty?
    if block_opened? || @tab_up
      @template_tabs += 1
      @parent = @parent.children.last
    end
    if !flat? && @next_line.tabs - @line.tabs > 1
      raise SyntaxError.new(Error.message(:deeper_indenting, @next_line.tabs - @line.tabs), @next_line.index)
    end
    @line = @next_line
  end
  # Close all the open tags
  close until @parent.type == :root
  @root
rescue Haml::Error => e
  e.backtrace.unshift "#{@options.filename}:#{(e.line ? e.line + 1 : @line.index + 1) + @options.line - 1}"
  raise if @raise_error
  error_with_lineno(e)
end