defmodule Slime.Parser do @moduledoc """ Build a Slime tree from a Slime document. """ alias Slime.Parser.Preprocessor alias Slime.TemplateSyntaxError def parse(""), do: [] def parse(input) do indented_input = Preprocessor.process(input) case :slime_parser.parse(indented_input) do {:fail, error} -> raise TemplateSyntaxError, syntax_error(input, indented_input, error) tokens -> tokens end end defp syntax_error(input, indented_input, error) do {_reason, error, {{:line, line}, {:column, column}}} = error indented_line = indented_input |> String.split("\n") |> Enum.at(line - 1) input_line = input |> String.split("\n") |> Enum.at(line - 1) indent = Preprocessor.indent_meta_symbol() column = case indented_line do <<^indent::binary-size(1), _::binary>> -> column - 1 _ -> column end dedent = Preprocessor.dedent_meta_symbol() message = case error do {:no_match, ^indent} -> "Unexpected indent" {:no_match, ^dedent} -> "Unexpected dedent" {:no_match, symbol} -> "Unexpected symbol '#{symbol}'" _ -> inspect(error) end [ line: input_line, message: message, line_number: line, column: column ] end end