-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.pm6
executable file
·91 lines (75 loc) · 2.14 KB
/
Parser.pm6
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 Grammar;
class pCNI is Hash {
has Str $.prefix = '';
# utility to get proper prefixes
method prefixify($key) {
if $!prefix { return $!prefix ~ '.' ~ $key; }
return $key;
}
# parsing methods
method TOP($/) {
my %out;
for $<stmt> { %out = %out, $_.made || (%); }
make %out;
}
method stmt:sym<keyval> ($/) {
make $<kv>.made;
}
method stmt:sym<rkeyval> ($/) {
make $<rkv>.made;
}
method header($/) { $!prefix = $<key>.made; }
method kv($/) { make self.prefixify($<key>.made) => $<value>.made; }
method rkv($/) { make self.prefixify($<key>.made) => $<value>.made; }
# parsing passthrough-ish
method parse($target) {
my $match = gCNI.parse($target, actions => self);
fail "Parse failed" if ! $match.defined;
self = self, $match.made;
return $match;
}
# recommended API methods
# recommended ones for export start with a capital
# walk over keys matching a matcher
# this is an internal routine for providing the other stuff
method walk($m, &c) {
for self.keys -> $k {
&c($k) if $k ~~ $m;
}
}
# private common code between SubRec and SubFlat
method sub($prefix, $cc) {
my $mr = /^/;
given $prefix {
when '' { succeed; }
default { $mr = /^ $prefix '.' /; }
}
my $m = / <$mr> (<$cc>+) $/;
my %out;
self.walk: $m, {
my $k = $^a.subst: $mr;
%out<<$k>> = self<<$^a>>;
}
return %out;
}
# returns kv pairs of all keys in a section, with the section stripped
method SubTree($prefix) {
return self.sub: $prefix, /./;
}
# returns kv pairs of all keys directly in a section, with the section stripped
method SubLeaves($prefix) {
return self.sub: $prefix, /<-[.]>/;
}
# returns a list of all values in a section
method ListTree($prefix) {
return self.SubTree($prefix).values.list;
}
# returns a list of all values directly in the section
method ListLeaves($prefix) {
return self.SubLeaves($prefix).values.list;
}
# you are also recommended to implement the following along the same lines:
# WalkLeaves and WalkTree (walker pattern, takes a function/closure)
# KeyLeaves and KeyTree (list of actual keys)
# SectionLeaves and SectionTree (list of non-leaf nodes in the pseudo-trie)
}