I'm doing Advent of Code day 9:
You sit for a while and record part of the stream (your puzzle input). The characters represent groups - sequences that begin with
{
and end with}
. Within a group, there are zero or more other things, separated by commas: either another group or garbage. Since groups can contain other groups, a}
only closes the most-recently-opened unclosed group - that is, they are nestable. Your puzzle input represents a single, large group which itself contains many smaller ones.Sometimes, instead of a group, you will find garbage. Garbage begins with
<
and ends with>
. Between those angle brackets, almost any character can appear, including{
and}
. Within garbage,<
has no special meaning.In a futile attempt to clean up the garbage, some program has canceled some of the characters within it using
!
: inside garbage, any character that comes after!
should be ignored, including<
,>
, and even another!
.
Of course, this screams out for a Perl 6 Grammar...
grammar Stream
{
rule TOP { ^ <group> $ }
rule group { '{' [ <group> || <garbage> ]* % ',' '}' }
rule garbage { '<' [ <garbchar> | <garbignore> ]* '>' }
token garbignore { '!' . }
token garbchar { <-[ !> ]> }
}
This seems to work fine on simple examples, but it goes wrong with two garbchar
s in a row:
say Stream.parse('{<aa>}');
gives Nil
.
Grammar::Tracer
is no help:
TOP
| group
| | group
| | * FAIL
| | garbage
| | | garbchar
| | | * MATCH "a"
| | * FAIL
| * FAIL
* FAIL
Nil
Multiple garbignore
s are no problem:
say Stream.parse('{<!!a!a>}');
gives:
「{<!!a!a>}」
group => 「{<!!a!a>}」
garbage => 「<!!a!a>」
garbignore => 「!!」
garbchar => 「a」
garbignore => 「!a」
Any ideas?
token group { '{' ~ '}' [ <group> || <garbage> ]* % ',' }
as it puts the{
and}
together. – Volitant}
, and there are some benefits to that, but I personally think that's less readable, since you can no longer simply read from left to right. – Domitiladomonic