{ sub consumer { my $text = shift; my $closure = sub { substr $text, 0, length($text) - length($_[0]) } } } start : entry(s) { $::res } entry : comment | def | def : def : # The // skips initial whitespace so it won't end up in $p_text def : // { $p_cons = consumer($text) } phrase { $p_text = $p_cons->($text) } '=' meanings ';' { $::res->{$p_text} = $item{meanings} } comment : /#.*(?=\n)/m phrase : ident(s) ident : /[\w&\.'-]+/ meanings : meaning(s /:/) meaning : meaning : // { $m_cons = consumer($text) } element(s /,?/) { $m_cons->($text) } element : alternation(s /\|/) alternation : expr(s /[+>]/) expr : /!?/ term term : ident '(' meaning ')' | ident