Skip to content

Commit

Permalink
Merge pull request #6413 from asterite/bug/6014-parse-named-tuple-ins…
Browse files Browse the repository at this point in the history
…ide-paren

Parser: fix parsing of named tuple inside generic type
  • Loading branch information
ysbaddaden authored Jul 20, 2018
2 parents 02a78a8 + c864338 commit 1bedce6
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
1 change: 1 addition & 0 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ module Crystal

it_parses "Foo({x: X})", Generic.new("Foo".path, [Generic.new(Path.global("NamedTuple"), [] of ASTNode, named_args: [NamedArgument.new("x", "X".path)])] of ASTNode)
it_parses "Foo({x: X, y: Y})", Generic.new("Foo".path, [Generic.new(Path.global("NamedTuple"), [] of ASTNode, named_args: [NamedArgument.new("x", "X".path), NamedArgument.new("y", "Y".path)])] of ASTNode)
it_parses "Foo(T, {x: X})", Generic.new("Foo".path, ["T".path, Generic.new(Path.global("NamedTuple"), [] of ASTNode, named_args: [NamedArgument.new("x", "X".path)])] of ASTNode)
assert_syntax_error "Foo({x: X, x: Y})", "duplicated key: x"

it_parses %(Foo({"foo bar": X})), Generic.new("Foo".path, [Generic.new(Path.global("NamedTuple"), [] of ASTNode, named_args: [NamedArgument.new("foo bar", "X".path)])] of ASTNode)
Expand Down
25 changes: 22 additions & 3 deletions src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4557,7 +4557,7 @@ module Crystal
end

def parse_types(allow_primitives = false, allow_splat = false)
type = parse_type(allow_primitives: allow_primitives, allow_splat: allow_splat)
type = parse_type(allow_primitives: allow_primitives, allow_splat: allow_splat, inside_paren: true)
case type
when Array
type
Expand All @@ -4581,15 +4581,19 @@ module Crystal
end
end

def parse_type(allow_primitives, allow_commas = true, allow_splat = false)
def parse_type(allow_primitives, allow_commas = true, allow_splat = false, inside_paren = false)
location = @token.location

if @token.type == :"->"
input_types = nil
else
input_types = parse_type_union(allow_primitives, allow_splat)
input_types = [input_types] unless input_types.is_a?(Array)
while allow_commas && @token.type == :"," && ((allow_primitives && next_comes_type_or_int) || (!allow_primitives && next_comes_type))
while allow_commas && @token.type == :"," && (
(allow_primitives && next_comes_type_or_int) ||
(!allow_primitives && next_comes_type) ||
(inside_paren && next_comes_curly)
)
next_token_skip_space_or_newline
if @token.type == :"->"
next_types = parse_type(false)
Expand Down Expand Up @@ -4856,6 +4860,21 @@ module Crystal
end
end

def next_comes_curly
old_pos, old_line, old_column = current_pos, @line_number, @column_number

@temp_token.copy_from(@token)

next_token_skip_space_or_newline

curly = @token.type == :"{"

@token.copy_from(@temp_token)
self.current_pos, @line_number, @column_number = old_pos, old_line, old_column

curly
end

def make_pointer_type(node)
Generic.new(Path.global("Pointer").at(node), [node] of ASTNode).at(node)
end
Expand Down

0 comments on commit 1bedce6

Please sign in to comment.