-use Regexp::Common qw /delimited/;
-
-# States
-use constant VALUE => 1;
-use constant AGGREG => 2;
-use constant OP => 4;
-use constant PAREN => 8;
-use constant KEYWORD => 16;
-my @tokens = qw[VALUE AGGREG OP PAREN KEYWORD];
-
-my $re_aggreg = qr[(?i:AND|OR)];
-my $re_value = qr[$RE{delimited}{-delim=>qq{\'\"}}|\d+];
-my $re_keyword = qr[$RE{delimited}{-delim=>qq{\'\"}}|(?:\{|\}|\w|\.)+];
-my $re_op = qr[=|!=|>=|<=|>|<|(?i:IS NOT)|(?i:IS)|(?i:NOT LIKE)|(?i:LIKE)]; # long to short
-my $re_paren = qr'\(|\)';
-
-sub _parser {
- my ($self,$string) = @_;
- my $want = KEYWORD | PAREN;
- my $last = undef;
-
- my $depth = 0;
-
- my ($ea,$key,$op,$value) = ("","","","");
-
- while ($string =~ /(
- $re_aggreg
- |$re_keyword
- |$re_value
- |$re_op
- |$re_paren
- )/igx ) {
- my $val = $1;
- my $current = 0;
-
- # Highest priority is last
- $current = OP if _match($re_op,$val);
- $current = VALUE if _match($re_value,$val);
- $current = KEYWORD if _match($re_keyword,$val) && ($want & KEYWORD);
- $current = AGGREG if _match($re_aggreg,$val);
- $current = PAREN if _match($re_paren,$val);
-
- unless ($current && $want & $current) {
- # Error
- # FIXME: I will only print out the highest $want value
- die "Error near ->$val<- expecting a ", $tokens[((log $want)/(log 2))], " in $string\n";
- }
-
- # State Machine:
-
- # Parens are highest priority
- if ($current & PAREN) {
- if ($val eq "(") {
- $depth++;
- $self->_OpenParen;
-
- } else {
- $depth--;
- $self->_CloseParen;
- }
-
- $want = KEYWORD | PAREN | AGGREG;
- }
- elsif ( $current & AGGREG ) {
- $ea = $val;
- $want = KEYWORD | PAREN;
- }
- elsif ( $current & KEYWORD ) {
- $key = $val;
- $want = OP;
- }
- elsif ( $current & OP ) {
- $op = $val;
- $want = VALUE;