aboutsummaryrefslogtreecommitdiff
path: root/challenge-017
diff options
context:
space:
mode:
authorAdam Russell <ac.russell@live.com>2019-07-21 02:56:19 -0400
committerAdam Russell <ac.russell@live.com>2019-07-21 02:56:19 -0400
commit2a16112bdf6da59fdc5eb0333e99083e549e0dbf (patch)
treef77a559e7969fd44bb66dd254178f4878baf937c /challenge-017
parent79f066fe8b36e3112158e777d7ada16feaf66cda (diff)
downloadperlweeklychallenge-club-2a16112bdf6da59fdc5eb0333e99083e549e0dbf.tar.gz
perlweeklychallenge-club-2a16112bdf6da59fdc5eb0333e99083e549e0dbf.tar.bz2
perlweeklychallenge-club-2a16112bdf6da59fdc5eb0333e99083e549e0dbf.zip
solutions for challenge 017
Diffstat (limited to 'challenge-017')
-rw-r--r--challenge-017/adam-russell/blog.txt1
-rw-r--r--challenge-017/adam-russell/perl5/UrlGrammar.output214
-rw-r--r--challenge-017/adam-russell/perl5/UrlGrammar.pm272
-rw-r--r--challenge-017/adam-russell/perl5/UrlGrammar.yp69
-rw-r--r--challenge-017/adam-russell/perl5/UrlParser.pm272
-rw-r--r--challenge-017/adam-russell/perl5/ch-1.pl17
-rw-r--r--challenge-017/adam-russell/perl5/ch-2.pl12
-rw-r--r--challenge-017/adam-russell/perl5/url_viz.pl5
8 files changed, 862 insertions, 0 deletions
diff --git a/challenge-017/adam-russell/blog.txt b/challenge-017/adam-russell/blog.txt
new file mode 100644
index 0000000000..b210bbc33c
--- /dev/null
+++ b/challenge-017/adam-russell/blog.txt
@@ -0,0 +1 @@
+https://adamcrussell.livejournal.com/5707.html
diff --git a/challenge-017/adam-russell/perl5/UrlGrammar.output b/challenge-017/adam-russell/perl5/UrlGrammar.output
new file mode 100644
index 0000000000..759308ef30
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/UrlGrammar.output
@@ -0,0 +1,214 @@
+Rules:
+------
+0: $start -> url $end
+1: url -> scheme colondoubleslash userpassword host port path query fragment
+2: url -> scheme colondoubleslash host path query fragment
+3: url -> scheme colondoubleslash host path fragment
+4: url -> scheme colondoubleslash host path
+5: url -> scheme colondoubleslash host
+6: colondoubleslash -> '://'
+7: scheme -> SCHEME
+8: userpassword -> USERPASSWORD
+9: host -> HOST
+10: port -> PORT
+11: path -> PATH
+12: query -> QUERY
+13: fragment -> FRAGMENT
+
+States:
+-------
+State 0:
+
+ $start -> . url $end (Rule 0)
+
+ SCHEME shift, and go to state 3
+
+ scheme go to state 1
+ url go to state 2
+
+State 1:
+
+ url -> scheme . colondoubleslash userpassword host port path query fragment (Rule 1)
+ url -> scheme . colondoubleslash host path query fragment (Rule 2)
+ url -> scheme . colondoubleslash host path fragment (Rule 3)
+ url -> scheme . colondoubleslash host path (Rule 4)
+ url -> scheme . colondoubleslash host (Rule 5)
+
+ '://' shift, and go to state 4
+
+ colondoubleslash go to state 5
+
+State 2:
+
+ $start -> url . $end (Rule 0)
+
+ $end shift, and go to state 6
+
+State 3:
+
+ scheme -> SCHEME . (Rule 7)
+
+ $default reduce using rule 7 (scheme)
+
+State 4:
+
+ colondoubleslash -> '://' . (Rule 6)
+
+ $default reduce using rule 6 (colondoubleslash)
+
+State 5:
+
+ url -> scheme colondoubleslash . userpassword host port path query fragment (Rule 1)
+ url -> scheme colondoubleslash . host path query fragment (Rule 2)
+ url -> scheme colondoubleslash . host path fragment (Rule 3)
+ url -> scheme colondoubleslash . host path (Rule 4)
+ url -> scheme colondoubleslash . host (Rule 5)
+
+ HOST shift, and go to state 8
+ USERPASSWORD shift, and go to state 9
+
+ host go to state 7
+ userpassword go to state 10
+
+State 6:
+
+ $start -> url $end . (Rule 0)
+
+ $default accept
+
+State 7:
+
+ url -> scheme colondoubleslash host . path query fragment (Rule 2)
+ url -> scheme colondoubleslash host . path fragment (Rule 3)
+ url -> scheme colondoubleslash host . path (Rule 4)
+ url -> scheme colondoubleslash host . (Rule 5)
+
+ PATH shift, and go to state 11
+
+ $default reduce using rule 5 (url)
+
+ path go to state 12
+
+State 8:
+
+ host -> HOST . (Rule 9)
+
+ $default reduce using rule 9 (host)
+
+State 9:
+
+ userpassword -> USERPASSWORD . (Rule 8)
+
+ $default reduce using rule 8 (userpassword)
+
+State 10:
+
+ url -> scheme colondoubleslash userpassword . host port path query fragment (Rule 1)
+
+ HOST shift, and go to state 8
+
+ host go to state 13
+
+State 11:
+
+ path -> PATH . (Rule 11)
+
+ $default reduce using rule 11 (path)
+
+State 12:
+
+ url -> scheme colondoubleslash host path . query fragment (Rule 2)
+ url -> scheme colondoubleslash host path . fragment (Rule 3)
+ url -> scheme colondoubleslash host path . (Rule 4)
+
+ FRAGMENT shift, and go to state 14
+ QUERY shift, and go to state 15
+
+ $default reduce using rule 4 (url)
+
+ fragment go to state 16
+ query go to state 17
+
+State 13:
+
+ url -> scheme colondoubleslash userpassword host . port path query fragment (Rule 1)
+
+ PORT shift, and go to state 18
+
+ port go to state 19
+
+State 14:
+
+ fragment -> FRAGMENT . (Rule 13)
+
+ $default reduce using rule 13 (fragment)
+
+State 15:
+
+ query -> QUERY . (Rule 12)
+
+ $default reduce using rule 12 (query)
+
+State 16:
+
+ url -> scheme colondoubleslash host path fragment . (Rule 3)
+
+ $default reduce using rule 3 (url)
+
+State 17:
+
+ url -> scheme colondoubleslash host path query . fragment (Rule 2)
+
+ FRAGMENT shift, and go to state 14
+
+ fragment go to state 20
+
+State 18:
+
+ port -> PORT . (Rule 10)
+
+ $default reduce using rule 10 (port)
+
+State 19:
+
+ url -> scheme colondoubleslash userpassword host port . path query fragment (Rule 1)
+
+ PATH shift, and go to state 11
+
+ path go to state 21
+
+State 20:
+
+ url -> scheme colondoubleslash host path query fragment . (Rule 2)
+
+ $default reduce using rule 2 (url)
+
+State 21:
+
+ url -> scheme colondoubleslash userpassword host port path . query fragment (Rule 1)
+
+ QUERY shift, and go to state 15
+
+ query go to state 22
+
+State 22:
+
+ url -> scheme colondoubleslash userpassword host port path query . fragment (Rule 1)
+
+ FRAGMENT shift, and go to state 14
+
+ fragment go to state 23
+
+State 23:
+
+ url -> scheme colondoubleslash userpassword host port path query fragment . (Rule 1)
+
+ $default reduce using rule 1 (url)
+
+
+Summary:
+--------
+Number of rules : 14
+Number of terminals : 9
+Number of non-terminals : 10
+Number of states : 24
diff --git a/challenge-017/adam-russell/perl5/UrlGrammar.pm b/challenge-017/adam-russell/perl5/UrlGrammar.pm
new file mode 100644
index 0000000000..60aeb9ff38
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/UrlGrammar.pm
@@ -0,0 +1,272 @@
+####################################################################
+#
+# This file was generated using Parse::Yapp version 1.21.
+#
+# Don't edit this file, use source file instead.
+#
+# ANY CHANGE MADE HERE WILL BE LOST !
+#
+####################################################################
+package UrlGrammar;
+use vars qw ( @ISA );
+use strict;
+
+@ISA= qw ( Parse::Yapp::Driver );
+use Parse::Yapp::Driver;
+
+
+
+sub new {
+ my($class)=shift;
+ ref($class)
+ and $class=ref($class);
+
+ my($self)=$class->SUPER::new( yyversion => '1.21',
+ yystates =>
+[
+ {#State 0
+ ACTIONS => {
+ 'SCHEME' => 3
+ },
+ GOTOS => {
+ 'scheme' => 1,
+ 'url' => 2
+ }
+ },
+ {#State 1
+ ACTIONS => {
+ "://" => 4
+ },
+ GOTOS => {
+ 'colondoubleslash' => 5
+ }
+ },
+ {#State 2
+ ACTIONS => {
+ '' => 6
+ }
+ },
+ {#State 3
+ DEFAULT => -7
+ },
+ {#State 4
+ DEFAULT => -6
+ },
+ {#State 5
+ ACTIONS => {
+ 'HOST' => 8,
+ 'USERPASSWORD' => 9
+ },
+ GOTOS => {
+ 'host' => 7,
+ 'userpassword' => 10
+ }
+ },
+ {#State 6
+ DEFAULT => 0
+ },
+ {#State 7
+ ACTIONS => {
+ 'PATH' => 11
+ },
+ DEFAULT => -5,
+ GOTOS => {
+ 'path' => 12
+ }
+ },
+ {#State 8
+ DEFAULT => -9
+ },
+ {#State 9
+ DEFAULT => -8
+ },
+ {#State 10
+ ACTIONS => {
+ 'HOST' => 8
+ },
+ GOTOS => {
+ 'host' => 13
+ }
+ },
+ {#State 11
+ DEFAULT => -11
+ },
+ {#State 12
+ ACTIONS => {
+ 'QUERY' => 15,
+ 'FRAGMENT' => 14
+ },
+ DEFAULT => -4,
+ GOTOS => {
+ 'fragment' => 16,
+ 'query' => 17
+ }
+ },
+ {#State 13
+ ACTIONS => {
+ 'PORT' => 18
+ },
+ GOTOS => {
+ 'port' => 19
+ }
+ },
+ {#State 14
+ DEFAULT => -13
+ },
+ {#State 15
+ DEFAULT => -12
+ },
+ {#State 16
+ DEFAULT => -3
+ },
+ {#State 17
+ ACTIONS => {
+ 'FRAGMENT' => 14
+ },
+ GOTOS => {
+ 'fragment' => 20
+ }
+ },
+ {#State 18
+ DEFAULT => -10
+ },
+ {#State 19
+ ACTIONS => {
+ 'PATH' => 11
+ },
+ GOTOS => {
+ 'path' => 21
+ }
+ },
+ {#State 20
+ DEFAULT => -2
+ },
+ {#State 21
+ ACTIONS => {
+ 'QUERY' => 15
+ },
+ GOTOS => {
+ 'query' => 22
+ }
+ },
+ {#State 22
+ ACTIONS => {
+ 'FRAGMENT' => 14
+ },
+ GOTOS => {
+ 'fragment' => 23
+ }
+ },
+ {#State 23
+ DEFAULT => -1
+ }
+],
+ yyrules =>
+[
+ [#Rule 0
+ '$start', 2, undef
+ ],
+ [#Rule 1
+ 'url', 8, undef
+ ],
+ [#Rule 2
+ 'url', 6, undef
+ ],
+ [#Rule 3
+ 'url', 5, undef
+ ],
+ [#Rule 4
+ 'url', 4, undef
+ ],
+ [#Rule 5
+ 'url', 3, undef
+ ],
+ [#Rule 6
+ 'colondoubleslash', 1, undef
+ ],
+ [#Rule 7
+ 'scheme', 1,
+sub
+#line 13 "perl5/UrlGrammar.yp"
+{ print "SCHEME:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 8
+ 'userpassword', 1,
+sub
+#line 16 "perl5/UrlGrammar.yp"
+{ my @a = split(/:/, $_[1]); print "USER:\t\t" . $a[0] . "\nPASSWORD:\t" . $a[1] . "\n" }
+ ],
+ [#Rule 9
+ 'host', 1,
+sub
+#line 19 "perl5/UrlGrammar.yp"
+{ $_[1] =~ s/@//; print "HOST:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 10
+ 'port', 1,
+sub
+#line 22 "perl5/UrlGrammar.yp"
+{ $_[1] =~ s/://; print "PORT:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 11
+ 'path', 1,
+sub
+#line 25 "perl5/UrlGrammar.yp"
+{ print "PATH:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 12
+ 'query', 1,
+sub
+#line 28 "perl5/UrlGrammar.yp"
+{ my $query = substr($_[1], 1); print "QUERY:\t\t$query\n" }
+ ],
+ [#Rule 13
+ 'fragment', 1,
+sub
+#line 31 "perl5/UrlGrammar.yp"
+{ my $fragment = substr($_[1], 1); print "FRAGMENT:\t$fragment\n" }
+ ]
+],
+ @_);
+ bless($self,$class);
+}
+
+#line 34 "perl5/UrlGrammar.yp"
+
+
+sub lexer{
+ my($parser) = @_;
+ $parser->YYData->{INPUT} or return('', undef);
+ $parser->YYData->{INPUT} =~ s/^[ \t]//;
+ ##
+ # send tokens to parser
+ ##
+ for($parser->YYData->{INPUT}){
+ s/^(http|https|ftp|jdbc)// and return ("SCHEME", $1);
+ s/^(:\/\/)// and return ("://", $1);
+ s/^(:[0-9]*)// and return ("PORT", $1);
+ s/^([a-zA-Z]*:[a-zA-Z]*)// and return ("USERPASSWORD", $1);
+ s/^(\/[\/a-zA-Z]*)// and return ("PATH", $1);
+ s/^(\?{1}[a-zA-z=a-zA-Z]*)// and return ("QUERY", $1);
+ s/^(#{1}[a-zA-Z]*[0-9]*)// and return ("FRAGMENT", $1);
+ s/^(@?\/{0}[a-zA-z]*)// and return ("HOST", $1);
+ }
+}
+
+sub error{
+ exists $_[0]->YYData->{ERRMSG}
+ and do{
+ print $_[0]->YYData->{ERRMSG};
+ return;
+ };
+ print "syntax error\n";
+}
+
+sub parse{
+ my($self, $input) = @_;
+ $self->YYData->{INPUT} = $input;
+ my $result = $self->YYParse(yylex => \&lexer, yyerror => \&error);
+ return $result;
+}
+
+1;
diff --git a/challenge-017/adam-russell/perl5/UrlGrammar.yp b/challenge-017/adam-russell/perl5/UrlGrammar.yp
new file mode 100644
index 0000000000..7c493c9a7b
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/UrlGrammar.yp
@@ -0,0 +1,69 @@
+%token '://' SCHEME USERPASSWORD HOST PORT PATH QUERY FRAGMENT
+%%
+url: scheme colondoubleslash userpassword host port path query fragment
+ | scheme colondoubleslash host path query fragment
+ | scheme colondoubleslash host path fragment
+ | scheme colondoubleslash host path
+ | scheme colondoubleslash host
+;
+
+colondoubleslash: '://'
+;
+
+scheme: SCHEME { print "SCHEME:\t\t" . $_[1] . "\n" }
+;
+
+userpassword: USERPASSWORD { my @a = split(/:/, $_[1]); print "USER:\t\t" . $a[0] . "\nPASSWORD:\t" . $a[1] . "\n" }
+;
+
+host: HOST { $_[1] =~ s/@//; print "HOST:\t\t" . $_[1] . "\n" }
+;
+
+port: PORT { $_[1] =~ s/://; print "PORT:\t\t" . $_[1] . "\n" }
+;
+
+path: PATH { print "PATH:\t\t" . $_[1] . "\n" }
+;
+
+query: QUERY { my $query = substr($_[1], 1); print "QUERY:\t\t$query\n" }
+;
+
+fragment: FRAGMENT { my $fragment = substr($_[1], 1); print "FRAGMENT:\t$fragment\n" }
+;
+
+%%
+
+sub lexer{
+ my($parser) = @_;
+ $parser->YYData->{INPUT} or return('', undef);
+ $parser->YYData->{INPUT} =~ s/^[ \t]//;
+ ##
+ # send tokens to parser
+ ##
+ for($parser->YYData->{INPUT}){
+ s/^(http|https|ftp|jdbc)// and return ("SCHEME", $1);
+ s/^(:\/\/)// and return ("://", $1);
+ s/^(:[0-9]*)// and return ("PORT", $1);
+ s/^([a-zA-Z]*:[a-zA-Z]*)// and return ("USERPASSWORD", $1);
+ s/^(\/[\/a-zA-Z]*)// and return ("PATH", $1);
+ s/^(\?{1}[a-zA-z=a-zA-Z]*)// and return ("QUERY", $1);
+ s/^(#{1}[a-zA-Z]*[0-9]*)// and return ("FRAGMENT", $1);
+ s/^(@?\/{0}[a-zA-z]*)// and return ("HOST", $1);
+ }
+}
+
+sub error{
+ exists $_[0]->YYData->{ERRMSG}
+ and do{
+ print $_[0]->YYData->{ERRMSG};
+ return;
+ };
+ print "syntax error\n";
+}
+
+sub parse{
+ my($self, $input) = @_;
+ $self->YYData->{INPUT} = $input;
+ my $result = $self->YYParse(yylex => \&lexer, yyerror => \&error);
+ return $result;
+}
diff --git a/challenge-017/adam-russell/perl5/UrlParser.pm b/challenge-017/adam-russell/perl5/UrlParser.pm
new file mode 100644
index 0000000000..53dfebfda6
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/UrlParser.pm
@@ -0,0 +1,272 @@
+####################################################################
+#
+# This file was generated using Parse::Yapp version 1.21.
+#
+# Don't edit this file, use source file instead.
+#
+# ANY CHANGE MADE HERE WILL BE LOST !
+#
+####################################################################
+package UrlParser;
+use vars qw ( @ISA );
+use strict;
+
+@ISA= qw ( Parse::Yapp::Driver );
+use Parse::Yapp::Driver;
+
+
+
+sub new {
+ my($class)=shift;
+ ref($class)
+ and $class=ref($class);
+
+ my($self)=$class->SUPER::new( yyversion => '1.21',
+ yystates =>
+[
+ {#State 0
+ ACTIONS => {
+ 'SCHEME' => 2
+ },
+ GOTOS => {
+ 'scheme' => 3,
+ 'url' => 1
+ }
+ },
+ {#State 1
+ ACTIONS => {
+ '' => 4
+ }
+ },
+ {#State 2
+ DEFAULT => -7
+ },
+ {#State 3
+ ACTIONS => {
+ "://" => 6
+ },
+ GOTOS => {
+ 'colondoubleslash' => 5
+ }
+ },
+ {#State 4
+ DEFAULT => 0
+ },
+ {#State 5
+ ACTIONS => {
+ 'HOST' => 10,
+ 'USERPASSWORD' => 8
+ },
+ GOTOS => {
+ 'host' => 7,
+ 'userpassword' => 9
+ }
+ },
+ {#State 6
+ DEFAULT => -6
+ },
+ {#State 7
+ ACTIONS => {
+ 'PATH' => 11
+ },
+ DEFAULT => -5,
+ GOTOS => {
+ 'path' => 12
+ }
+ },
+ {#State 8
+ DEFAULT => -8
+ },
+ {#State 9
+ ACTIONS => {
+ 'HOST' => 10
+ },
+ GOTOS => {
+ 'host' => 13
+ }
+ },
+ {#State 10
+ DEFAULT => -9
+ },
+ {#State 11
+ DEFAULT => -11
+ },
+ {#State 12
+ ACTIONS => {
+ 'FRAGMENT' => 16,
+ 'QUERY' => 17
+ },
+ DEFAULT => -4,
+ GOTOS => {
+ 'fragment' => 15,
+ 'query' => 14
+ }
+ },
+ {#State 13
+ ACTIONS => {
+ 'PORT' => 19
+ },
+ GOTOS => {
+ 'port' => 18
+ }
+ },
+ {#State 14
+ ACTIONS => {
+ 'FRAGMENT' => 16
+ },
+ GOTOS => {
+ 'fragment' => 20
+ }
+ },
+ {#State 15
+ DEFAULT => -3
+ },
+ {#State 16
+ DEFAULT => -13
+ },
+ {#State 17
+ DEFAULT => -12
+ },
+ {#State 18
+ ACTIONS => {
+ 'PATH' => 11
+ },
+ GOTOS => {
+ 'path' => 21
+ }
+ },
+ {#State 19
+ DEFAULT => -10
+ },
+ {#State 20
+ DEFAULT => -2
+ },
+ {#State 21
+ ACTIONS => {
+ 'QUERY' => 17
+ },
+ GOTOS => {
+ 'query' => 22
+ }
+ },
+ {#State 22
+ ACTIONS => {
+ 'FRAGMENT' => 16
+ },
+ GOTOS => {
+ 'fragment' => 23
+ }
+ },
+ {#State 23
+ DEFAULT => -1
+ }
+],
+ yyrules =>
+[
+ [#Rule 0
+ '$start', 2, undef
+ ],
+ [#Rule 1
+ 'url', 8, undef
+ ],
+ [#Rule 2
+ 'url', 6, undef
+ ],
+ [#Rule 3
+ 'url', 5, undef
+ ],
+ [#Rule 4
+ 'url', 4, undef
+ ],
+ [#Rule 5
+ 'url', 3, undef
+ ],
+ [#Rule 6
+ 'colondoubleslash', 1, undef
+ ],
+ [#Rule 7
+ 'scheme', 1,
+sub
+#line 13 "perl5/UrlGrammar.yp"
+{ print "SCHEME:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 8
+ 'userpassword', 1,
+sub
+#line 16 "perl5/UrlGrammar.yp"
+{ my @a = split(/:/, $_[1]); print "USER:\t\t" . $a[0] . "\nPASSWORD:\t" . $a[1] . "\n" }
+ ],
+ [#Rule 9
+ 'host', 1,
+sub
+#line 19 "perl5/UrlGrammar.yp"
+{ $_[1] =~ s/@//; print "HOST:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 10
+ 'port', 1,
+sub
+#line 22 "perl5/UrlGrammar.yp"
+{ $_[1] =~ s/://; print "PORT:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 11
+ 'path', 1,
+sub
+#line 25 "perl5/UrlGrammar.yp"
+{ print "PATH:\t\t" . $_[1] . "\n" }
+ ],
+ [#Rule 12
+ 'query', 1,
+sub
+#line 28 "perl5/UrlGrammar.yp"
+{ my $query = substr($_[1], 1); print "QUERY:\t\t$query\n" }
+ ],
+ [#Rule 13
+ 'fragment', 1,
+sub
+#line 31 "perl5/UrlGrammar.yp"
+{ my $fragment = substr($_[1], 1); print "FRAGMENT:\t$fragment\n" }
+ ]
+],
+ @_);
+ bless($self,$class);
+}
+
+#line 34 "perl5/UrlGrammar.yp"
+
+
+sub lexer{
+ my($parser) = @_;
+ $parser->YYData->{INPUT} or return('', undef);
+ $parser->YYData->{INPUT} =~ s/^[ \t]//;
+ ##
+ # send tokens to parser
+ ##
+ for($parser->YYData->{INPUT}){
+ s/^(http|https|ftp|jdbc)// and return ("SCHEME", $1);
+ s/^(:\/\/)// and return ("://", $1);
+ s/^(:[0-9]*)// and return ("PORT", $1);
+ s/^([a-zA-Z]*:[a-zA-Z]*)// and return ("USERPASSWORD", $1);
+ s/^(\/[\/a-zA-Z]*)// and return ("PATH", $1);
+ s/^(\?{1}[a-zA-z=a-zA-Z]*)// and return ("QUERY", $1);
+ s/^(#{1}[a-zA-Z]*[0-9]*)// and return ("FRAGMENT", $1);
+ s/^(@?\/{0}[a-zA-z]*)// and return ("HOST", $1);
+ }
+}
+
+sub error{
+ exists $_[0]->YYData->{ERRMSG}
+ and do{
+ print $_[0]->YYData->{ERRMSG};
+ return;
+ };
+ print "syntax error\n";
+}
+
+sub parse{
+ my($self, $input) = @_;
+ $self->YYData->{INPUT} = $input;
+ my $result = $self->YYParse(yylex => \&lexer, yyerror => \&error);
+ return $result;
+}
+
+1;
diff --git a/challenge-017/adam-russell/perl5/ch-1.pl b/challenge-017/adam-russell/perl5/ch-1.pl
new file mode 100644
index 0000000000..24237d86ec
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/ch-1.pl
@@ -0,0 +1,17 @@
+use strict;
+use warnings;
+##
+# Create a script to demonstrate Ackermann function.
+##
+
+sub A{
+ my($m, $n) = @_;
+ return $n + 1 if($m == 0);
+ return A($m - 1, 1) if($m > 0 && $n == 0);
+ return A($m - 1, A($m, $n - 1)) if ($m > 0 && $n > 0);
+}
+
+MAIN:{
+ my $ackermann = A(1,2);
+ print "$ackermann\n";
+}
diff --git a/challenge-017/adam-russell/perl5/ch-2.pl b/challenge-017/adam-russell/perl5/ch-2.pl
new file mode 100644
index 0000000000..a9ce9edb9b
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/ch-2.pl
@@ -0,0 +1,12 @@
+use strict;
+use warnings;
+##
+# Create a script to parse URL and print the components of URL.
+##
+use UrlParser;
+use constant URL => q|jdbc://user:password@localhost:3306/pwc?profile=true#h1|;
+
+MAIN:{
+ my $parser = new UrlParser();
+ $parser->parse(URL);
+}
diff --git a/challenge-017/adam-russell/perl5/url_viz.pl b/challenge-017/adam-russell/perl5/url_viz.pl
new file mode 100644
index 0000000000..a9f4dfefb2
--- /dev/null
+++ b/challenge-017/adam-russell/perl5/url_viz.pl
@@ -0,0 +1,5 @@
+use GraphViz::Parse::Yapp;
+
+# Pass in a file generated via yapp -v
+my $g = GraphViz::Parse::Yapp->new("perl5/UrlGrammar.output");
+print $g->as_png;