#!/usr/bin/env raku
grammar INI {
rule TOP { ^^ [ <comment> || <kvpair> || <section> ]* }
token comment { [ ';' || '#' ] \N* }
token kvpair { $<key> = \w+ \s* '=' \s* $<value> = \N* }
token section { '[' $<key> = \w+ ']' }
}
class INI-actions {
has $.title is rw = Nil;
has @.kv is rw = [];
has @.data is rw = [];
method update { @.data.push({$.title => [@.kv]}) if $.title }
method TOP($/) { self.update; make @.data }
method kvpair($/) {
$.title ??
@.kv.push({$<key> => $<value>.Str})
!!
@.data.push({$<key> => $<value>.Str})
}
method section($/) {
self.update;
$.title = $<key>;
@.kv = [];
}
}
my $content = q:to/INI/;
; foobar
foo = bar
[toto_tata]
toto = tata
titi = tutu
# some comments
[foobar]
fi = fo
[some_foo]
[tada_foo]
[toudoufoo]
INI
my @ini = try { INI.parse($content, :actions(INI-actions.new)).made } // die "Couldnt parse the INI";
.say for @ini;