Skip to content

Commit

Permalink
Show parsing errors with line and column number
Browse files Browse the repository at this point in the history
  • Loading branch information
Rakoth committed Apr 21, 2017
1 parent 4acaf9b commit 8f7288c
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 20 deletions.
11 changes: 10 additions & 1 deletion lib/slime.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@ defmodule Slime do
@moduledoc """
Syntax exception which may appear during parsing and compilation processes
"""
defexception message: "Syntax error in slime file"
defexception [:line, :line_number, :column, message: "Syntax error", source: "INPUT"]

def message(exception) do
"""
#{exception.message}
#{exception.source}, Line #{exception.line_number}, Column #{exception.column}
#{exception.line}
#{String.duplicate(" ", exception.column - 1)}^
"""
end
end

defdelegate render(slime), to: Renderer
Expand Down
20 changes: 17 additions & 3 deletions lib/slime/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,27 @@ defmodule Slime.Parser do
def parse(input) do
indented_input = Preprocessor.indent(input)
case :slime_parser.parse(indented_input) do
# TODO: Map column index to original input, handle errors on indent and dedent
{:fail, error} ->
raise TemplateSyntaxError, "Parsing Error: #{inspect error}\n#{input}"
{:fail, error} -> handle_syntax_error(input, indented_input, error)
tokens -> tokens
end
end

defp handle_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
raise TemplateSyntaxError,
line: input_line,
message: inspect(error),
line_number: line,
column: column
end

@content "|"
@comment "/"
@html "<"
Expand Down
20 changes: 6 additions & 14 deletions lib/slime/parser/preprocessor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,7 @@ defmodule Slime.Parser.Preprocessor do
@moduledoc """
This module helps to process input and insert indents and dedents to simplify parser design.
"""

defmodule IndentationError do
defexception [:line, :line_number, :indent, message: "Malformed indentation"]

def message(exception) do
"""
#{exception.message}
INPUT, Line #{exception.line_number}, Column #{exception.indent}
#{exception.line}
#{String.duplicate(" ", exception.indent)}^
"""
end
end
alias Slime.TemplateSyntaxError

@indent "\x0E"
@dedent "\x0F"
Expand Down Expand Up @@ -62,7 +50,11 @@ defmodule Slime.Parser.Preprocessor do
[prev_line | result] = result
{stack, [line, prev_line <> dedents | result]}
else
raise IndentationError, line: line, line_number: Enum.count(result) + 1, indent: indent
raise TemplateSyntaxError,
message: "Malformed indentation",
line: line,
line_number: Enum.count(result) + 1,
column: indent
end
end

Expand Down
4 changes: 2 additions & 2 deletions test/parser/preprocessor_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Slime.Parser.PreprocessorTest do
use ExUnit.Case
alias Slime.Parser.Preprocessor
alias Preprocessor.IndentationError
alias Slime.TemplateSyntaxError

doctest Preprocessor

Expand All @@ -16,7 +16,7 @@ defmodule Slime.Parser.PreprocessorTest do
| test
"""

assert_raise(IndentationError, fn -> Preprocessor.indent(slime) end)
assert_raise(TemplateSyntaxError, fn -> Preprocessor.indent(slime) end)
end

test "skip indents in embedded engine lines" do
Expand Down

0 comments on commit 8f7288c

Please sign in to comment.