@@ -513,7 +513,7 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
513513 UnresolvedDeclRefExpr *Operator;
514514
515515 // First check to see if we have the start of a regex literal `/.../`.
516- tryLexRegexLiteral (/* mustBeRegex */ true );
516+ tryLexRegexLiteral (/* forUnappliedOperator */ false );
517517
518518 switch (Tok.getKind ()) {
519519 default :
@@ -880,56 +880,70 @@ UnresolvedDeclRefExpr *Parser::parseExprOperator() {
880880 return new (Context) UnresolvedDeclRefExpr (name, refKind, DeclNameLoc (loc));
881881}
882882
883- void Parser::tryLexRegexLiteral (bool mustBeRegex ) {
883+ void Parser::tryLexRegexLiteral (bool forUnappliedOperator ) {
884884 if (!Context.LangOpts .EnableBareSlashRegexLiterals )
885885 return ;
886886
887+ // Never a regex literal.
888+ if (Tok.isEscapedOperator ())
889+ return ;
890+
887891 // Check to see if we have a regex literal `/.../`, optionally with a prefix
888892 // operator e.g `!/.../`.
893+ bool mustBeRegex = false ;
889894 switch (Tok.getKind ()) {
890895 case tok::oper_prefix:
896+ // Prefix operators may contain `/` characters, so this may not be a regex,
897+ // and as such need to make sure we have a closing `/`. The first character
898+ // heuristics aren't relevant here as a right-bound operator will not have
899+ // a space, tab, or `)` character.
900+ break ;
891901 case tok::oper_binary_spaced:
892- case tok::oper_binary_unspaced: {
893- // Check to see if we have an operator containing '/'.
894- auto slashIdx = Tok.getText ().find (" /" );
895- if (slashIdx == StringRef::npos)
896- break ;
902+ case tok::oper_binary_unspaced:
903+ // When re-lexing for a 'proper' expression, binary operators are always
904+ // invalid, so we can be confident in always lexing a regex literal.
905+ mustBeRegex = !forUnappliedOperator;
906+ break ;
907+ default :
908+ // We only re-lex regex literals for operator tokens.
909+ return ;
910+ }
897911
898- CancellableBacktrackingScope backtrack (*this );
899- {
900- Optional<Lexer::ForwardSlashRegexRAII> regexScope;
901- regexScope.emplace (*L, mustBeRegex);
902-
903- // Try re-lex as a `/.../` regex literal, this will split an operator if
904- // necessary.
905- L->restoreState (getParserPosition ().LS , /* enableDiagnostics*/ true );
906-
907- // If we didn't split a prefix operator, reset the regex lexing scope.
908- // Otherwise, we want to keep it in place for the next token.
909- auto didSplit = L->peekNextToken ().getLength () == slashIdx;
910- if (!didSplit)
911- regexScope.reset ();
912-
913- // Discard the current token, which will be replaced by the re-lexed
914- // token, which will either be a regex literal token, a prefix operator,
915- // or the original unchanged token.
916- discardToken ();
917-
918- // If we split a prefix operator from the regex literal, and are not sure
919- // whether this should be a regex, backtrack if we didn't end up lexing a
920- // regex literal.
921- if (didSplit && !mustBeRegex &&
922- !L->peekNextToken ().is (tok::regex_literal)) {
923- return ;
924- }
912+ // Check to see if we have an operator containing '/'.
913+ auto slashIdx = Tok.getText ().find (" /" );
914+ if (slashIdx == StringRef::npos)
915+ return ;
916+
917+ CancellableBacktrackingScope backtrack (*this );
918+ {
919+ Optional<Lexer::ForwardSlashRegexRAII> regexScope;
920+ regexScope.emplace (*L, mustBeRegex);
921+
922+ // Try re-lex as a `/.../` regex literal, this will split an operator if
923+ // necessary.
924+ L->restoreState (getParserPosition ().LS , /* enableDiagnostics*/ true );
925+
926+ // If we didn't split a prefix operator, reset the regex lexing scope.
927+ // Otherwise, we want to keep it in place for the next token.
928+ auto didSplit = L->peekNextToken ().getLength () == slashIdx;
929+ if (!didSplit)
930+ regexScope.reset ();
931+
932+ // Discard the current token, which will be replaced by the re-lexed
933+ // token, which will either be a regex literal token, a prefix operator,
934+ // or the original unchanged token.
935+ discardToken ();
925936
926- // Otherwise, accept the result.
927- backtrack.cancelBacktrack ();
937+ // If we split a prefix operator from the regex literal, and are not sure
938+ // whether this should be a regex, backtrack if we didn't end up lexing a
939+ // regex literal.
940+ if (didSplit && !mustBeRegex &&
941+ !L->peekNextToken ().is (tok::regex_literal)) {
942+ return ;
928943 }
929- break ;
930- }
931- default :
932- break ;
944+
945+ // Otherwise, accept the result.
946+ backtrack.cancelBacktrack ();
933947 }
934948}
935949
@@ -3226,7 +3240,7 @@ ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
32263240 // First check to see if we have the start of a regex literal `/.../`. We
32273241 // need to do this before handling unapplied operator references, as e.g
32283242 // `(/, /)` might be a regex literal.
3229- tryLexRegexLiteral (/* mustBeRegex */ false );
3243+ tryLexRegexLiteral (/* forUnappliedOperator */ true );
32303244
32313245 // See if we have an operator decl ref '(<op>)'. The operator token in
32323246 // this case lexes as a binary operator because it neither leads nor
0 commit comments