From f3bb477b370ef28264813c6cb8e2590030faebf0 Mon Sep 17 00:00:00 2001 From: Packy Anderson Date: Sun, 10 Mar 2024 22:16:28 -0400 Subject: Challenge 259 late solution by Packy Anderson * Perl - Task 2 --- challenge-259/packy-anderson/perl/ch-2.pl | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 challenge-259/packy-anderson/perl/ch-2.pl 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..5be4e1fb4e --- /dev/null +++ b/challenge-259/packy-anderson/perl/ch-2.pl @@ -0,0 +1,71 @@ +#!/usr/bin/env perl +use v5.38; + +my $ID = qr/ (? \w+) /x; +my $FIELD = qr/ (? \w+) /x; +my $NUMBER = qr/ (? \d+ [ \. \d+ ]? ) /x; +my $STRING = qr/ (? ([^"] | \\ | \\\" )+ ) /x; + +my $QUOTED_STRING = qr/ (? " $STRING " ) /x; +my $FIELD_VALUE = qr/ $FIELD \s* = \s* ( $NUMBER | $QUOTED_STRING ) \s* /x; +my $FIELD_VALUES = qr/ (? (?: $FIELD_VALUE \s* )* ) /x; + +# negative lookbehind and negative lookahead +my $TEXT = qr/ (? (? \{% \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>) { + say 'L: ' . $line; + $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}); +} -- cgit