class Haml::Parser
def call(template)
def call(template) 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 end