@@ -40,6 +40,7 @@ import {
4040 PrefixNot ,
4141 PropertyRead ,
4242 RecursiveAstVisitor ,
43+ RegularExpressionLiteral ,
4344 SafeCall ,
4445 SafeKeyedRead ,
4546 SafePropertyRead ,
@@ -581,6 +582,9 @@ enum ParseContextFlags {
581582 Writable = 1 ,
582583}
583584
585+ /** Possible flags that can be used in a regex literal. */
586+ const SUPPORTED_REGEX_FLAGS = new Set ( [ 'd' , 'g' , 'i' , 'm' , 's' , 'u' , 'v' , 'y' ] ) ;
587+
584588class _ParseAST {
585589 private rparensExpected = 0 ;
586590 private rbracketsExpected = 0 ;
@@ -1178,6 +1182,8 @@ class _ParseAST {
11781182 } else if ( this . next . isPrivateIdentifier ( ) ) {
11791183 this . _reportErrorForPrivateIdentifier ( this . next , null ) ;
11801184 return new EmptyExpr ( this . span ( start ) , this . sourceSpan ( start ) ) ;
1185+ } else if ( this . next . isRegExpBody ( ) ) {
1186+ return this . parseRegularExpressionLiteral ( ) ;
11811187 } else if ( this . index >= this . tokens . length ) {
11821188 this . error ( `Unexpected end of expression: ${ this . input } ` ) ;
11831189 return new EmptyExpr ( this . span ( start ) , this . sourceSpan ( start ) ) ;
@@ -1618,6 +1624,49 @@ class _ParseAST {
16181624 return new TemplateLiteral ( this . span ( start ) , this . sourceSpan ( start ) , elements , expressions ) ;
16191625 }
16201626
1627+ private parseRegularExpressionLiteral ( ) {
1628+ const bodyToken = this . next ;
1629+ this . advance ( ) ;
1630+
1631+ if ( ! bodyToken . isRegExpBody ( ) ) {
1632+ return new EmptyExpr ( this . span ( this . inputIndex ) , this . sourceSpan ( this . inputIndex ) ) ;
1633+ }
1634+
1635+ let flagsToken : Token | null = null ;
1636+
1637+ if ( this . next . isRegExpFlags ( ) ) {
1638+ flagsToken = this . next ;
1639+ this . advance ( ) ;
1640+ const seenFlags = new Set < string > ( ) ;
1641+
1642+ for ( let i = 0 ; i < flagsToken . strValue . length ; i ++ ) {
1643+ const char = flagsToken . strValue [ i ] ;
1644+
1645+ if ( ! SUPPORTED_REGEX_FLAGS . has ( char ) ) {
1646+ this . error (
1647+ `Unsupported regular expression flag "${ char } ". The supported flags are: ` +
1648+ Array . from ( SUPPORTED_REGEX_FLAGS , ( f ) => `"${ f } "` ) . join ( ', ' ) ,
1649+ flagsToken . index + i ,
1650+ ) ;
1651+ } else if ( seenFlags . has ( char ) ) {
1652+ this . error ( `Duplicate regular expression flag "${ char } "` , flagsToken . index + i ) ;
1653+ } else {
1654+ seenFlags . add ( char ) ;
1655+ }
1656+ }
1657+ }
1658+
1659+ const start = bodyToken . index ;
1660+ const end = flagsToken ? flagsToken . end : bodyToken . end ;
1661+
1662+ return new RegularExpressionLiteral (
1663+ this . span ( start , end ) ,
1664+ this . sourceSpan ( start , end ) ,
1665+ bodyToken . strValue ,
1666+ flagsToken ? flagsToken . strValue : null ,
1667+ ) ;
1668+ }
1669+
16211670 /**
16221671 * Consume the optional statement terminator: semicolon or comma.
16231672 */
0 commit comments