diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 9d41a0adc..10bc538d3 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -656,6 +656,14 @@ Pointer_Type :: struct { elem: ^Expr, } +Multi_Pointer_Type :: struct { + using node: Expr, + open: tokenizer.Pos, + pointer: tokenizer.Pos, + close: tokenizer.Pos, + elem: ^Expr, +} + Array_Type :: struct { using node: Expr, open: tokenizer.Pos, diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin index e80a4d05f..9af4b3941 100644 --- a/core/odin/ast/clone.odin +++ b/core/odin/ast/clone.odin @@ -251,6 +251,8 @@ clone_node :: proc(node: ^Node) -> ^Node { r.results = auto_cast clone(r.results); case Pointer_Type: r.elem = clone(r.elem); + case Multi_Pointer_Type: + r.elem = clone(r.elem); case Array_Type: r.len = clone(r.len); r.elem = clone(r.elem); diff --git a/core/odin/ast/walk.odin b/core/odin/ast/walk.odin index c64d4d29c..c6922fb35 100644 --- a/core/odin/ast/walk.odin +++ b/core/odin/ast/walk.odin @@ -349,6 +349,8 @@ walk :: proc(v: ^Visitor, node: ^Node) { walk(v, n.results); case Pointer_Type: walk(v, n.elem); + case Multi_Pointer_Type: + walk(v, n.elem); case Array_Type: if n.tag != nil { walk(v, n.tag); diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 6bcb564fe..5dda2fc27 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -2440,18 +2440,26 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { tok := expect_token(p, .Pointer); elem := parse_type(p); ptr := ast.new(ast.Pointer_Type, tok.pos, elem.end); + ptr.pointer = tok.pos; ptr.elem = elem; return ptr; + case .Open_Bracket: open := expect_token(p, .Open_Bracket); count: ^ast.Expr; - if p.curr_tok.kind == .Question { - tok := expect_token(p, .Question); - q := ast.new(ast.Unary_Expr, tok.pos, end_pos(tok)); - q.op = tok; - count = q; - } else if p.curr_tok.kind == .Dynamic { + switch p.curr_tok.kind { + case .Pointer: + tok := expect_token(p, .Pointer); + close := expect_token(p, .Close_Bracket); + elem := parse_type(p); + t := ast.new(ast.Multi_Pointer_Type, open.pos, elem.end_pos); + t.open = open.pos; + t.pointer = tok.pos; + t.close = close.pos; + t.elem = elem; + return t; + case .Dynamic: tok := expect_token(p, .Dynamic); close := expect_token(p, .Close_Bracket); elem := parse_type(p); @@ -2460,12 +2468,18 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { da.dynamic_pos = tok.pos; da.close = close.pos; da.elem = elem; - return da; - } else if p.curr_tok.kind != .Close_Bracket { + case .Question: + tok := expect_token(p, .Question); + q := ast.new(ast.Unary_Expr, tok.pos, end_pos(tok)); + q.op = tok; + count = q; + case: p.expr_level += 1; count = parse_expr(p, false); p.expr_level -= 1; + case .Close_Bracket: + // handle below } close := expect_token(p, .Close_Bracket); elem := parse_type(p);