diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 8941016291a5..a73b3dc2a182 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -571,6 +571,7 @@ module Crystal it_parses "foo { 1 }", Call.new(nil, "foo", block: Block.new(body: 1.int32)) it_parses "foo { |a| 1 }", Call.new(nil, "foo", block: Block.new(["a".var], 1.int32)) it_parses "foo { |a, b| 1 }", Call.new(nil, "foo", block: Block.new(["a".var, "b".var], 1.int32)) + it_parses "foo { |a, b, | 1 }", Call.new(nil, "foo", block: Block.new(["a".var, "b".var], 1.int32)) it_parses "1.foo do; 1; end", Call.new(1.int32, "foo", block: Block.new(body: 1.int32)) it_parses "a b() {}", Call.new(nil, "a", Call.new(nil, "b", block: Block.new)) @@ -591,6 +592,16 @@ module Crystal "c".var, ] of ASTNode))) + it_parses "foo { |(_, c, )| c }", Call.new(nil, "foo", + block: Block.new(["__arg0".var], + Expressions.new([ + Assign.new("c".var, Call.new("__arg0".var, "[]", 1.int32)), + "c".var, + ] of ASTNode))) + + assert_syntax_error "foo { |a b| }", "expecting ',' or '|', not b" + assert_syntax_error "foo { |(a b)| }", "expecting ',' or ')', not b" + it_parses "1 ? 2 : 3", If.new(1.int32, 2.int32, 3.int32) it_parses "1 ? a : b", If.new(1.int32, "a".call, "b".call) it_parses "1 ? a : b ? c : 3", If.new(1.int32, "a".call, If.new("b".call, "c".call, 3.int32)) diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 35af8e800f9e..3522f546154a 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -4014,7 +4014,7 @@ module Crystal next_token_skip_space if @token.type == :"|" next_token_skip_space_or_newline - while @token.type != :"|" + while true if @token.type == :"*" if splat_index raise "splat block argument already specified", @token @@ -4064,12 +4064,14 @@ module Crystal end next_token_skip_space_or_newline - if @token.type == :"," + case @token.type + when :"," next_token_skip_space_or_newline - end - - if @token.type == :")" + break if @token.type == :")" + when :")" break + else + raise "expecting ',' or ')', not #{@token}", @token end i += 1 @@ -4084,8 +4086,15 @@ module Crystal block_args << var next_token_skip_space_or_newline - if @token.type == :"," + + case @token.type + when :"," next_token_skip_space_or_newline + break if @token.type == :"|" + when :"|" + break + else + raise "expecting ',' or '|', not #{@token}", @token end arg_index += 1