#!/usr/bin/perl

use Parse::RecDescent;

my $parser = new Parse::RecDescent q{

        expression :    term 'or' expression
                                { $return = "$item[1] || $item[3]" }
                   |    term

        term       :    factor 'and' term
                                { $return = "$item[1] && $item[3]"}
                   |    factor

        factor     :    '(' expression ')'
                                { $return = "( $item[2] )" }
                   |    'not' expression
                                { $return = "!$item[2]" }
                   |    string

        string     :
                        '"' /[^"]+/ '"'
                                { $return = "/$item[2]/" }

                   # The ...! is a negative lookahead.

                   |    ...!'or' ...!'and' ...!'not' /[^ \\t\\n()]+/
                                { $return = "/$item[4]/" }
};

$text = 'abc and def or (ghi and not "jkl mno")';

print $parser->expression( $text ), "\n";
