@@ -425,9 +425,38 @@ class Parser {
425
425
llvm::Optional<SyntaxParsingContext> SynContext;
426
426
bool Backtrack = true ;
427
427
428
+ // / A token receiver used by the parser in the back tracking scope. This
429
+ // / receiver will save any consumed tokens during this back tracking scope.
430
+ // / After the scope ends, it either transfers the saved tokens to the old receiver
431
+ // / or discard them.
432
+ struct DelayedTokenReceiver : ConsumeTokenReceiver {
433
+ // / Keep track of the old token receiver in the parser so that we can recover
434
+ // / after the backtracking sope ends.
435
+ llvm::SaveAndRestore<ConsumeTokenReceiver*> savedConsumer;
436
+
437
+ // Whether the tokens should be transferred to the original receiver.
438
+ // When the back tracking scope will actually back track, this should be false;
439
+ // otherwise true.
440
+ bool shouldTransfer = false ;
441
+ std::vector<Token> delayedTokens;
442
+ DelayedTokenReceiver (ConsumeTokenReceiver *&receiver):
443
+ savedConsumer (receiver, this ) {}
444
+ void receive (Token tok) override {
445
+ delayedTokens.push_back (tok);
446
+ }
447
+ ~DelayedTokenReceiver () {
448
+ if (!shouldTransfer)
449
+ return ;
450
+ for (auto tok: delayedTokens) {
451
+ savedConsumer.get ()->receive (tok);
452
+ }
453
+ }
454
+ } TempReceiver;
455
+
428
456
public:
429
457
BacktrackingScope (Parser &P)
430
- : P(P), PP(P.getParserPosition()), DT(P.Diags) {
458
+ : P(P), PP(P.getParserPosition()), DT(P.Diags),
459
+ TempReceiver (P.TokReceiver) {
431
460
SynContext.emplace (P.SyntaxContext );
432
461
SynContext->setBackTracking ();
433
462
}
@@ -440,8 +469,8 @@ class Parser {
440
469
SynContext->setTransparent ();
441
470
SynContext.reset ();
442
471
DT.commit ();
472
+ TempReceiver.shouldTransfer = true ;
443
473
}
444
-
445
474
};
446
475
447
476
// / RAII object that, when it is destructed, restores the parser and lexer to
0 commit comments