From 83c8c48ed7b5eb97637992d03cb39bff51b5c781 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Aug 2022 13:07:49 +0100 Subject: [PATCH 1/2] Simplify ast parsing for prefixes --- core/odin/ast/ast.odin | 25 +++++++++++++ core/odin/parser/parser.odin | 68 +++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index f4aa67446..a4e4a6b35 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -553,12 +553,16 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) { } Field_Flag :: enum { + Unknown, + Ellipsis, Using, No_Alias, C_Vararg, Auto_Cast, Any_Int, + Subtype, + By_Ptr, Results, Tags, @@ -566,11 +570,31 @@ Field_Flag :: enum { Typeid_Token, } +field_flag_strings := [Field_Flag]string{ + .Unknown = "", + + .Ellipsis = "..", + .Using = "using", + .No_Alias = "#no_alias", + .C_Vararg = "#c_vararg", + .Auto_Cast = "auto_cast", + .Any_Int = "#any_int", + .Subtype = "#subtype", + .By_Ptr = "#by_ptr", + + .Results = "results", + .Tags = "field tag", + .Default_Parameters = "default parameters", + .Typeid_Token = "typeid", +} + + Field_Flags :: distinct bit_set[Field_Flag] Field_Flags_Struct :: Field_Flags{ .Using, .Tags, + .Subtype, } Field_Flags_Record_Poly_Params :: Field_Flags{ .Typeid_Token, @@ -583,6 +607,7 @@ Field_Flags_Signature :: Field_Flags{ .C_Vararg, .Auto_Cast, .Any_Int, + .By_Ptr, .Default_Parameters, } diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 52ecb4781..52f4d1588 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1621,6 +1621,34 @@ Field_Prefix :: enum { C_Vararg, Auto_Cast, Any_Int, + Subtype, + By_Ptr, +} + +field_prefix_strings := [Field_Prefix]string{ + .Invalid = "invalid", + .Unknown = "unknown", + + .Using = "using", + .Auto_Cast = "auto_cast", + .No_Alias = "#no_alias", + .C_Vararg = "#c_vararg", + .Any_Int = "#any_int", + .Subtype = "#subtype", + .By_Ptr = "#by_ptr", +} + +field_prefix_to_flag := [Field_Prefix]ast.Field_Flag{ + .Invalid = .Unknown, + .Unknown = .Unknown, + + .Using = .Using, + .No_Alias = .No_Alias, + .C_Vararg = .C_Vararg, + .Auto_Cast = .Auto_Cast, + .Any_Int = .Any_Int, + .Subtype = .Subtype, + .By_Ptr = .By_Ptr, } Field_Prefixes :: distinct bit_set[Field_Prefix] @@ -1688,6 +1716,10 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix { return .C_Vararg case "any_int": return .Any_Int + case "subtype": + return .Subtype + case "by_ptr": + return .By_Ptr } } return .Unknown @@ -1716,23 +1748,11 @@ parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags { for kind in Field_Prefix { count := counts[kind] - switch kind { - case .Invalid, .Unknown: // Ignore - case .Using: - if count > 1 { error(p, p.curr_tok.pos, "multiple 'using' in this field list") } - if count > 0 { flags += {.Using} } - case .No_Alias: - if count > 1 { error(p, p.curr_tok.pos, "multiple '#no_alias' in this field list") } - if count > 0 { flags += {.No_Alias} } - case .C_Vararg: - if count > 1 { error(p, p.curr_tok.pos, "multiple '#c_vararg' in this field list") } - if count > 0 { flags += {.C_Vararg} } - case .Auto_Cast: - if count > 1 { error(p, p.curr_tok.pos, "multiple 'auto_cast' in this field list") } - if count > 0 { flags += {.Auto_Cast} } - case .Any_Int: - if count > 1 { error(p, p.curr_tok.pos, "multiple '#any_int' in this field list") } - if count > 0 { flags += {.Any_Int} } + if kind == .Invalid || kind == .Unknown { + // Ignore + } else { + if count > 1 { error(p, p.curr_tok.pos, "multiple '%s' in this field list", field_prefix_strings[kind]) } + if count > 0 { flags += {field_prefix_to_flag[kind]} } } } @@ -1748,19 +1768,11 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se for flag in ast.Field_Flag { if flag not_in allowed_flags && flag in flags { - switch flag { - case .Using: - error(p, p.curr_tok.pos, "'using' is not allowed within this field list") - case .No_Alias: - error(p, p.curr_tok.pos, "'#no_alias' is not allowed within this field list") - case .C_Vararg: - error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list") - case .Auto_Cast: - error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list") - case .Any_Int: - error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list") + #partial switch flag { case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token: panic("Impossible prefixes") + case: + error(p, p.curr_tok.pos, "'%s' is not allowed within this field list", ast.field_flag_strings[flag]) } flags -= {flag} } From 97acc57649924e3ce1c9a3c8d18f954df9d24bb1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Aug 2022 13:17:10 +0100 Subject: [PATCH 2/2] Simplify field prefix handling --- core/odin/ast/ast.odin | 12 +++++- core/odin/parser/parser.odin | 77 +++++++----------------------------- 2 files changed, 25 insertions(+), 64 deletions(-) diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index a4e4a6b35..d1b91a829 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -552,7 +552,10 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) { return } +Field_Flags :: distinct bit_set[Field_Flag] + Field_Flag :: enum { + Invalid, Unknown, Ellipsis, @@ -571,6 +574,7 @@ Field_Flag :: enum { } field_flag_strings := [Field_Flag]string{ + .Invalid = "", .Unknown = "", .Ellipsis = "..", @@ -588,8 +592,14 @@ field_flag_strings := [Field_Flag]string{ .Typeid_Token = "typeid", } +field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{ + {"no_alias", .No_Alias}, + {"c_vararg", .C_Vararg}, + {"any_int", .Any_Int}, + {"subtype", .Subtype}, + {"by_ptr", .By_Ptr}, +} -Field_Flags :: distinct bit_set[Field_Flag] Field_Flags_Struct :: Field_Flags{ .Using, diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 52f4d1588..320db28c1 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1611,48 +1611,6 @@ new_ast_field :: proc(names: []^ast.Expr, type: ^ast.Expr, default_value: ^ast.E return field } - -Field_Prefix :: enum { - Invalid, - Unknown, - - Using, - No_Alias, - C_Vararg, - Auto_Cast, - Any_Int, - Subtype, - By_Ptr, -} - -field_prefix_strings := [Field_Prefix]string{ - .Invalid = "invalid", - .Unknown = "unknown", - - .Using = "using", - .Auto_Cast = "auto_cast", - .No_Alias = "#no_alias", - .C_Vararg = "#c_vararg", - .Any_Int = "#any_int", - .Subtype = "#subtype", - .By_Ptr = "#by_ptr", -} - -field_prefix_to_flag := [Field_Prefix]ast.Field_Flag{ - .Invalid = .Unknown, - .Unknown = .Unknown, - - .Using = .Using, - .No_Alias = .No_Alias, - .C_Vararg = .C_Vararg, - .Auto_Cast = .Auto_Cast, - .Any_Int = .Any_Int, - .Subtype = .Subtype, - .By_Ptr = .By_Ptr, -} - -Field_Prefixes :: distinct bit_set[Field_Prefix] - Expr_And_Flags :: struct { expr: ^ast.Expr, flags: ast.Field_Flags, @@ -1694,7 +1652,7 @@ convert_to_ident_list :: proc(p: ^Parser, list: []Expr_And_Flags, ignore_flags, return idents[:] } -is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix { +is_token_field_prefix :: proc(p: ^Parser) -> ast.Field_Flag { #partial switch p.curr_tok.kind { case .EOF: return .Invalid @@ -1709,26 +1667,19 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix { defer advance_token(p) #partial switch p.curr_tok.kind { case .Ident: - switch p.curr_tok.text { - case "no_alias": - return .No_Alias - case "c_vararg": - return .C_Vararg - case "any_int": - return .Any_Int - case "subtype": - return .Subtype - case "by_ptr": - return .By_Ptr + for kf in ast.field_hash_flag_strings { + if p.curr_tok.text == kf.key { + return kf.flag + } } } return .Unknown } - return .Invalid + return .Unknown } -parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags { - counts: [len(Field_Prefix)]int +parse_field_prefixes :: proc(p: ^Parser) -> (flags: ast.Field_Flags) { + counts: [len(ast.Field_Flag)]int for { kind := is_token_field_prefix(p) @@ -1744,19 +1695,17 @@ parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags { counts[kind] += 1 } - flags: ast.Field_Flags - - for kind in Field_Prefix { + for kind in ast.Field_Flag { count := counts[kind] if kind == .Invalid || kind == .Unknown { // Ignore } else { - if count > 1 { error(p, p.curr_tok.pos, "multiple '%s' in this field list", field_prefix_strings[kind]) } - if count > 0 { flags += {field_prefix_to_flag[kind]} } + if count > 1 { error(p, p.curr_tok.pos, "multiple '%s' in this field list", ast.field_flag_strings[kind]) } + if count > 0 { flags += {kind} } } } - return flags + return } check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, set_flags: ast.Field_Flags) -> (flags: ast.Field_Flags) { @@ -1769,6 +1718,8 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se for flag in ast.Field_Flag { if flag not_in allowed_flags && flag in flags { #partial switch flag { + case .Unknown, .Invalid: + // ignore case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token: panic("Impossible prefixes") case: