Skip to content

Commit b6bbdb4

Browse files
authored
fix: parsing crashes on code with errors (#65)
1 parent 0513a5d commit b6bbdb4

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

lib/spitfire.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ defmodule Spitfire do
212212
peek_token(parser) in [:eol, :";", :eof] and parser.tokens != :eot ->
213213
next_token(parser)
214214

215+
current_token(parser) in [:")", :"]", :"}", :">>"] ->
216+
next_token(parser)
217+
218+
peek_token(parser) in [:")", :"]", :"}", :">>"] ->
219+
next_token(parser)
220+
215221
true ->
216222
parser
217223
end

test/spitfire_test.exs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2646,7 +2646,6 @@ defmodule SpitfireTest do
26462646
{{:., [line: 5, column: 37], [{:state, [line: 5, column: 32], nil}, :baz]},
26472647
[no_parens: true, line: 5, column: 38], []}
26482648
]},
2649-
{:__block__, [error: true, line: 5, column: 41], []},
26502649
{:__block__,
26512650
[
26522651
end_of_expression: [newlines: 1, line: 5, column: 43],
@@ -2658,7 +2657,6 @@ defmodule SpitfireTest do
26582657
[
26592658
{[line: 2, column: 8], "missing closing brace for map"},
26602659
{[line: 4, column: 1], "unknown token: ,"},
2661-
{[line: 5, column: 41], "unknown token: )"},
26622660
{[line: 5, column: 42], "unknown token: }"}
26632661
]}
26642662
end
@@ -3104,6 +3102,59 @@ defmodule SpitfireTest do
31043102
{[line: 1, column: 16], "missing closing brace for struct %__MODULE__"}
31053103
]} == Spitfire.parse("%__MODULE__ a: 1")
31063104
end
3105+
3106+
test "stray closing delimiter after identifier" do
3107+
assert {:error, {:__block__, [], [{:x, _, nil}, {:__block__, [error: true, line: 1, column: 3], []}]},
3108+
[{[line: 1, column: 3], "unknown token: ]"}]} = Spitfire.parse("x ]")
3109+
3110+
assert {:error, {:__block__, [], [{:x, _, nil}, {:__block__, [error: true, line: 1, column: 3], []}]},
3111+
[{[line: 1, column: 3], "unknown token: }"}]} = Spitfire.parse("x }")
3112+
3113+
assert {:error, {:__block__, [], [{:x, _, nil}, {:__block__, [error: true, line: 1, column: 3], []}]},
3114+
[{[line: 1, column: 3], "unknown token: )"}]} = Spitfire.parse("x )")
3115+
3116+
assert {:error, {:__block__, [], [{:@, _, [{:x, _, nil}]}, {:__block__, [error: true, line: 1, column: 4], []}]},
3117+
[{[line: 1, column: 4], "unknown token: ]"}]} = Spitfire.parse("@x ]")
3118+
3119+
assert {:error, {:__block__, [], [1, {:__block__, [error: true, line: 1, column: 3], []}]},
3120+
[{[line: 1, column: 3], "unknown token: ]"}]} = Spitfire.parse("1 ]")
3121+
3122+
assert {:error, _ast, [{[line: 1, column: 3], "unknown token: ]"}, {[line: 1, column: 5], "unknown token: }"}]} =
3123+
Spitfire.parse("x ] }")
3124+
3125+
code = """
3126+
x]
3127+
3128+
foo = Foo.bar(42)
3129+
"""
3130+
3131+
assert {:error,
3132+
{:__block__, [],
3133+
[
3134+
{:x, _, nil},
3135+
{:__block__, [end_of_expression: _, error: true, line: 1, column: 2], []},
3136+
{:=, _, [{:foo, _, nil}, {{:., _, [{:__aliases__, _, [:Foo]}, :bar]}, _, [42]}]}
3137+
]}, [{[line: 1, column: 2], "unknown token: ]"}]} = Spitfire.parse(code)
3138+
end
3139+
3140+
test "stray closing delimiter after complete expression" do
3141+
assert {:error,
3142+
{:__block__, [],
3143+
[
3144+
{:foo, [closing: [line: 1, column: 5], line: 1, column: 1], []},
3145+
{:__block__, [error: true, line: 1, column: 6], []}
3146+
]}, [{[line: 1, column: 6], "unknown token: }"}]} = Spitfire.parse("foo()}")
3147+
3148+
assert {:error, {:__block__, [], [[1, 2], {:__block__, [error: true, line: 1, column: 7], []}]},
3149+
[{[line: 1, column: 7], "unknown token: }"}]} = Spitfire.parse("[1, 2]}")
3150+
3151+
assert {:error,
3152+
{:__block__, [],
3153+
[
3154+
{:%{}, [closing: [line: 1, column: 7], line: 1, column: 1], [a: 1]},
3155+
{:__block__, [error: true, line: 1, column: 8], []}
3156+
]}, [{[line: 1, column: 8], "unknown token: )"}]} = Spitfire.parse("%{a: 1})")
3157+
end
31073158
end
31083159

31093160
describe "&parse_with_comments/2" do

0 commit comments

Comments
 (0)