@@ -59,13 +59,14 @@ const octet: Parser<number> = guard(
5959// the quantifier requires hex digits — a second ":" causes backtracking.
6060const hexChain = regex ( / [ 0 - 9 a - f A - F ] { 1 , 4 } (?: : [ 0 - 9 a - f A - F ] { 1 , 4 } ) * / , "hex-chain" ) ;
6161
62- // Regex for zero or more hex groups each with a trailing colon, e.g. "ffff:a:".
62+ // Regex for one or more hex groups each with a trailing colon, e.g. "ffff:a:".
6363// Used in IPv4-mapped IPv6 to match middle groups before the IPv4 suffix.
6464// Unlike hexChain this stops as soon as the next group would not be followed
6565// by ":" — so for "ffff:192.0.2.128" it matches only "ffff:" because "192."
66- // has no trailing colon.
66+ // has no trailing colon. Wrapped with optional() in seq() to handle the
67+ // zero-group case (e.g. "::192.0.2.128").
6768const hexGroupsPrefix = regex (
68- / (?: [ 0 - 9 a - f A - F ] { 1 , 4 } : ) * / ,
69+ / (?: [ 0 - 9 a - f A - F ] { 1 , 4 } : ) + / ,
6970 "hex-groups-prefix" ,
7071) ;
7172
@@ -213,17 +214,18 @@ export const IPAddress: DefinedLanguage<IPAddressOutputs> = defineLanguage<
213214 // ::192.0.2.128 (IPv4-compatible, deprecated but parseable)
214215 // 2001:db8::ffff:192.0.2.128
215216 //
216- // The `hexGroupsPrefix` regex matches zero -or-more "hex:" tokens and stops
217+ // The `hexGroupsPrefix` regex matches one -or-more "hex:" tokens and stops
217218 // before the IPv4 octet because IPv4 octets are not followed by ":".
218219 // This prevents `hexChain` from greedily consuming "ffff:192" as two hex
219- // groups and then failing on the trailing ".".
220+ // groups and then failing on the trailing ".". Wrapped with optional() to
221+ // handle the zero-group case (e.g. "::192.0.2.128").
220222 IPv6v4Mapped : ( s ) =>
221223 guard (
222224 map (
223225 seq (
224226 optional ( hexChain ) , // optional leading hex groups before "::"
225227 str ( "::" ) ,
226- hexGroupsPrefix , // zero or more "hex:" groups before IPv4
228+ optional ( hexGroupsPrefix ) , // zero or more "hex:" groups before IPv4
227229 s . IPv4 , // IPv4 address occupying the last 32 bits
228230 ) ,
229231 ( _ , b , a ) => b . text . substring ( b . index , a . index ) ,
0 commit comments