Created
March 27, 2014 23:06
-
-
Save dwarring/9821113 to your computer and use it in GitHub Desktop.
advent 2013 day 14 - config combiner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
our %TestFiles = ( | |
'config1.ini' => q:to"END1", | |
[fruit] | |
apples = 0.50 | |
oranges = 0.70 | |
[veges] | |
broccoli = 0.25 | |
END1 | |
'config2.ini' => q:to"END2", | |
[fruit] | |
kiwis = 0.75 | |
[veges] | |
cabbage = 0.20 | |
END2 | |
); | |
my @files = %TestFiles.keys; | |
diag "files: {@files}"; | |
read_all(@files); | |
sub read_all(@files) { | |
my $read = Channel.new; | |
my $parsed = Channel.new; | |
read_worker(@files, $read); | |
parse_worker($read, $parsed) for 1..2; | |
my %all_config = await config_combiner($parsed); | |
diag %all_config.perl; | |
} | |
sub read_worker(@files, $dest) { | |
start { | |
for @files -> $file { | |
sleep .1; | |
die "no such file: $file" | |
unless %TestFiles{$file}:exists; | |
$dest.send(%TestFiles{$file}); | |
} | |
$dest.close(); | |
CATCH { $dest.fail($_) } | |
} | |
} | |
sub parse_worker($source, $dest) { | |
my grammar INIFile { | |
token TOP { | |
^ | |
<entries> | |
<section>+ | |
$ | |
} | |
token section { | |
'[' ~ ']' <key> \n | |
<entries> | |
} | |
token entries { | |
[ | |
| <entry> \n | |
| \n | |
]* | |
} | |
rule entry { <key> '=' <value> } | |
token key { \w+ } | |
token value { \N+ } | |
token ws { \h* } | |
} | |
my class INIFileActions { | |
method TOP($/) { | |
my %result; | |
%result<_> = $<entries>.ast; | |
for $<section> -> $sec { | |
%result{$sec<key>} = $sec<entries>.ast; | |
} | |
make %result; | |
} | |
method entries($/) { | |
my %entries; | |
for $<entry> -> $e { | |
%entries{$e<key>} = ~$e<value>; | |
} | |
make %entries; | |
} | |
} | |
start { | |
loop { | |
winner $source { | |
more $source { | |
diag "parsing: {$_}"; | |
if INIFile.parse($_, :actions(INIFileActions)) -> $parsed { | |
diag "parsed: {$parsed}"; | |
diag "ast: {$parsed.ast}"; | |
$dest.send($parsed.ast); | |
} | |
else { | |
diag "unable to parse"; | |
$dest.fail("Could not parse INI file"); | |
last; | |
} | |
} | |
done $source { last } | |
} | |
} | |
$dest.close(); | |
CATCH { $dest.fail($_) } | |
} | |
} | |
sub config_combiner($source) { | |
my $p = Promise.new; | |
my $v = $p.vow; | |
warn "combiner..."; | |
start { | |
my %result; | |
loop { | |
winner $source { | |
more $source { | |
for %^content.kv -> $sec, %kvs { | |
warn "sec: $sec"; | |
for %kvs.kv -> $k, $v { | |
warn "\tcombining: k={$k} v={$v}"; | |
%result{$sec}{$k} = $v; | |
} | |
} | |
} | |
done $source { last } | |
} | |
} | |
$v.keep(%result); | |
CATCH { $v.break($_) } | |
} | |
return $p; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment