Parse an IP Address
grammar IP_Addr {
token TOP { ^ [ <IPv4> | <IPv6> ] $ }
token IPv4 {
[ <d8> +% '.' ] <?{ $<d8> == 4 }> <port>?
{ @*by8 = @$<d8> }
}
token IPv6 {
| <ipv6>
| '[' <ipv6> ']' <port>
}
token ipv6 {
| <h16> +% ':' <?{ $<h16> == 8 }>
{ @*by16 = @$<h16> }
| [ (<h16>) +% ':']? '::' [ (<h16>) +% ':' ]? <?{ @$0 + @$1 ≤ 8 }>
{ @*by16 = |@$0, |('0' xx 8 - (@$0 + @$1)), |@$1 }
| '::ffff:' <IPv4>
{ @*by16 = |('0' xx 5), 'ffff', |(by8to16 @*by8) }
}
token d8 { (\d+) <?{ $0 < 256 }> }
token d16 { (\d+) <?{ $0 < 65536 }> }
token h16 { (<xdigit>+) <?{ $0.chars ≤ 4 }> }
token port {
':' <d16> { $*port = +$<d16> }
}
}
sub by8to16 (@m) { gather for @m -> $a,$b { take ($a * 256 + $b).fmt("%04x") } }
my @cases = <
127.0.0.1
127.0.0.1:80
::1
[::1]:80
2605:2700:0:3::4713:93e3
[2605:2700:0:3::4713:93e3]:80
2001:db8:85a3:0:0:8a2e:370:7334
2001:db8:85a3::8a2e:370:7334
[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443
192.168.0.1
::ffff:192.168.0.1
::ffff:71.19.147.227
[::ffff:71.19.147.227]:80
::
256.0.0.0
g::1
0000
0000:0000
0000:0000:0000:0000:0000:0000:0000:0000
0000:0000:0000::0000:0000
0000::0000::0000:0000
ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
ffff:ffff:ffff:fffg:ffff:ffff:ffff:ffff
fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
fff:ffff:0:ffff:ffff:ffff:ffff:ffff
>;
for @cases -> $addr {
my @*by8;
my @*by16;
my $*port;
IP_Addr.parse($addr);
say $addr;
if @*by16 {
say " IPv6: ", @*by16.map({:16(~$_)})».fmt("%04x").join;
say " Port: ", $*port if $*port;
}
elsif @*by8 {
say " IPv4: ", @*by8».fmt("%02x").join;
say " Port: ", $*port if $*port;
}
else {
say " BOGUS!";
}
say '';
}
Output:
127.0.0.1
IPv4: 7f000001
127.0.0.1:80
IPv4: 7f000001
Port: 80
::1
IPv6: 00000000000000000000000000000001
[::1]:80
IPv6: 00000000000000000000000000000001
Port: 80
2605:2700:0:3::4713:93e3
IPv6: 260527000000000300000000471393e3
[2605:2700:0:3::4713:93e3]:80
IPv6: 260527000000000300000000471393e3
Port: 80
2001:db8:85a3:0:0:8a2e:370:7334
IPv6: 20010db885a3000000008a2e03707334
2001:db8:85a3::8a2e:370:7334
IPv6: 20010db885a3000000008a2e03707334
[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443
IPv6: 20010db885a308d313198a2e03707348
Port: 443
192.168.0.1
IPv4: c0a80001
::ffff:192.168.0.1
IPv6: 00000000000000000000ffffc0a80001
::ffff:71.19.147.227
IPv6: 00000000000000000000ffff471393e3
[::ffff:71.19.147.227]:80
IPv6: 00000000000000000000ffff471393e3
Port: 80
::
IPv6: 00000000000000000000000000000000
256.0.0.0
BOGUS!
g::1
BOGUS!
0000
BOGUS!
0000:0000
BOGUS!
0000:0000:0000:0000:0000:0000:0000:0000
IPv6: 00000000000000000000000000000000
0000:0000:0000::0000:0000
IPv6: 00000000000000000000000000000000
0000::0000::0000:0000
IPv6: 00000000000000000000000000000000
ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
IPv6: ffffffffffffffffffffffffffffffff
ffff:ffff:ffff:fffg:ffff:ffff:ffff:ffff
BOGUS!
fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
IPv6: 0fffffffffffffffffffffffffffffff
fff:ffff:0:ffff:ffff:ffff:ffff:ffff
IPv6: 0fffffff0000ffffffffffffffffffff
Last updated