I'd suggest separating parsing from evaluation. The first argument to the action subroutines is a hash that you can use for any purpose. In this case, I'd store parts of the specification in there, then return that hash (which makes the convenient default ::= action => ::first work for the Dice_Expression rule). Also, I split modifier_r_comp from modifier_r action, but you could equally merge them and count the number of arguments.
use Marpa::R2;
use Data::Dump;
my $dsl = <<'END_OF_DSL';
:default ::= action => ::first
lexeme default = latm => 1
Dice_Expression ::= Dice_Expression1
| Dice_Expression1 add_modifier
Dice_Expression1 ::= Simple_Dice
| Simple_Dice x_modifier
| Simple_Dice r_modifier
Simple_Dice ::= Rolls 'd' Sides action => sim
+ple_roll
add_modifier ::= '+' Die_Modifier_Val action => mod
+ifier_add
| '-' Die_Modifier_Val action => mod
+ifier_add
x_modifier ::= 'x' Die_Modifier_Val action => mod
+ifier_x
r_modifier ::= 'r' Die_Modifier_Val action => mod
+ifier_r
| 'r' Die_Modifier_Comp Die_Modifier_Val action => mod
+ifier_r_comp
Die_Modifier_Val ~ digits
Die_Modifier_Comp ~ 'gt' | 'lt'
Rolls ~ digits
Sides ~ digits
digits ~ [\d]+
:discard ~ whitespace
whitespace ~ [\s]+
END_OF_DSL
my $grammar = Marpa::R2::Scanless::G->new( { source => \$dsl } );
my $input = $ARGV[0] // '6d4x1';
my $parsed = $grammar->parse( \$input, 'My_Actions' );
print "\n\nParsed result: ";dd $parsed;
# print "\n\nFinal result: ";dd evaluate_rolls($parsed);
sub evaluate_rolls {
my $spec = shift;
# TODO...
}
sub My_Actions::modifier_add {
my ( $self, $sign, $val ) = @_;
$$self{add} = 0 + "$sign$val";
$self;
}
sub My_Actions::modifier_r {
my ( $self, undef, $reroll ) = @_;
$$self{r} = $reroll;
return $self;
}
sub My_Actions::modifier_r_comp {
my ( $self, undef, $comp, $reroll ) = @_;
$$self{comp} = $comp;
$$self{r} = $reroll;
return $self;
}
sub My_Actions::simple_roll {
my ( $self, $rolls, undef, $sides ) = @_;
$$self{rolls} = $rolls;
$$self{sides} = $sides;
return $self;
}
sub My_Actions::modifier_x {
my ( $self, $modifier, $modifier_val ) = @_;
$$self{x} = $modifier_val;
return $self;
}
Update: Added +/- modifiers
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.