My Perl solution. I used the Marpa::R2 library to write a parser. It supports rule precedence, so solving the part 2 took me just a minute.
#!/usr/bin/perlusewarnings;usestrict;usefeatureqw{ say };useList::Utilqw{ sum };useMarpa::R2;my$DSL=<<'__DSL__';:default::=action=>[name,values]lexemedefault=latm=>1Expression::=('(')Expression(')')assoc=>groupaction=>::first|digitsaction=>::first||ExpressionopExpressionaction=>main::operatewhitespace~[\s]+
digits ~ [\d]+
op ~ [+*]:discard~whitespace__DSL__sub operate{{'+'=>sub {$_[0]+$_[1]},'*'=>sub {$_[0]*$_[1]}}->{$_[2]}->($_[1],$_[3])}my$grammar='Marpa::R2::Scanless::G'->new({source=>\$DSL});sub evaluate{my($expression)=@_;return${$grammar->parse(\$expression)}}saysum(mapevaluate($_),<>);
My Perl solution. I used the Marpa::R2 library to write a parser. It supports rule precedence, so solving the part 2 took me just a minute.
For part 2, the DSL is