use v6.d.PREVIEW;
grammar Message {
regex TOP {
<headers>
<separator>
<body>
}
token newline { [\x0d\x0a] | [\x0a\x0d] | \x0a | \x0d }
token separator {
[\x0a\x0d\x0a\x0d] | [\x0d\x0a\x0d\x0a] | \x0a ** 2 | \x0d ** 2
}
token body { .* }
regex headers {
<header>+ % <newline>
}
regex header {
<name> \: \h* <value>
|| <junk>
}
token name {
<-[:\s]>+
}
regex value {
<line>+ % [<newline> \h+]
}
token line { \N* }
token junk { \N+ }
}
class Message-actions {
method TOP($/) {
make %( headers => $/<headers>.made, body => $/<body>.Str );
}
method headers($/) {
make %( |$/<header>ยป.made );
}
method header($/) {
make $/<junk> ?? () !! ( $/<name>.Str => $/<value>.made );
}
method value($/) {
make $/<line>.join(' ')
}
}
sub MAIN(*@files) {
say "Starting";my $start = now;
my @messages = @files.race(:degree(10) :batch(100)).map({
my $email = $_.IO.slurp(:enc<utf8-c8>);
my $match = Message.parse($email,:actions(Message-actions.new));
});
say "Took { now - $start } for { +@messages } messages";
}