use v6-alpha; use File::Spec; my $dat = splitpath($*PROGRAM_NAME)[1] ~ "/p6explain.dat"; my %things; # Parsing the dat my $fh = open $dat err die "Couldn't open \"$dat\" for reading: $!\n"; for =$fh { state $cur_entry; # Skip comments # next if m:Perl5/^\s*a/; # Extract title when m:Perl5/^(\S.*)$/ { $cur_entry = $0; } # Extract explanation when m:Perl5/^(\s+)(.+)$/ { %things{$cur_entry} ~= "$1\n"; } } # Expansion # This part is a bit complicated, it'd be much easier if # s:Perl5/.../{ any ... }/ # would work in Pugs. But as it doesn't currently (read: it will do tomorrow # :)), we have to fake it by using lots of loops. for %things.kv -> $key_, $value { my &deref = -> $key_ { my @ret = ($key_); # Check if we have to substitute some references. while any(@ret) ~~ rx:Perl5/\@\w+/ { my @new_ret; for @ret -> $key { if $key ~~ rx:Perl5/\@(\w+)/ { # This is the thing we want to replace, for example 'infix_ops'. my $ref = $0; # These are all substitutions. my @subst = split rx:Perl5/\s+/, %things{$ref}; # These are the original keys. my @k = ($key) xx @subst; # Now we substitute all @infix_ops by the values in @subst. $_ ~~ s:Perl5/\@\Q$ref/{ shift @subst }/ for @k; # Finally, we add that to our array of return values. push @new_ret, @k; } else { push @new_ret, $key; } } @ret = @new_ret; } @ret; }; my @new = deref $key_; %things{$_} //= $value for @new; } die "Usage: $*PROGRAM_NAME thing1_to_explain thing2_to_explain...\n" unless @*ARGS; # Finally, output! for @*ARGS -> $lookup { say $lookup; say " $_" for split "\n", %things{$lookup} // "Sorry, didn't found an entry for \"$lookup\".\n"; }