diff --git a/lib/spitfire.ex b/lib/spitfire.ex index 9db95c1..905242e 100644 --- a/lib/spitfire.ex +++ b/lib/spitfire.ex @@ -203,6 +203,12 @@ defmodule Spitfire do peek_token(parser) in [:eol, :";", :eof] and parser.tokens != :eot -> next_token(parser) + current_token(parser) in [:")", :"]", :"}", :">>"] -> + next_token(parser) + + peek_token(parser) in [:")", :"]", :"}", :">>"] -> + next_token(parser) + true -> parser end diff --git a/test/spitfire_test.exs b/test/spitfire_test.exs index a806b26..fa75116 100644 --- a/test/spitfire_test.exs +++ b/test/spitfire_test.exs @@ -2653,7 +2653,6 @@ defmodule SpitfireTest do {{:., [line: 5, column: 37], [{:state, [line: 5, column: 32], nil}, :baz]}, [no_parens: true, line: 5, column: 38], []} ]}, - {:__block__, [error: true, line: 5, column: 41], []}, {:__block__, [ end_of_expression: [newlines: 1, line: 5, column: 43], @@ -2665,7 +2664,6 @@ defmodule SpitfireTest do [ {[line: 2, column: 8], "missing closing brace for map"}, {[line: 4, column: 1], "unknown token: ,"}, - {[line: 5, column: 41], "unknown token: )"}, {[line: 5, column: 42], "unknown token: }"} ]} end @@ -2844,6 +2842,45 @@ defmodule SpitfireTest do assert {:error, _ast, [{[line: 1, column: 4], "missing closing parentheses"}]} = Spitfire.parse(code) end + + test "stray closing delimiter after identifier" do + assert {:error, {:__block__, [], [{:x, _, nil}, {:__block__, [error: true, line: 1, column: 3], []}]}, + [{[line: 1, column: 3], "unknown token: ]"}]} = Spitfire.parse("x ]") + + assert {:error, {:__block__, [], [{:x, _, nil}, {:__block__, [error: true, line: 1, column: 3], []}]}, + [{[line: 1, column: 3], "unknown token: }"}]} = Spitfire.parse("x }") + + assert {:error, {:__block__, [], [{:x, _, nil}, {:__block__, [error: true, line: 1, column: 3], []}]}, + [{[line: 1, column: 3], "unknown token: )"}]} = Spitfire.parse("x )") + + assert {:error, {:__block__, [], [{:@, _, [{:x, _, nil}]}, {:__block__, [error: true, line: 1, column: 4], []}]}, + [{[line: 1, column: 4], "unknown token: ]"}]} = Spitfire.parse("@x ]") + + assert {:error, {:__block__, [], [1, {:__block__, [error: true, line: 1, column: 3], []}]}, + [{[line: 1, column: 3], "unknown token: ]"}]} = Spitfire.parse("1 ]") + + assert {:error, _ast, [{[line: 1, column: 3], "unknown token: ]"}, {[line: 1, column: 5], "unknown token: }"}]} = + Spitfire.parse("x ] }") + end + + test "stray closing delimiter after complete expression" do + assert {:error, + {:__block__, [], + [ + {:foo, [closing: [line: 1, column: 5], line: 1, column: 1], []}, + {:__block__, [error: true, line: 1, column: 6], []} + ]}, [{[line: 1, column: 6], "unknown token: }"}]} = Spitfire.parse("foo()}") + + assert {:error, {:__block__, [], [[1, 2], {:__block__, [error: true, line: 1, column: 7], []}]}, + [{[line: 1, column: 7], "unknown token: }"}]} = Spitfire.parse("[1, 2]}") + + assert {:error, + {:__block__, [], + [ + {:%{}, [closing: [line: 1, column: 7], line: 1, column: 1], [a: 1]}, + {:__block__, [error: true, line: 1, column: 8], []} + ]}, [{[line: 1, column: 8], "unknown token: )"}]} = Spitfire.parse("%{a: 1})") + end end describe "&parse_with_comments/2" do