@@ -4852,24 +4852,51 @@ pub const PositionContext = union(enum) {
48524852 }
48534853};
48544854
4855- const StackState = struct {
4856- ctx : PositionContext ,
4857- stack_id : StackId ,
4855+ const Stack = struct {
4856+ states : std .ArrayList (State ),
48584857
4859- /// Indicates whether the current context is an ErrorSet definition, ie `error{...}`
4860- pub fn isErrSetDef (self : StackState ) bool {
4861- return (self .stack_id == .brace and self .ctx == .error_access );
4858+ const State = struct {
4859+ ctx : PositionContext ,
4860+ scope : State.Scope ,
4861+
4862+ const Scope = enum { parens , brackets , braces , global };
4863+
4864+ /// Indicates whether the current context is an ErrorSet definition, ie `error{...}`
4865+ pub fn isErrSetDef (self : * Stack.State ) bool {
4866+ return (self .scope == .braces and self .ctx == .error_access );
4867+ }
4868+ };
4869+
4870+ pub fn initCapacity (allocator : std.mem.Allocator , capacity : usize ) error {OutOfMemory }! Stack {
4871+ return .{ .states = try .initCapacity (allocator , capacity ) };
48624872 }
4863- };
48644873
4865- const StackId = enum { paren , bracket , brace , global };
4874+ pub fn deinit (self : * Stack , allocator : std.mem.Allocator ) void {
4875+ self .states .deinit (allocator );
4876+ }
48664877
4867- fn peek (allocator : std.mem.Allocator , arr : * std .ArrayList (StackState )) ! * StackState {
4868- if (arr .items .len == 0 ) {
4869- try arr .append (allocator , .{ .ctx = .empty , .stack_id = .global });
4878+ pub fn push (self : * Stack , allocator : std.mem.Allocator , state : * const State ) error {OutOfMemory }! void {
4879+ try self .states .append (allocator , state .* );
48704880 }
4871- return & arr .items [arr .items .len - 1 ];
4872- }
4881+
4882+ pub fn peek (self : * Stack , allocator : std.mem.Allocator ) error {OutOfMemory }! * Stack.State {
4883+ if (self .states .items .len == 0 ) {
4884+ try self .states .append (allocator , .{ .ctx = .empty , .scope = .global });
4885+ }
4886+ return & self .states .items [self .states .items .len - 1 ];
4887+ }
4888+
4889+ /// Pops the last state off the stack. Sets previous state's ctx to .empty if !scopes_match
4890+ pub fn pop (
4891+ self : * Stack ,
4892+ allocator : std.mem.Allocator ,
4893+ /// Indicate whether the current state's scope matches the one being closed
4894+ scopes_match : bool ,
4895+ ) error {OutOfMemory }! void {
4896+ if (self .states .items .len != 0 ) self .states .items .len -= 1 ;
4897+ if (! scopes_match ) (try self .peek (allocator )).ctx = .empty ;
4898+ }
4899+ };
48734900
48744901fn tokenLocAppend (prev : offsets.Loc , token : std.zig.Token ) offsets.Loc {
48754902 return .{
@@ -4941,7 +4968,7 @@ pub fn getPositionContext(
49414968 break ;
49424969 }
49434970
4944- var stack : std . ArrayList ( StackState ) = try .initCapacity (allocator , 8 );
4971+ var stack : Stack = try .initCapacity (allocator , 8 );
49454972 defer stack .deinit (allocator );
49464973 var should_do_lookahead = lookahead ;
49474974
@@ -4968,7 +4995,7 @@ pub fn getPositionContext(
49684995 // `tok` is the latter of the two.
49694996 if (! should_do_lookahead ) break ;
49704997 should_do_lookahead = false ;
4971- const curr_ctx = try peek (allocator , & stack );
4998+ const curr_ctx = try stack . peek (allocator );
49724999 switch (tok .tag ) {
49735000 .identifier ,
49745001 .builtin ,
@@ -4999,7 +5026,7 @@ pub fn getPositionContext(
49995026 }
50005027
50015028 // State changes
5002- var curr_ctx = try peek (allocator , & stack );
5029+ var curr_ctx = try stack . peek (allocator );
50035030 switch (tok .tag ) {
50045031 .string_literal , .multiline_string_literal_line = > string_lit_block : {
50055032 curr_ctx .ctx = .{ .string_literal = tok .loc };
@@ -5017,10 +5044,10 @@ pub fn getPositionContext(
50175044
50185045 if (source_index < content_loc .start or content_loc .end < source_index ) break :string_lit_block ;
50195046
5020- if (curr_ctx .stack_id == .paren and
5021- stack .items .len >= 2 )
5047+ if (curr_ctx .scope == .parens and
5048+ stack .states . items .len >= 2 )
50225049 {
5023- const perhaps_builtin = stack .items [stack .items .len - 2 ];
5050+ const perhaps_builtin = stack .states . items [stack . states .items .len - 2 ];
50245051
50255052 switch (perhaps_builtin .ctx ) {
50265053 .builtin = > | loc | {
@@ -5075,41 +5102,20 @@ pub fn getPositionContext(
50755102 },
50765103 .l_paren = > {
50775104 if (curr_ctx .ctx == .empty ) curr_ctx .ctx = .{ .parens_expr = tok .loc };
5078- const stack_id : StackId = switch (curr_ctx .ctx ) {
5079- .keyword = > | token_index | switch (tree .tokenTag (token_index )) {
5080- .keyword_for ,
5081- .keyword_if ,
5082- .keyword_while ,
5083- = > .global ,
5084- else = > .paren ,
5085- },
5086- else = > .paren ,
5087- };
5088- try stack .append (allocator , .{ .ctx = .empty , .stack_id = stack_id });
5089- },
5090- .r_paren = > {
5091- // Do this manually, as .pop() sets `stack.items[stack.items.len - 1]` to `undefined` which currently curr_ctx points to
5092- if (stack .items .len != 0 ) stack .items .len -= 1 ;
5093- if (curr_ctx .stack_id != .paren ) {
5094- (try peek (allocator , & stack )).ctx = .empty ;
5095- }
5096- },
5097- .l_bracket = > try stack .append (allocator , .{ .ctx = .empty , .stack_id = .bracket }),
5098- .r_bracket = > {
5099- // Do this manually, as .pop() sets `stack.items[stack.items.len - 1]` to `undefined` which currently curr_ctx points to
5100- if (stack .items .len != 0 ) stack .items .len -= 1 ;
5101- if (curr_ctx .stack_id != .bracket ) {
5102- (try peek (allocator , & stack )).ctx = .empty ;
5103- }
5104- },
5105- .l_brace = > try stack .append (allocator , .{ .ctx = if (curr_ctx .ctx == .error_access ) curr_ctx .ctx else .empty , .stack_id = .brace }),
5106- .r_brace = > {
5107- // Do this manually, as .pop() sets `stack.items[stack.items.len - 1]` to `undefined` which currently curr_ctx points to
5108- if (stack .items .len != 0 ) stack .items .len -= 1 ;
5109- if (curr_ctx .stack_id != .brace ) {
5110- (try peek (allocator , & stack )).ctx = .empty ;
5111- }
5105+ const scope : Stack.State.Scope = if (curr_ctx .ctx == .keyword ) switch (tree .tokenTag (curr_ctx .ctx .keyword )) {
5106+ .keyword_for ,
5107+ .keyword_if ,
5108+ .keyword_while ,
5109+ = > .global ,
5110+ else = > .parens ,
5111+ } else .parens ;
5112+ try stack .push (allocator , &.{ .ctx = .empty , .scope = scope });
51125113 },
5114+ .r_paren = > try stack .pop (allocator , curr_ctx .scope == .parens ),
5115+ .l_bracket = > try stack .push (allocator , &.{ .ctx = .empty , .scope = .brackets }),
5116+ .r_bracket = > try stack .pop (allocator , curr_ctx .scope == .brackets ),
5117+ .l_brace = > try stack .push (allocator , &.{ .ctx = if (curr_ctx .ctx == .error_access ) curr_ctx .ctx else .empty , .scope = .braces }),
5118+ .r_brace = > try stack .pop (allocator , curr_ctx .scope == .braces ),
51135119 .keyword_error = > curr_ctx .ctx = .error_access ,
51145120 .number_literal = > {
51155121 if (tok .loc .start <= source_index and tok .loc .end >= source_index ) {
@@ -5143,14 +5149,14 @@ pub fn getPositionContext(
51435149 else = > curr_ctx .ctx = .empty ,
51445150 }
51455151
5146- curr_ctx = try peek (allocator , & stack );
5152+ curr_ctx = try stack . peek (allocator );
51475153 switch (curr_ctx .ctx ) {
51485154 .field_access = > | r | curr_ctx .ctx = .{ .field_access = tokenLocAppend (r , tok ) },
51495155 else = > {},
51505156 }
51515157 }
51525158
5153- if (stack .pop ()) | state | {
5159+ if (stack .states . pop ()) | state | {
51545160 switch (state .ctx ) {
51555161 .parens_expr = > | loc | return .{ .var_access = loc },
51565162 .var_access = > | loc | {
0 commit comments