@@ -315,8 +315,20 @@ struct expression_statement_node
315
315
struct capture {
316
316
postfix_expression_node* capture_expr;
317
317
std::string str = {};
318
+ auto operator ==(postfix_expression_node* p) { return capture_expr == p; }
319
+ };
320
+
321
+ struct capture_group {
322
+ std::vector<capture> members;
323
+
324
+ auto add (postfix_expression_node* p) -> void {
325
+ members.push_back ({p});
326
+ }
327
+
328
+ auto remove (postfix_expression_node* p) -> void;
329
+
330
+ ~capture_group ();
318
331
};
319
- using capture_group = std::vector<capture>;
320
332
321
333
struct postfix_expression_node
322
334
{
@@ -336,6 +348,12 @@ struct postfix_expression_node
336
348
std::vector<term> ops;
337
349
capture_group* cap_grp = {};
338
350
351
+ ~postfix_expression_node () {
352
+ if (cap_grp) {
353
+ cap_grp->remove (this );
354
+ }
355
+ }
356
+
339
357
auto position () const -> source_position
340
358
{
341
359
assert (expr);
@@ -345,6 +363,25 @@ struct postfix_expression_node
345
363
auto visit (auto & v, int depth) -> void;
346
364
};
347
365
366
+ auto capture_group::remove (postfix_expression_node* p) -> void {
367
+ p->cap_grp = nullptr ;
368
+ auto old_size = members.size ();
369
+ std::erase (members, p);
370
+ assert (members.size () == old_size-1 );
371
+ }
372
+
373
+ capture_group::~capture_group () {
374
+ assert (members.empty ());
375
+ // We shouldn't need to do this:
376
+ // while (!members.empty()) {
377
+ // remove(members.front().capture_expr);
378
+ // }
379
+ // if the capture_group outlives the tree of things that can point to it
380
+ // => each node with a capture_group should declare it as the first member
381
+ // before any other node that could own a postfix_expression that could
382
+ // point back up to that capture_group
383
+ }
384
+
348
385
auto prefix_expression_node::position () const -> source_position
349
386
{
350
387
if (std::ssize (ops) > 0 ) {
@@ -719,12 +756,15 @@ struct inspect_expression_node
719
756
720
757
struct contract_node
721
758
{
759
+ // Declared first, because it should outlive any owned
760
+ // postfix_expressions that could refer to it
761
+ capture_group captures;
762
+
722
763
source_position open_bracket;
723
764
token const * kind = {};
724
765
std::unique_ptr<id_expression_node> group;
725
766
std::unique_ptr<logical_or_expression_node> condition;
726
767
token const * message = {};
727
- capture_group captures;
728
768
729
769
contract_node ( source_position pos ) : open_bracket{pos} { }
730
770
@@ -905,6 +945,10 @@ struct function_type_node
905
945
906
946
struct declaration_node
907
947
{
948
+ // Declared first, because it should outlive any owned
949
+ // postfix_expressions that could refer to it
950
+ capture_group captures;
951
+
908
952
source_position pos;
909
953
std::unique_ptr<unqualified_id_node> identifier;
910
954
@@ -919,7 +963,6 @@ struct declaration_node
919
963
source_position equal_sign = {};
920
964
source_position decl_end = {};
921
965
std::unique_ptr<statement_node> initializer;
922
- capture_group captures;
923
966
924
967
declaration_node* parent_scope = nullptr ;
925
968
@@ -1504,7 +1547,7 @@ class parser
1504
1547
return {};
1505
1548
}
1506
1549
n->cap_grp = current_capture_groups.back ();
1507
- n->cap_grp ->push_back ({n.get ()});
1550
+ n->cap_grp ->add ({n.get ()});
1508
1551
}
1509
1552
1510
1553
auto term = postfix_expression_node::term{&curr ()};
@@ -2900,7 +2943,7 @@ class parser
2900
2943
n->pos = start;
2901
2944
auto guard =
2902
2945
captures_allowed
2903
- ? make_unique<capture_groups_stack_guard>(this , &n->captures )
2946
+ ? std:: make_unique<capture_groups_stack_guard>(this , &n->captures )
2904
2947
: std::unique_ptr<capture_groups_stack_guard>()
2905
2948
;
2906
2949
@@ -3198,8 +3241,8 @@ class parse_tree_printer : printing_visitor
3198
3241
if (n.message ) {
3199
3242
o << pre (indent+1 ) << " message: " << std::string_view (*n.message ) << " \n " ;
3200
3243
}
3201
- if (!n.captures .empty ()) {
3202
- o << pre (indent+1 ) << " captures: " << n.captures .size () << " \n " ;
3244
+ if (!n.captures .members . empty ()) {
3245
+ o << pre (indent+1 ) << " captures: " << n.captures .members . size () << " \n " ;
3203
3246
}
3204
3247
}
3205
3248
@@ -3217,8 +3260,8 @@ class parse_tree_printer : printing_visitor
3217
3260
auto start (declaration_node const & n, int indent) -> void
3218
3261
{
3219
3262
o << pre (indent) << " declaration\n " ;
3220
- if (!n.captures .empty ()) {
3221
- o << pre (indent+1 ) << " captures: " << n.captures .size () << " \n " ;
3263
+ if (!n.captures .members . empty ()) {
3264
+ o << pre (indent+1 ) << " captures: " << n.captures .members . size () << " \n " ;
3222
3265
}
3223
3266
}
3224
3267
0 commit comments