diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 3b0df5fda..b7ece0ef1 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -146,6 +146,7 @@ Paren_Expr :: struct { Selector_Expr :: struct { using node: Expr, expr: ^Expr, + op: tokenizer.Token, field: ^Ident, } @@ -154,6 +155,13 @@ Implicit_Selector_Expr :: struct { field: ^Ident, } +Selector_Call_Expr :: struct { + using node: Expr, + expr: ^Expr, + call: ^Call_Expr, + modified_call: bool, +} + Index_Expr :: struct { using node: Expr, expr: ^Expr, diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 70bdc9e26..259d8f482 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -2353,10 +2353,10 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { where_clauses: []^ast.Expr; if (p.curr_tok.kind == .Where) { where_token = expect_token(p, .Where); - prev_level := p.expr_level; + where_prev_level := p.expr_level; p.expr_level = -1; where_clauses = parse_rhs_expr_list(p); - p.expr_level = prev_level; + p.expr_level = where_prev_level; } expect_token(p, .Open_Brace); @@ -2416,10 +2416,10 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { where_clauses: []^ast.Expr; if (p.curr_tok.kind == .Where) { where_token = expect_token(p, .Where); - prev_level := p.expr_level; + where_prev_level := p.expr_level; p.expr_level = -1; where_clauses = parse_rhs_expr_list(p); - p.expr_level = prev_level; + p.expr_level = where_prev_level; } variants: [dynamic]^ast.Expr; @@ -2628,7 +2628,7 @@ parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit { return lit; } -parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Call_Expr { +parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { args: [dynamic]^ast.Expr; ellipsis: tokenizer.Token; @@ -2686,6 +2686,14 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Call_Expr { ce.ellipsis = ellipsis; ce.close = close.pos; + o := ast.unparen_expr(operand); + if se, ok := o.derived.(ast.Selector_Expr); ok && se.op.kind == .Arrow_Right { + sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce.end); + sce.expr = o; + sce.call = ce; + return sce; + } + return ce; } @@ -2776,6 +2784,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a sel := ast.new(ast.Selector_Expr, operand.pos, field.end); sel.expr = operand; + sel.op = tok; sel.field = field; operand = sel; @@ -2811,6 +2820,24 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)); } + case .Arrow_Right: + tok := expect_token(p, .Arrow_Right); + #partial switch p.curr_tok.kind { + case .Ident: + field := parse_ident(p); + + sel := ast.new(ast.Selector_Expr, operand.pos, field.end); + sel.expr = operand; + sel.op = tok; + sel.field = field; + + operand = sel; + case: + error(p, p.curr_tok.pos, "expected a selector"); + advance_token(p); + operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)); + } + case .Pointer: op := expect_token(p, .Pointer); deref := ast.new(ast.Deref_Expr, operand.pos, end_pos(op));