Perl6 already contains grammars.
Perl5 backported "named captures" from perl6:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(switch say);
#use locale;
#use re 'debug';
my $expression = qr{
(?(DEFINE)
(?<expr> (?&space)* (?&term) (?&space)* (?&opterm)? (?&space)* ; (?&space)* )
(?<term> (?&identifier)
| (?&number)
| (?&string)
)
(?<opterm> (?&space)* (?&operator) (?&space)* (?&term) (?&space)* (?&opterm)? (?&space)* )
(?<operator> [=+*/-] )
(?<identifier> [A-Za-z_][A-Za-z0-9_]+ )
(?<number> [0-9]+ )
(?<string> (?"e) ( (?&char) | (?&bsquote) )*? (?"e) )
(?<quote> \" )
(?<char> [^\\\"] )
(?<bsquote> \\. )
(?<space> [ \t] )
)
(?&expr)
}x;
while (<>) {
chomp;
if ( /^ $expression $/x ) {
say "Correct expression: $_";
}else {
say "Incorrect expression: $_";
}
}