| 1 | use v6; |
|---|
| 2 | |
|---|
| 3 | # ------------------------ E M I T T E R ------------------------ # |
|---|
| 4 | |
|---|
| 5 | class Talk { |
|---|
| 6 | has $.presenter; |
|---|
| 7 | has $.title; |
|---|
| 8 | method emit { |
|---|
| 9 | '<talk><title>' ~ $.title ~ '</title><presenter>' ~ $.presenter ~ '</presenter></talk>'; |
|---|
| 10 | } |
|---|
| 11 | } |
|---|
| 12 | |
|---|
| 13 | # --------------------------- P L A N --------------------------- # |
|---|
| 14 | |
|---|
| 15 | package main; |
|---|
| 16 | |
|---|
| 17 | use v6; |
|---|
| 18 | use Test; |
|---|
| 19 | |
|---|
| 20 | plan 11 + (2 * 2); |
|---|
| 21 | |
|---|
| 22 | if !eval('("a" ~~ /a/)') { |
|---|
| 23 | skip_rest "skipped tests - rules support appears to be missing"; |
|---|
| 24 | exit; |
|---|
| 25 | } |
|---|
| 26 | |
|---|
| 27 | # ------------------------ G R A M M A R ------------------------ # |
|---|
| 28 | |
|---|
| 29 | rule embedded_title { |
|---|
| 30 | <title> |
|---|
| 31 | } |
|---|
| 32 | |
|---|
| 33 | rule presentation { |
|---|
| 34 | <title> |
|---|
| 35 | <presenter> |
|---|
| 36 | } |
|---|
| 37 | |
|---|
| 38 | rule talk { |
|---|
| 39 | <title> |
|---|
| 40 | <presenter> |
|---|
| 41 | { return ::Talk(:$$<title>, :$$<presenter>) } |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | token presenter { |
|---|
| 45 | '<span class="speaker">' '<tt>'? <( <alpha>+ [<ws> <alpha>+]+ )> |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | token title { |
|---|
| 49 | '<span class="talk">' <link> '</span>' |
|---|
| 50 | { return $<link><label> } |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | token link { |
|---|
| 54 | '<a href="' |
|---|
| 55 | $<url> = ([\/]? \w+ [\/ \w+]+ \. \w+) '">' |
|---|
| 56 | $<label> = (<alpha>+ [<ws> <alpha>+]+) '</a>' |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | # ------------------------- S O U R C E ------------------------- # |
|---|
| 60 | |
|---|
| 61 | # snippet from http://pghpw.org/schedule.html |
|---|
| 62 | my $content = ' |
|---|
| 63 | <tr> |
|---|
| 64 | <td class="time">9:45 AM</td> |
|---|
| 65 | |
|---|
| 66 | <td class="beginner" |
|---|
| 67 | rowspan="2" |
|---|
| 68 | |
|---|
| 69 | > |
|---|
| 70 | <span class="talk"><a href="schedule/making_perl_work_for_you.html">Making Perl Work for You</a></span> |
|---|
| 71 | <span class="speaker"><tt>brian d foy</tt></span> |
|---|
| 72 | </td> |
|---|
| 73 | |
|---|
| 74 | |
|---|
| 75 | <td class="advanced" |
|---|
| 76 | |
|---|
| 77 | |
|---|
| 78 | > |
|---|
| 79 | <span class="talk"><a href="schedule/make_your_database_work_for_you.html">Make your database work for you</a></span> |
|---|
| 80 | <span class="speaker">Beth Skwarecki</span> |
|---|
| 81 | </td> |
|---|
| 82 | |
|---|
| 83 | </tr> |
|---|
| 84 | '; |
|---|
| 85 | |
|---|
| 86 | # -------------------------- T E S T S -------------------------- # |
|---|
| 87 | |
|---|
| 88 | my @expected = ( |
|---|
| 89 | 'Making Perl Work for You', |
|---|
| 90 | 'Make your database work for you', |
|---|
| 91 | ); |
|---|
| 92 | |
|---|
| 93 | # L<S05/Subrule captures> |
|---|
| 94 | my $presenter = ($content ~~ m/<presenter>/); |
|---|
| 95 | is(~$presenter, 'brian d foy', 'match presenter'); |
|---|
| 96 | |
|---|
| 97 | my $title = ($content ~~ m/<title>/); |
|---|
| 98 | is(~$title, 'Making Perl Work for You', 'match title'); |
|---|
| 99 | |
|---|
| 100 | # L<S05/Match objects/"This returned object is also automatically assigned to the lexical $/ variable"> |
|---|
| 101 | my $embedded = ($content ~~ m/<embedded_title>/); |
|---|
| 102 | ok($embedded); |
|---|
| 103 | # $embedded behaves just like $/, so you have to specify the <embedded_title> layer |
|---|
| 104 | is(~$embedded<embedded_title><title>, 'Making Perl Work for You', 'match embedded.title'); |
|---|
| 105 | |
|---|
| 106 | my $presentation = ($content ~~ m/<presentation>/); |
|---|
| 107 | ok($presentation); |
|---|
| 108 | is(~$presentation<presentation><title>, 'Making Perl Work for You', 'match presentation.title'); |
|---|
| 109 | is(~$presentation<presentation><presenter>, 'brian d foy', 'match presentation.presenter'); |
|---|
| 110 | |
|---|
| 111 | # L<< S05/Match objects/"you can override that by calling C<make> inside a regex" >> |
|---|
| 112 | my $talk = ($content ~~ m/<talk>/); |
|---|
| 113 | ok($talk); |
|---|
| 114 | my $title_value; eval('$title_value = $talk.title'); |
|---|
| 115 | is($title_value, 'Making Perl Work for You', 'match talk.title'); |
|---|
| 116 | my $presenter_value; eval('$presenter_value = $talk.presenter'); |
|---|
| 117 | is($presenter_value, 'brian d foy', 'match talk.presenter'); |
|---|
| 118 | my $emit_value; eval('$emit_value = $talk.emit'); |
|---|
| 119 | is($emit_value, '<talk><title>Making Perl Work for You</title><presenter>brian d foy</presenter></talk>', 'talk.emit'); |
|---|
| 120 | |
|---|
| 121 | # make sure we can find multiple presentations in our $content |
|---|
| 122 | # L<S05/Match objects/"Match object can produce the rest of the results lazily"> |
|---|
| 123 | my $c = 0; |
|---|
| 124 | for $content ~~ m:g/<presentation>/ -> $match { |
|---|
| 125 | # should loop through two matches |
|---|
| 126 | ok($match); |
|---|
| 127 | is(~$match<presentation><title>, @expected[$c], "presentation $c title"); |
|---|
| 128 | $c++; |
|---|
| 129 | } |
|---|