Skip to content

Commit 79b5b25

Browse files
committed
fix: parsing crashes on code with errors
1 parent 1d728cf commit 79b5b25

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ spitfire-*.tar
2727
benchmarks
2828
*.bggg
2929
priv/plts/*
30+
.expert

lib/spitfire.ex

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ defmodule Spitfire do
174174
case result do
175175
{:ok, ast} -> {:ok, ast, comments}
176176
{:error, ast, errors} -> {:error, ast, comments, errors}
177+
{:error, :no_fuel_remaining} -> {:error, :no_fuel_remaining}
177178
end
178179
after
179180
Process.delete(:code_formatter_comments)
@@ -619,9 +620,16 @@ defmodule Spitfire do
619620
{kvs, parser} =
620621
while2 peek_token(parser) == :"," <- parser do
621622
parser = parser |> next_token() |> next_token()
622-
{pair, parser} = parse_kw_identifier(parser)
623623

624-
{pair, parser}
624+
case current_token_type(parser) do
625+
type when type in [:kw_identifier, :kw_identifier_unsafe] ->
626+
{pair, parser} = parse_kw_identifier(parser)
627+
{pair, parser}
628+
629+
_ ->
630+
# Not a keyword identifier, exit the loop
631+
{:filter, {nil, parser}}
632+
end
625633
end
626634

627635
{[{token, value} | kvs], parser}
@@ -646,9 +654,16 @@ defmodule Spitfire do
646654
{kvs, parser} =
647655
while2 peek_token(parser) == :"," <- parser do
648656
parser = parser |> next_token() |> next_token()
649-
{pair, parser} = parse_kw_identifier(parser)
650657

651-
{pair, parser}
658+
case current_token_type(parser) do
659+
type when type in [:kw_identifier, :kw_identifier_unsafe] ->
660+
{pair, parser} = parse_kw_identifier(parser)
661+
{pair, parser}
662+
663+
_ ->
664+
# Not a keyword identifier, exit the loop
665+
{:filter, {nil, parser}}
666+
end
652667
end
653668

654669
{[{atom, value} | kvs], parser}
@@ -1698,11 +1713,9 @@ defmodule Spitfire do
16981713
{parser, is_valid} = validate_peek(parser, current_token_type(parser))
16991714

17001715
if is_valid do
1701-
while peek_token(parser) not in terminals && calc_prec(parser, associativity, precedence) <- {left, parser} do
1702-
case peek_token_type(parser) do
1703-
:. -> parse_dot_expression(next_token(parser), left)
1704-
_ -> {left, parser}
1705-
end
1716+
while peek_token(parser) not in terminals && peek_token(parser) == :. &&
1717+
calc_prec(parser, associativity, precedence) <- {left, parser} do
1718+
parse_dot_expression(next_token(parser), left)
17061719
end
17071720
else
17081721
{left, parser}
@@ -2415,6 +2428,10 @@ defmodule Spitfire do
24152428
:eof
24162429
end
24172430

2431+
defp peek_token(%{peek_token: nil}) do
2432+
:eof
2433+
end
2434+
24182435
defp peek_token_eat_eol(%{peek_token: {:eol, _token}} = parser) do
24192436
peek_token_eat_eol(next_token(parser))
24202437
end

test/spitfire_test.exs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2722,6 +2722,34 @@ defmodule SpitfireTest do
27222722
]
27232723
}
27242724
end
2725+
2726+
test "incomplete struct in match expression" do
2727+
assert Spitfire.parse("%Foo = x") ==
2728+
{:error,
2729+
{:%, [line: 1, column: 1],
2730+
[
2731+
{:__aliases__, [last: [line: 1, column: 2], line: 1, column: 2], [:Foo]},
2732+
{:%{}, [closing: [line: 1, column: 8], line: 1, column: 6], [{:x, [line: 1, column: 8], nil}]}
2733+
]}, [{[line: 1, column: 8], "missing closing brace for struct"}]}
2734+
end
2735+
2736+
test "invalid character inside list" do
2737+
assert Spitfire.parse("[«]") ==
2738+
{:error, [{:__block__, [error: true], []}],
2739+
[
2740+
{[], "unknown token: eot"},
2741+
{[line: 1, column: 1], "missing closing bracket for list"}
2742+
]}
2743+
end
2744+
2745+
test "invalid character inside tuple" do
2746+
assert Spitfire.parse("{«}") ==
2747+
{:error, {:{}, [closing: [], line: 1, column: 1], [{:__block__, [error: true], []}]},
2748+
[
2749+
{[], "unknown token: eot"},
2750+
{[line: 1, column: 1], "missing closing brace for tuple"}
2751+
]}
2752+
end
27252753
end
27262754

27272755
describe "&parse_with_comments/2" do

0 commit comments

Comments
 (0)