aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Ferrari <fluca1978@gmail.com>2024-03-04 09:39:17 +0100
committerLuca Ferrari <fluca1978@gmail.com>2024-03-04 14:19:40 +0100
commit2b5457f572cf53ed6ff5b679de754feafa5b8eb6 (patch)
treedee7a4007ed79c9bbbc87a1000d910eae4b80396
parentad381c1123e47114d3d98f1749f9f354eebafcdd (diff)
downloadperlweeklychallenge-club-2b5457f572cf53ed6ff5b679de754feafa5b8eb6.tar.gz
perlweeklychallenge-club-2b5457f572cf53ed6ff5b679de754feafa5b8eb6.tar.bz2
perlweeklychallenge-club-2b5457f572cf53ed6ff5b679de754feafa5b8eb6.zip
PWC 259
Task 1 Raku done Task 2 Raku done Task 1 PL/Perl done Task 2 PL/Perl done Task 1 PL/PgSQL done Task 2 PL/PgSQL done Task 1 Python done Task 2 Python done Task 1 PL/Java done Task 2 PL/Java done
-rw-r--r--challenge-259/luca-ferrari/blog-1.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-10.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-2.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-3.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-4.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-5.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-6.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-7.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-8.txt1
-rw-r--r--challenge-259/luca-ferrari/blog-9.txt1
-rw-r--r--challenge-259/luca-ferrari/pljava/pom.xml6
-rw-r--r--challenge-259/luca-ferrari/pljava/src/main/java/Task1.java73
-rw-r--r--challenge-259/luca-ferrari/pljava/src/main/java/Task2.java107
-rw-r--r--challenge-259/luca-ferrari/plperl/ch-1.plperl41
-rw-r--r--challenge-259/luca-ferrari/plperl/ch-2.plperl58
-rw-r--r--challenge-259/luca-ferrari/plpgsql/ch-1.sql36
-rw-r--r--challenge-259/luca-ferrari/plpgsql/ch-2.sql15
-rw-r--r--challenge-259/luca-ferrari/python/ch-1.py37
-rw-r--r--challenge-259/luca-ferrari/python/ch-2.py69
-rw-r--r--challenge-259/luca-ferrari/raku/ch-1.raku36
-rw-r--r--challenge-259/luca-ferrari/raku/ch-2.raku45
21 files changed, 530 insertions, 3 deletions
diff --git a/challenge-259/luca-ferrari/blog-1.txt b/challenge-259/luca-ferrari/blog-1.txt
new file mode 100644
index 0000000000..f59eee9b34
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-1.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1
diff --git a/challenge-259/luca-ferrari/blog-10.txt b/challenge-259/luca-ferrari/blog-10.txt
new file mode 100644
index 0000000000..3a8f05e0f8
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-10.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/[= date -%]/PerlWeeklyChallenge259.html#task2pljava
diff --git a/challenge-259/luca-ferrari/blog-2.txt b/challenge-259/luca-ferrari/blog-2.txt
new file mode 100644
index 0000000000..9fa1af6ea8
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-2.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2
diff --git a/challenge-259/luca-ferrari/blog-3.txt b/challenge-259/luca-ferrari/blog-3.txt
new file mode 100644
index 0000000000..26ad2f3825
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-3.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1plperl
diff --git a/challenge-259/luca-ferrari/blog-4.txt b/challenge-259/luca-ferrari/blog-4.txt
new file mode 100644
index 0000000000..a1c1a8df1d
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-4.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2plperl
diff --git a/challenge-259/luca-ferrari/blog-5.txt b/challenge-259/luca-ferrari/blog-5.txt
new file mode 100644
index 0000000000..8f99d56a78
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-5.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1plpgsql
diff --git a/challenge-259/luca-ferrari/blog-6.txt b/challenge-259/luca-ferrari/blog-6.txt
new file mode 100644
index 0000000000..2956e4b204
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-6.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2plpgsql
diff --git a/challenge-259/luca-ferrari/blog-7.txt b/challenge-259/luca-ferrari/blog-7.txt
new file mode 100644
index 0000000000..ae78544493
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-7.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1python
diff --git a/challenge-259/luca-ferrari/blog-8.txt b/challenge-259/luca-ferrari/blog-8.txt
new file mode 100644
index 0000000000..0374c2d0a7
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-8.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2python
diff --git a/challenge-259/luca-ferrari/blog-9.txt b/challenge-259/luca-ferrari/blog-9.txt
new file mode 100644
index 0000000000..7521039415
--- /dev/null
+++ b/challenge-259/luca-ferrari/blog-9.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1pljava
diff --git a/challenge-259/luca-ferrari/pljava/pom.xml b/challenge-259/luca-ferrari/pljava/pom.xml
index 1a0d8dbf4d..30b7a337f3 100644
--- a/challenge-259/luca-ferrari/pljava/pom.xml
+++ b/challenge-259/luca-ferrari/pljava/pom.xml
@@ -5,11 +5,11 @@
<modelVersion>4.0.0</modelVersion>
<groupId>PWC</groupId>
- <artifactId>PWC258</artifactId>
+ <artifactId>PWC259</artifactId>
<version>1</version>
- <name>Perl Weekly Challenge 258</name>
- <description>Implementation of the tasks in PL/Java for PWC 258</description>
+ <name>Perl Weekly Challenge 259</name>
+ <description>Implementation of the tasks in PL/Java for PWC 259</description>
<properties>
<project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
diff --git a/challenge-259/luca-ferrari/pljava/src/main/java/Task1.java b/challenge-259/luca-ferrari/pljava/src/main/java/Task1.java
new file mode 100644
index 0000000000..de464e56c0
--- /dev/null
+++ b/challenge-259/luca-ferrari/pljava/src/main/java/Task1.java
@@ -0,0 +1,73 @@
+
+
+
+package PWC259;
+
+/**
+ * PL/Java implementation for PWC 259
+ * Task 1
+ * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+ *
+ *
+ * To compile on the local machine:
+
+ $ export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ # if not already set
+ $ mvn clean build
+ $ scp target/PWC259-1.jar luca@rachel:/tmp
+
+
+ * To install into PostgreSQL execute:
+
+ select sqlj.install_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', true );
+
+ select pwc259.task2_pljava();
+
+ and then to redeploy:
+
+ select sqlj.replace_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', true );
+
+*/
+
+import org.postgresql.pljava.*;
+import org.postgresql.pljava.annotation.Function;
+import static org.postgresql.pljava.annotation.Function.Effects.IMMUTABLE;
+import static org.postgresql.pljava.annotation.Function.OnNullInput.RETURNS_NULL;
+
+import java.util.*;
+import java.util.stream.*;
+import java.sql.SQLException;
+import java.util.logging.*;
+import java.sql.ResultSet;
+import java.sql.Date;
+
+public class Task1 {
+
+ private final static Logger logger = Logger.getAnonymousLogger();
+
+ @Function( schema = "pwc259",
+ onNullInput = RETURNS_NULL,
+ effects = IMMUTABLE )
+ public static final java.sql.Date task1_pljava( Date startDay, int how_many, Date[] holidays ) throws SQLException {
+ logger.log( Level.INFO, "Entering pwc259.task1_pljava" );
+
+ Calendar day = Calendar.getInstance();
+ day.setTime( startDay );
+
+ while ( how_many > 0 ) {
+ day.add( Calendar.DAY_OF_YEAR, 1 );
+
+ while ( day.get( Calendar.DAY_OF_MONTH ) == Calendar.SUNDAY
+ || day.get( Calendar.DAY_OF_MONTH ) == Calendar.SATURDAY )
+ day.add( Calendar.DAY_OF_YEAR, 1 );
+
+ if ( holidays != null )
+ for ( Date skip : holidays )
+ if ( skip.equals( day.getTime() ) )
+ day.add( Calendar.DAY_OF_YEAR, 1 );
+
+ how_many--;
+ }
+
+ return new java.sql.Date( day.getTimeInMillis() );
+ }
+}
diff --git a/challenge-259/luca-ferrari/pljava/src/main/java/Task2.java b/challenge-259/luca-ferrari/pljava/src/main/java/Task2.java
new file mode 100644
index 0000000000..1a33f13bea
--- /dev/null
+++ b/challenge-259/luca-ferrari/pljava/src/main/java/Task2.java
@@ -0,0 +1,107 @@
+
+
+
+package PWC259;
+
+/**
+ * PL/Java implementation for PWC 259
+ * Task 2
+ * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+ *
+ *
+ * To compile on the local machine:
+
+ $ export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ # if not already set
+ $ mvn clean build
+ $ scp target/PWC259-1.jar luca@rachel:/tmp
+
+
+ * To install into PostgreSQL execute:
+
+ select sqlj.install_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', true );
+
+ select pwc259.task2_pljava();
+
+ and then to redeploy:
+
+ select sqlj.replace_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', true );
+
+*/
+
+import org.postgresql.pljava.*;
+import org.postgresql.pljava.annotation.Function;
+import static org.postgresql.pljava.annotation.Function.Effects.IMMUTABLE;
+import static org.postgresql.pljava.annotation.Function.OnNullInput.RETURNS_NULL;
+
+import java.util.*;
+import java.util.regex.*;
+import java.util.stream.*;
+import java.sql.SQLException;
+import java.util.logging.*;
+import java.sql.ResultSet;
+import java.sql.Date;
+
+public class Task2 implements ResultSetProvider {
+
+ private final static Logger logger = Logger.getAnonymousLogger();
+
+ @Function( schema = "pwc259",
+ onNullInput = RETURNS_NULL,
+ effects = IMMUTABLE )
+ public static final ResultSetProvider task2_pljava( String line ) throws SQLException {
+ logger.log( Level.INFO, "Entering pwc259.task2_pljava : " + line );
+ return new Task2( line );
+ }
+
+
+ public Task2( String line ) throws SQLException {
+ params = new LinkedList< List<String> >();
+ parse( line );
+ }
+
+
+ private final void parse( String line ) throws SQLException {
+ Pattern pattern = Pattern.compile( "[{][%] (\\w+)\\s*(.*)\\s* [%][}]" );
+ Matcher matcher = pattern.matcher( line );
+
+ if ( matcher.find() ) {
+ id = matcher.group( 1 );
+
+ Pattern subPattern = Pattern.compile( "(\\w+)[=](\\w+)\\s*" );
+ Matcher subMatch = subPattern.matcher( matcher.group( 2 ) );
+
+ while ( subMatch.find() ) {
+ List<String> current = new LinkedList<String>();
+ current.add( subMatch.group( 1 ) );
+ current.add( subMatch.group( 2 ) );
+ params.add( current );
+
+ }
+ }
+ else
+ throw new SQLException( "Cannot parse " + line );
+
+ }
+
+ private List< List<String> > params;
+ private String id;
+
+ @Override
+ public boolean assignRowValues(ResultSet rs, int row)
+ throws SQLException {
+
+ // stop the result set
+ if ( row >= params.size() )
+ return false;
+
+ rs.updateInt( 1, row );
+ rs.updateString( 2, id );
+ rs.updateString( 3, params.get( row ).get( 0 ) );
+ rs.updateString( 4, params.get( row ).get( 1 ) );
+ return true;
+ }
+
+ @Override
+ public void close() {
+ }
+}
diff --git a/challenge-259/luca-ferrari/plperl/ch-1.plperl b/challenge-259/luca-ferrari/plperl/ch-1.plperl
new file mode 100644
index 0000000000..bd7a6e6a27
--- /dev/null
+++ b/challenge-259/luca-ferrari/plperl/ch-1.plperl
@@ -0,0 +1,41 @@
+--
+-- Perl Weekly Challenge 259
+-- Task 1
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc259;
+
+CREATE OR REPLACE FUNCTION
+pwc259.task1_plperl( date, int, date[] )
+RETURNS date
+AS $CODE$
+
+use DateTime;
+
+ my ( $when, $offset, $holidays ) = @_;
+
+ $when =~ / ^ (?<year>\d{4}) [-] (?<month>\d{2}) [-] (?<day>\d{2}) $ /x;
+
+ my $day = DateTime->new( year => $+{ year}, month => $+{ month }, day => $+{ day } );
+
+ while ( $offset > 0 ) {
+ $day->add( days => 1 );
+ $offset--;
+
+ # skip weekends
+ while ( $day->day_of_week == 6 || $day->day_of_week == 7 ) {
+ $day->add( days => 1 );
+ }
+
+ if ( $holidays->@* ) {
+ while( grep { $_ eq $day->ymd } $holidays->@* ) {
+ $day->add( days => 1 );
+ }
+ }
+ }
+
+ return $day->ymd;
+
+$CODE$
+LANGUAGE plperlu;
diff --git a/challenge-259/luca-ferrari/plperl/ch-2.plperl b/challenge-259/luca-ferrari/plperl/ch-2.plperl
new file mode 100644
index 0000000000..b3500be853
--- /dev/null
+++ b/challenge-259/luca-ferrari/plperl/ch-2.plperl
@@ -0,0 +1,58 @@
+--
+-- Perl Weekly Challenge 259
+-- Task 2
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc259;
+
+CREATE OR REPLACE FUNCTION
+pwc259.task2_plperl( text)
+RETURNS TABLE( id text, field_name text, field_value text )
+AS $CODE$
+
+ my ( $line ) = @_;
+
+ if ( $line =~ / ^ [{] [%] \s* (?<id>\w+) \s* (?<options>.*) \s* [%] [}] $ /x ) {
+ my $id = $+{ id };
+ my ( $name, $value ) = ( '', '' );
+ if ( $+{ options } ) {
+ my $is_value = 0;
+ my $allowed_spaces = 0;
+ my $previous = '';
+
+ for ( split //, $+{ options } ) {
+
+
+ $is_value = 1 and $previous = $_ and next if ( $_ eq '=' );
+ $allowed_spaces = 1 and $previous = $_ and next if ( $_ eq '"' and $previous eq '=' );
+
+ $name .= $_ if ( ! $is_value );
+ $value .= $_ if ( $is_value );
+
+ if ( $is_value
+ && ( ( $_ eq ' ' && ! $allowed_spaces )
+ || ( $_ eq '"' && $previous ne '\\' && $allowed_spaces ) )
+ ) {
+ # stop here!
+ $value =~ s/^\s*|\s*$//g;
+ $value =~ s/^["]|["]$//g;
+ $value =~ s/\\"/"/g;
+ return_next( { id => $id ,
+ field_name => $name,
+ field_value => $value } );
+
+ ( $name, $value, $is_value, $allowed_spaces ) = ( '', '', 0, 0 );
+ }
+
+ $previous = $_;
+ }
+
+
+ }
+ }
+
+ return undef;
+
+$CODE$
+LANGUAGE plperl;
diff --git a/challenge-259/luca-ferrari/plpgsql/ch-1.sql b/challenge-259/luca-ferrari/plpgsql/ch-1.sql
new file mode 100644
index 0000000000..4b8f2eff5a
--- /dev/null
+++ b/challenge-259/luca-ferrari/plpgsql/ch-1.sql
@@ -0,0 +1,36 @@
+--
+-- Perl Weekly Challenge 259
+-- Task 1
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc259;
+
+CREATE OR REPLACE FUNCTION
+pwc259.task1_plpgsql( day date, how_many_days int, holidays date[] )
+RETURNS date
+AS $CODE$
+DECLARE
+ current_holiday date;
+BEGIN
+
+ WHILE how_many_days > 0 LOOP
+ day := day + 1;
+
+ WHILE extract( dow from day ) IN ( 0, 6 ) LOOP
+ day := day + 1;
+ END LOOP;
+
+ FOREACH current_holiday IN ARRAY holidays LOOP
+ IF current_holiday = day THEN
+ day := day + 1;
+ END IF;
+ END LOOP;
+
+ how_many_days := how_many_days - 1;
+ END LOOP;
+
+ RETURN day;
+END
+$CODE$
+LANGUAGE plpgsql;
diff --git a/challenge-259/luca-ferrari/plpgsql/ch-2.sql b/challenge-259/luca-ferrari/plpgsql/ch-2.sql
new file mode 100644
index 0000000000..15c2f30024
--- /dev/null
+++ b/challenge-259/luca-ferrari/plpgsql/ch-2.sql
@@ -0,0 +1,15 @@
+--
+-- Perl Weekly Challenge 259
+-- Task 2
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc259;
+
+CREATE OR REPLACE FUNCTION
+pwc259.task2_plpgsql( line text )
+RETURNS TABLE( id text, field_name text, field_value text )
+AS $CODE$
+ SELECT pwc259.task2_plperl( line );
+$CODE$
+LANGUAGE sql;
diff --git a/challenge-259/luca-ferrari/python/ch-1.py b/challenge-259/luca-ferrari/python/ch-1.py
new file mode 100644
index 0000000000..9b3a0fd121
--- /dev/null
+++ b/challenge-259/luca-ferrari/python/ch-1.py
@@ -0,0 +1,37 @@
+#!python
+
+#
+# Perl Weekly Challenge 259
+# Task 1
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+#
+
+import sys
+from datetime import date, timedelta
+
+# task implementation
+# the return value will be printed
+def task_1( args ):
+ day = date.fromisoformat( args[ 0 ] )
+ offset = int( args[ 1 ] )
+ holidays = list( map( lambda x: date.fromisoformat( x ), args[ 2: ] ) )
+ one_day = timedelta( days=1 )
+
+ while offset > 0 :
+ day += one_day
+
+ while day.weekday() >= 6 or day.weekday() == 0:
+ day += one_day
+
+ while day in holidays :
+ day += one_day
+
+ offset -= 1
+
+ return day
+
+
+# invoke the main without the command itself
+if __name__ == '__main__':
+ print( task_1( sys.argv[ 1: ] ) )
diff --git a/challenge-259/luca-ferrari/python/ch-2.py b/challenge-259/luca-ferrari/python/ch-2.py
new file mode 100644
index 0000000000..d8da389ecc
--- /dev/null
+++ b/challenge-259/luca-ferrari/python/ch-2.py
@@ -0,0 +1,69 @@
+#!python
+
+#
+# Perl Weekly Challenge 259
+# Task 2
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+#
+
+import sys
+
+# task implementation
+# the return value will be printed
+def task_2( args ):
+ line = args[ 0 ]
+
+ parsed = {}
+ id = ''
+ key = ''
+ value = ''
+ is_value = False
+ is_key = False
+
+ for c in line:
+ if c == '{' :
+ continue
+ elif c == '%':
+ continue
+ elif c == '}':
+ return parsed
+ elif c == ' ':
+ if not 'id' in parsed and len( id ) > 0 :
+ parsed[ 'id' ] = id
+ parsed[ 'fields' ] = []
+ is_key = True
+ continue
+ elif 'fields' in parsed:
+ parsed[ 'fields' ].append( { key : value } )
+ is_key = True
+ key = ''
+ value = ''
+ is_value = False
+
+ elif c != '=' :
+ if not 'id' in parsed:
+ id += c
+ is_value = False
+ is_key = False
+ continue
+ else:
+ if is_key:
+ key += c
+ else:
+ value += c
+
+ elif c == '=':
+ if is_key:
+ is_value = True
+ is_key = False
+
+
+
+
+ return parsed
+
+
+# invoke the main without the command itself
+if __name__ == '__main__':
+ print( task_2( sys.argv[ 1: ] ) )
diff --git a/challenge-259/luca-ferrari/raku/ch-1.raku b/challenge-259/luca-ferrari/raku/ch-1.raku
new file mode 100644
index 0000000000..4835c0b013
--- /dev/null
+++ b/challenge-259/luca-ferrari/raku/ch-1.raku
@@ -0,0 +1,36 @@
+#!raku
+
+#
+# Perl Weekly Challenge 259
+# Task 1
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+#
+
+sub MAIN( $date,
+ Int $offset is copy,
+ *@holidays
+ where { $date ~~ / ^ \d ** 4 <[-]>\d ** 2 <[-]> \d ** 2 $ / and $offset > 0 } ) {
+
+ my $day = DateTime.new( $date, formatter => { sprintf "%04d-%02d-%02d", .year, .month, .day } );
+
+
+ while ( $offset > 0 ) {
+ $day .= later( days => 1 );
+
+ # skip weekends
+ while ( $day.day-of-week == any( 7, 6 ) ) {
+ $day .= later( days => 1 );
+ }
+
+ while ( @holidays.elems > 0 && @holidays.grep( * ~~ $day.Str ) ) {
+ $day .= later( days => 1 );
+ }
+
+
+ $offset--;
+ }
+
+ $day.say;
+
+}
diff --git a/challenge-259/luca-ferrari/raku/ch-2.raku b/challenge-259/luca-ferrari/raku/ch-2.raku
new file mode 100644
index 0000000000..1005c9e48d
--- /dev/null
+++ b/challenge-259/luca-ferrari/raku/ch-2.raku
@@ -0,0 +1,45 @@
+#!raku
+
+#
+# Perl Weekly Challenge 259
+# Task 2
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259>
+#
+
+
+# {% id field1="value1" field2="value2" field3=42 %}
+
+# Where
+
+# a) "id" can be \w+.
+# b) There can be 0 or more field-value pairs.
+# c) The name of the fields are \w+.
+# b) The values are either number in which case we don't need parentheses or string in
+# which case we need parentheses around them.
+
+
+sub MAIN() {
+
+ my %parsed;
+
+ my $line = '{% youtube video=foobar password=xyz abc=def donald="duck here \"escaped\" " %}';
+
+ my regex id { \w+ };
+ my regex option { $<name>= [ \w+ ] \s* <[=]> $<value>= [ \w+ | \" \w+ \s* .* \" ] };
+ my regex opening { <[{]> <[%]> };
+ my regex closing { <[%]> <[}]> };
+
+ if ( $line ~~ / ^ <opening> \s+ <id> \s+ <option>* % \s \s* <closing> $ / ) {
+
+ %parsed<name> = $/<id>;
+
+ say $/<option>;
+ for $/<option> {
+ my ( $key, $value ) = .split( '=' );
+ %parsed<fields>{ $key } = $value;
+ }
+ }
+
+ say %parsed;
+}