Skip to content

Commit

Permalink
Fixed #4311: {"a" : 1} won't parse anymore as a named tuple
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Jun 3, 2017
1 parent 7eba0e8 commit d8eac43
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 14 deletions.
3 changes: 3 additions & 0 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,9 @@ describe "Parser" do

assert_syntax_error %(def foo("bar");end), "expected argument internal name"

assert_syntax_error %({"a" : 1})
assert_syntax_error %({"a": 1, "b" : 2})

describe "end locations" do
assert_end_location "nil"
assert_end_location "false"
Expand Down
32 changes: 18 additions & 14 deletions src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1743,7 +1743,7 @@ module Crystal
value : String | ASTNode,
line_number : Int32

def parse_delimiter
def parse_delimiter(want_skip_space = true)
if @token.type == :STRING
return node_and_next_token StringLiteral.new(@token.value.to_s)
end
Expand All @@ -1761,7 +1761,7 @@ module Crystal

delimiter_state, has_interpolation, options, token_end_location = consume_delimiter pieces, delimiter_state, has_interpolation

if delimiter_state.kind == :string
if delimiter_state.kind == :string && want_skip_space
while true
passed_backslash_newline = @token.passed_backslash_newline
skip_space
Expand Down Expand Up @@ -1981,14 +1981,14 @@ module Crystal
end
end

def parse_string_without_interpolation(context)
def parse_string_without_interpolation(context, want_skip_space = true)
location = @token.location

unless string_literal_start?
raise "expected string literal for #{context}, not #{@token}"
end

string = parse_delimiter
string = parse_delimiter(want_skip_space)
if string.is_a?(StringLiteral)
string.value
else
Expand Down Expand Up @@ -2096,18 +2096,22 @@ module Crystal
end
return parse_named_tuple(location)
else
first_key = parse_op_assign_no_control
case @token.type
when :":"
if first_key.is_a?(StringLiteral)
if string_literal_start?
first_key = parse_delimiter(want_skip_space: false)
if first_key.is_a?(StringLiteral) && @token.type == :":"
# It's a named tuple
unless allow_of
raise "can't use named tuple syntax for Hash-like literal, use '=>'", @token
end
return parse_named_tuple(location, first_key.value)
else
check :"=>"
end
else
first_key = parse_op_assign_no_control
end

skip_space

case @token.type
when :","
slash_is_regex!
next_token_skip_space_or_newline
Expand All @@ -2121,10 +2125,10 @@ module Crystal
else
check :"=>"
end
slash_is_regex!
next_token_skip_space
parse_hash_literal first_key, location, allow_of
end
slash_is_regex!
next_token_skip_space
parse_hash_literal first_key, location, allow_of
end
end

Expand Down Expand Up @@ -2265,7 +2269,7 @@ module Crystal
if named_tuple_start?
next_token
elsif string_literal_start?
key = parse_string_without_interpolation("named tuple name")
key = parse_string_without_interpolation("named tuple name", want_skip_space: false)
else
raise "expected '}' or named tuple name, not #{@token}", @token
end
Expand Down

0 comments on commit d8eac43

Please sign in to comment.