aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-03-11 02:23:21 +0000
committerGitHub <noreply@github.com>2024-03-11 02:23:21 +0000
commit50a3019e0c4a294c48c5c2027bb33859b5d72dae (patch)
tree67e2b95bbf292755cc59862083a116536b09a62a
parentde66833c83011f6f547877afa7ae5209f2b92377 (diff)
parente7a7f165fb07916e31bf6ddd259fbd0cbf200dc2 (diff)
downloadperlweeklychallenge-club-50a3019e0c4a294c48c5c2027bb33859b5d72dae.tar.gz
perlweeklychallenge-club-50a3019e0c4a294c48c5c2027bb33859b5d72dae.tar.bz2
perlweeklychallenge-club-50a3019e0c4a294c48c5c2027bb33859b5d72dae.zip
Merge pull request #9724 from packy/master
Challenge 259 late solution by Packy Anderson
-rwxr-xr-xchallenge-259/packy-anderson/perl/ch-2.pl70
1 files changed, 70 insertions, 0 deletions
diff --git a/challenge-259/packy-anderson/perl/ch-2.pl b/challenge-259/packy-anderson/perl/ch-2.pl
new file mode 100755
index 0000000000..1532560d53
--- /dev/null
+++ b/challenge-259/packy-anderson/perl/ch-2.pl
@@ -0,0 +1,70 @@
+#!/usr/bin/env perl
+use v5.38;
+
+my $ID = qr/ (?<ID> \w+) /x;
+my $FIELD = qr/ (?<FIELD> \w+) /x;
+my $NUMBER = qr/ (?<NUMBER> \d+ [ \. \d+ ]? ) /x;
+my $STRING = qr/ (?<STRING> ([^"] | \\ | \\\" )+ ) /x;
+
+my $QUOTED_STRING = qr/ (?<QUOTED_STRING> " $STRING " ) /x;
+my $FIELD_VALUE = qr/ $FIELD \s* = \s* ( $NUMBER | $QUOTED_STRING ) \s* /x;
+my $FIELD_VALUES = qr/ (?<FIELD_VALUES> (?: $FIELD_VALUE \s* )* ) /x;
+
+# negative lookbehind and negative lookahead
+my $TEXT = qr/ (?<TEXT> (?<! {% ) .+ (?! %} ) ) /x;
+my $LINE = qr/ (?<LINE> \{% \s* $ID \s* $FIELD_VALUES \s* %\} ) /x;
+
+my $TOP = qr/^ (?: $LINE | $TEXT ) $/x;
+
+my $file = shift @ARGV;
+open my $fh, '<', $file;
+
+my %data;
+my @ids;
+my $in_id;
+
+while (my $line = <$fh>) {
+ $line =~ /$TOP/;
+
+ # is there a line with {% ... %} ?
+ if ($+{LINE}) {
+ my $id = $+{ID};
+ # is the id the end of a block?
+ if ($id =~ /^ end(\w+) $/x) { # capture after end
+ if (exists $data{$1}) { # it is!
+ $id = $1;
+ undef $in_id; # clear the id we're processing
+ if ($data{$id}{'text'}) {
+ # if there's text, remove the final "newline"
+ $data{$id}{'text'} =~ s/\\n$//;
+ }
+ next; # skip to next line of file
+ }
+ }
+ push @ids, $id; # keep list of ids in order
+ $in_id = $id; # keep track of the current id for text
+ # initialize base data for this id
+ $data{$id} = { name => $id };
+ # if we have fields...
+ my $field_values = $+{FIELD_VALUES};
+ # loop over field values and store them in the data
+ while ($field_values =~ /$FIELD_VALUE/g) {
+ my $value = $+{STRING} ? $+{STRING} : $+{NUMBER};
+ if ($+{NUMBER}) {
+ $value =~ s/\s+$//; # we're picking up trailing spaces
+ }
+ $data{$id}->{'fields'}->{ $+{FIELD} } = $value;
+ }
+
+ }
+ # if we have non-{% ... %} lines and we have an ID
+ elsif ($+{TEXT} && $in_id) {
+ # append a "newline" to the end
+ $data{$in_id}{'text'} .= $+{TEXT} . "\\n";
+ }
+}
+
+use Data::Dumper::Concise;
+foreach my $id (@ids) {
+ print Dumper($data{$id});
+}