diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 05b572acea27..f637577c20a5 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -705,7 +705,10 @@ describe "Parser" do it_parses "lib LibC\nalias Foo = Bar\nend", LibDef.new("LibC", [Alias.new("Foo", "Bar".path)] of ASTNode) it_parses "lib LibC; struct Foo; include Bar; end; end", LibDef.new("LibC", [CStructOrUnionDef.new("Foo", Include.new("Bar".path))] of ASTNode) + it_parses "lib LibC\nfun SomeFun\nend", LibDef.new("LibC", [FunDef.new("SomeFun")] of ASTNode) + it_parses "fun foo(x : Int32) : Int64\nx\nend", FunDef.new("foo", [Arg.new("x", restriction: "Int32".path)], "Int64".path, body: "x".var) + assert_syntax_error "fun Foo : Int64\nend" it_parses "lib LibC; {{ 1 }}; end", LibDef.new("LibC", body: [MacroExpression.new(1.int32)] of ASTNode) it_parses "lib LibC; {% if 1 %}2{% end %}; end", LibDef.new("LibC", body: [MacroIf.new(1.int32, MacroLiteral.new("2"))] of ASTNode) @@ -1297,6 +1300,8 @@ describe "Parser" do it_parses "1 ** -x", Call.new(1.int32, "**", Call.new("x".call, "-")) + it_parses "foo.Bar", Call.new("foo".call, "Bar") + assert_syntax_error "return do\nend", "unexpected token: do" %w(def macro class struct module fun alias abstract include extend lib).each do |keyword| diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index bdf7057cd542..87d481d57fc0 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -550,7 +550,7 @@ module Crystal end end - AtomicWithMethodCheck = [:IDENT, :"+", :"-", :"*", :"/", :"%", :"|", :"&", :"^", :"**", :"<<", :"<", :"<=", :"==", :"!=", :"=~", :"!~", :">>", :">", :">=", :"<=>", :"===", :"[]", :"[]=", :"[]?", :"["] + AtomicWithMethodCheck = [:IDENT, :CONST, :"+", :"-", :"*", :"/", :"%", :"|", :"&", :"^", :"**", :"<<", :"<", :"<=", :"==", :"!=", :"=~", :"!~", :">>", :">", :">=", :"<=>", :"===", :"[]", :"[]=", :"[]?", :"["] def parse_atomic_with_method location = @token.location @@ -619,7 +619,12 @@ module Crystal elsif @token.type == :"[" return parse_atomic_method_suffix(atomic, location) else - name = @token.type == :IDENT ? @token.value.to_s : @token.type.to_s + name = case @token.type + when :IDENT, :CONST + @token.value.to_s + else + @token.type.to_s + end end_location = token_end_location @wants_regex = false @@ -1026,7 +1031,7 @@ module Crystal when :fun check_type_declaration do check_not_inside_def("can't define fun inside def") do - parse_fun_def require_body: true + parse_fun_def top_level: true, require_body: true end end when :alias @@ -4864,7 +4869,7 @@ module Crystal when :alias parse_alias when :fun - parse_fun_def + parse_fun_def(top_level: false) when :type parse_type_def when :struct @@ -4918,14 +4923,21 @@ module Crystal IdentOrConst = [:IDENT, :CONST] - def parse_fun_def(require_body = false) + def parse_fun_def(top_level, require_body = false) location = @token.location doc = @token.doc push_def if require_body next_token_skip_space_or_newline - name = check_ident + + name = if top_level + check_ident + else + check IdentOrConst + @token.value.to_s + end + next_token_skip_space_or_newline if @token.type == :"="