From 49d998122f68b54d554323129427a6b9d7a9ceec Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Mon, 17 Oct 2022 23:35:25 +0800 Subject: [PATCH 1/2] Fix for unexpected literals in class definitions --- spec/compiler/parser/parser_spec.cr | 11 +++++++++++ src/compiler/crystal/syntax/parser.cr | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index b5e0a0301fc6..581b1e9dbe15 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -253,6 +253,17 @@ module Crystal assert_syntax_error "foo { |(#{kw})| }", "cannot use '#{kw}' as a block parameter name", 1, 9 end + describe "literals in class definitions" do + # #11209 + %w("a" 'a' [1] {1} {|a|a} ->{} ->(x : Bar){} :Bar :bar %x() %w() %()).each do |invalid| + assert_syntax_error "class Foo#{invalid}; end" + assert_syntax_error "class Foo#{invalid} < Baz; end" + assert_syntax_error "class Foo#{invalid} < self; end" + assert_syntax_error "class Foo < Baz#{invalid}; end" + assert_syntax_error "class Foo < self#{invalid}; end" + end + end + it_parses "def self.foo\n1\nend", Def.new("foo", body: 1.int32, receiver: "self".var) it_parses "def self.foo()\n1\nend", Def.new("foo", body: 1.int32, receiver: "self".var) it_parses "def self.foo=\n1\nend", Def.new("foo=", body: 1.int32, receiver: "self".var) diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index ce3a1cc9b38d..4f7af8e54f2c 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -1637,6 +1637,10 @@ module Crystal name = parse_path skip_space + unexpected_token unless @token.type.op_lt? || # Inheritance + @token.type.op_lparen? || # Generic Arguments + @token.type.newline? || @token.type.op_semicolon? + type_vars, splat_index = parse_type_vars superclass = nil @@ -1649,6 +1653,8 @@ module Crystal else superclass = parse_generic end + + unexpected_token unless @token.type.newline? || @token.type.op_semicolon? || @token.type.space? end skip_statement_end From 857f3a0de985e38a40826cbfca735ba5fbe68352 Mon Sep 17 00:00:00 2001 From: Caspian Baska Date: Tue, 18 Oct 2022 01:32:11 +0800 Subject: [PATCH 2/2] Account for single-line class declarations --- src/compiler/crystal/syntax/parser.cr | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 4f7af8e54f2c..4c41220d4234 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -1639,7 +1639,7 @@ module Crystal unexpected_token unless @token.type.op_lt? || # Inheritance @token.type.op_lparen? || # Generic Arguments - @token.type.newline? || @token.type.op_semicolon? + is_statement_end? type_vars, splat_index = parse_type_vars @@ -1654,7 +1654,7 @@ module Crystal superclass = parse_generic end - unexpected_token unless @token.type.newline? || @token.type.op_semicolon? || @token.type.space? + unexpected_token unless @token.type.space? || is_statement_end? end skip_statement_end @@ -1674,6 +1674,10 @@ module Crystal class_def end + def is_statement_end? + @token.type.newline? || @token.type.op_semicolon? || @token.keyword?(:end) + end + def parse_type_vars type_vars = nil splat_index = nil