#! /usr/bin/perl use strict; use warnings; use 5.010; my $query = q{ body:("et tu" (Brute OR Caesar)) AND published:[1900 TO 2010] NOT author:Shakespeare }; my $grammar = do{ use Regexp::Grammars; qr{ \A \s* <Query> \s* \Z <rule: Query> <[And_Clause]>+ % (OR) <rule: And_Clause> <[Term]>+ % <[And_Operator]> <rule: And_Operator> AND | NOT | \s++ <MATCH=(?{'AND'})> <token: Term> (?: <Field> : )? (?: \( <Subquery=Query> \) | <Range> | <Value=Quoted_Value> | <Value=Raw_Value> ) <token: Field> <.Non_Keyword> \w++ <rule: Range> \[ <From=(.*?)> TO <To=(.*?)> \] <rule: Quoted_Value> ' <MATCH=( [^'\\]*+ (?: \\. [^'\\]*+ )*+ )> ' | " <MATCH=( [^"\\]*+ (?: \\. [^"\\]*+ )*+ )> " <rule: Raw_Value> <.Non_Keyword> [^'"()][^\s()]*+ <token: Non_Keyword> (?! NOT | AND | OR | \( | \) ) }xms; }; if ($query =~ $grammar) { use Data::Dumper 'Dumper'; say Dumper \%/; } else { say 'Failed'; }