@@ -17,11 +17,6 @@ const regExpFlags = [
1717
1818// type RegExpFlag = typeof regExpFlags[number]
1919
20- // TODO:
21- // - parse \uXXXX notation
22- // - allow empty strings, e.g. regex like "(|)"
23- // const emptyString = P.string('').map(() => RE.epsilon)
24-
2520const startMarker = P . optional ( P . string ( '^' ) ) . map ( marker => {
2621 if ( marker === undefined ) {
2722 return RE . star ( RE . anySingleChar )
@@ -225,6 +220,14 @@ function lookAheadOp(): P.Expr.BinaryOperator<RE.ExtRegex | undefined, RE.ExtReg
225220 )
226221 )
227222}
223+
224+ /**
225+ * Parses expression like `(a|b)`. The left- and right operand are optional,
226+ * e.g. `(a|)` and `(|)` are also valid expressions.
227+ */
228+ function unionOp ( ) : P . Expr . BinaryOperator < RE . ExtRegex | undefined , RE . ExtRegex > {
229+ return P . string ( '|' ) . map ( _ => ( left , right ) => RE . union ( left ?? RE . epsilon , right ?? RE . epsilon ) )
230+ }
228231
229232function regex ( ) : P . Parser < RE . ExtRegex > {
230233 return P . lazy ( ( ) => P . Expr . makeExprParser < RE . ExtRegex > (
@@ -236,7 +239,7 @@ function regex(): P.Parser<RE.ExtRegex> {
236239 { type : 'postfix' , op : P . string ( '?' ) . map ( _ => RE . optional ) } ,
237240 { type : 'infixRight' , op : P . string ( '' ) . map ( _ => RE . concat ) } ,
238241 { type : 'infixRightOptional' , op : lookAheadOp ( ) } ,
239- { type : 'infixRight ' , op : P . string ( '|' ) . map ( _ => RE . union ) } ,
242+ { type : 'infixRightOptional ' , op : unionOp ( ) } ,
240243 ]
241244 ) )
242245}
0 commit comments