I admit this example is a bit contrived, but it helps focus on what I'm trying to do...

Say I have a file like:

bang !some text! at @more words@ percent %good stuff% star !not in stars!

I'm trying to match lines where the delimiter is specified by the keyword in the first column.

I can hard-code everything statically, like this:

#!/usr/bin/env perl6 use Test; our grammar StatGrammar { rule TOP { [ <bang-line> | <at-line> | <hash-line> | <dollar-line> | <percent-line> | <caret-line> | <and-line> | <star-line> ] } regex bang-line { ^ 'bang' \s+ '!' (.*?) '!' \n? $ } regex at-line { ^ 'at' \s+ '@' (.*?) '@' \n? $ } regex hash-line { ^ 'hash' \s+ '#' (.*?) '#' \n? $ } regex dollar-line { ^ 'dollar' \s+ '$' (.*?) '$' \n? $ } regex percent-line { ^ 'percent' \s+ '%' (.*?) '%' \n? $ } regex caret-line { ^ 'caret' \s+ '^' (.*?) '^' \n? $ } regex and-line { ^ 'and' \s+ '&' (.*?) '&' \n? $ } regex star-line { ^ 'star' \s+ '*' (.*?) '*' \n? $ } } our class StatActions { method TOP($/) { make $<bang-line>[0] if $<bang-line>; make $<at-line>[0] if $<at-line>; make $<hash-line>[0] if $<hash-line>; make $<dollar-line>[0] if $<dollar-line>; make $<percent-line>[0] if $<percent-line>; make $<caret-line>[0] if $<caret-line>; make $<and-line>[0] if $<and-line>; make $<star-line>[0] if $<star-line>; } } sub static(Str $str) { StatGrammar.parse($str, :actions(StatActions)).made } is static('bang !one!' ), 'one', 'parse bang!one ok'; isnt static('bang @one@' ), 'one', 'isnt bang@one ok'; nok StatGrammar.parse('bang @one@', :actions(StatActions)), 'nok';

But that feels kind of gross, and not very DRY...

I can also do this:

#!/usr/bin/env perl6 use Test; our %sigils = ( bang => '!', at => '@', hash => '#', dollar => '$', percent => '%', caret => '^', and => '&', star => '*', ); our grammar DynGrammar { regex TOP { ^ (\w+) \s+ (.*?) \n? $ } } our class DynActions { method TOP($/) { if $1.match( rx/ ^ "{%sigils{$0}}" (.*?) "{%sigils{$0}}" $ / ) - +> $match { make $match[0]; } } } sub dyn(Str $str) { DynGrammar.parse($str, :actions(DynActions)).made } is dyn('bang !one!' ), 'one', 'parse bang!one ok'; isnt dyn('bang @one@' ), 'one', 'isnt bang@one ok'; nok DynGrammar.parse('bang @one@', :actions(DynActions)), 'nok';

Which *ALMOST* works... Except that the mismatch, erm, "fails to fail".

Can anybody think of a way to either A: 'fail' a match from within an action, or B: move my pattern matching up into the grammar itself? (or C: tell me I'm going about it all wrong, and suggest a better way, hehe!)

Cheers! :-D


In reply to Perl6: Dynamic Grammars by OneTrueDabe

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.