Skip to content

Instantly share code, notes, and snippets.

@bduggan
Created December 10, 2018 03:00
Show Gist options
  • Save bduggan/dc8fb3c3faef958c1ff993291106f2b1 to your computer and use it in GitHub Desktop.
Save bduggan/dc8fb3c3faef958c1ff993291106f2b1 to your computer and use it in GitHub Desktop.
grammar ical {
rule TOP {
<vcalendar>
}
rule vcalendar {
<section>
\n?
}
# section does not end with a NL
rule section {
'BEGIN:' <tag> \n
<thing>+ % \n
\n
'END:' $<tag>
}
rule thing {
[ <section> | <property> ]
}
rule property {
<single-line> | <multi-line>
}
regex single-line {
^^ <!before 'BEGIN'|'END'> <tag> ':' <value> $$
}
token multi-line {
^^ <tag> ':' \n
<multi-line-value>
}
token multi-line-value {
[ ^^ <.indent> \N* ]+ %% \n
}
token indent {
' '+
}
regex tag {
<[A..Z-]>+
}
token value {
\V+
}
token ws { <!ww> \h* }
}
class actions {
my sub escape($str) {
$str.subst('\n',"\n",:g);
}
method TOP($/) {
$/.make: $<vcalendar>.made
}
method vcalendar($/) {
$/.make: $<section>.made<VCALENDAR>;
}
method section($/) {
$/.make: "$<tag>" => %( $<thing>.map: *.made )
}
multi method thing($/ where $<property>) {
$/.make: $<property>.made;
}
multi method thing($/ where $<section>) {
$/.make: $<section>.made;
}
method single-line($/) {
$/.make: "$<tag>" => $<value>
}
method multi-line($/) {
$/.make: "$<tag>" => escape("$<multi-line-value>")
}
method property($/) {
$/.make: .made given $<single-line> || $<multi-line>;
}
}
#!/usr/bin/env perl6
use lib '.';
use ICal;
sub MAIN($file = 'one.ical', Bool :$debug) {
my $data = $file.IO.slurp;
my \p = ical.new;
my $actions = actions.new;
my $match = p.parse($data,:$actions);
my $raw = $match.made;
say $raw.keys if $debug;
say $raw<VEVENT>.keys if $debug;
say $raw<VEVENT><DTSTART> if $debug;
say $raw<VEVENT><DTEND> if $debug;
say $raw<VEVENT><DESCRIPTION>.lines.join("\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment