/
INI.pm
91 lines (71 loc) · 2.37 KB
/
INI.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use v6;
module Config::INI:<github:tadzik 0.1>;
grammar INI {
token TOP {
<.eol>*
<toplevel>?
<sections>*
<.eol>*
$
}
token toplevel { <keyval>* }
token sections { <header> <keyval>* }
token header { ^^ \h* '[' ~ ']' $<text>=[\w | \h]+ \h* <.eol>+ }
token keyval { ^^ \h* <key> \h* '=' \h* <value>? \h* <.eol>+ }
regex key { <![\[]> <-[;=]>+ }
regex value { [ <![;]> \N ]+ }
# TODO: This should be just overriden \n once Rakudo implements it
token eol { [ ';' \N+ ]? \n }
}
class INI::Actions {
method TOP ($/) { make { '_' => $<toplevel>[0].ast, $<sections>».ast } }
method toplevel ($/) { make $<keyval>».ast.hash }
method sections ($/) { make $<header><text>.Str => $<keyval>».ast.hash }
# TODO: The .trim is useless, <!after \h> should be added to key regex,
# once Rakudo implements it
method keyval ($/) { make $<key>.Str.trim => $<value>.Str.trim }
}
our sub parse (Str $string) {
INI.parse($string, :actions(INI::Actions.new)).ast;
}
our sub parse_file (Str $file) {
my $conf = slurp $file;
my $parseconf = 0;
my %result;
try {
%result = parse $conf;
CATCH {
$parseconf = 1
}
}
if $parseconf {
die "Failed parsing $file"
}
return %result
}
=begin pod
=head1 NAME
Config::INI - parse standard configuration files (.ini files)
=head1 SYNOPSIS
use Config::INI;
my %hash = Config::INI::parse_file('config.ini');
#or
%hash = Config::INI::parse($file_contents);
say %hash<_><root_property_key>;
say %hash<section><in_section_key>;
=head1 DESCRIPTION
This module provides 2 functions: parse() and parse_file(), both taking
one C<Str> argument, where parse_file is just parse(slurp $file).
Both return a hash which keys are either toplevel keys or a section
names. For example, the following config file:
foo=bar
[section]
another=thing
would result in the following hash:
{ '_' => { foo => "bar" }, section => { another => "thing" } }
=head1 CAVEATS
Parser will fail if a file contains either empty sections, or keys
without specified value (as in 'foo='). Whether this is a bug
or a feature, time will tell.
=end pod
# vim: ft=perl6