On Tue, Jun 10, 2014 at 10:35:41AM +0100, Andrew Beverley wrote: > On Tue, 2014-06-10 at 10:05 +0100, James Laver wrote: > > I was sort of hoping that the not too subtle hints that using eval is a > > bad idea would pay off. Apparently not. > > D'oh, I thought someone might say that... But it's so easy ;-) > > Got the message, will play with a parser.
Note that all you need is a *validating* parser. You don't have to bother with building a parse tree, and evaluating the results -- *that* can be left to Perl. Here's a pattern that accepts expressions of the form you initially posted (and I've replaced [var] with "var"): #!/usr/bin/perl use 5.010; use strict; use warnings; no warnings 'syntax'; use Test::Regexp; use Test::More; my $pat = qr { (?(DEFINE) (?<expression> (?&term) (?: \ * (?: [-<>+*] | && | eq ) \ * (?&expression))?) (?<term> \( (?&expression) \) | " [a-z]+ " | [0-9]+)) ^(?&expression)$ }x; my $test = Test::Regexp:: -> new -> init ( keep_pattern => $pat, no_keep_message => 1, name => "Expression" ); # # Using (?<name>PAT) leaves traces in %- behind, even if they don't # actually capture... # my $captures = [[expression => undef], [term => undef]]; $test -> match ('"age" > 10 && "price" < ("age" + 5) * 10', captures => $captures); $test -> no_match ('"@{qx (rm -rf)}" && 1'); done_testing; __END__