use Parse::RecDescent; use Data::Dumper; my $grammar = q{ startrule: logical_expr logical_expr: comparison_expr logical_op logical_expr { [@item[1,2,3]] } | comparison_expr logical_op: /\\|\\||or|&&|and/ comparison_expr: paren_expr comparison_op comparison_expr { [@item[1,2,3]] } | paren_expr comparison_op: />=?|<=?|!=|==|le|ge|eq|ne|lt|gt/ paren_expr: '(' logical_expr ')' { $item[2] } | atom atom: /[A-Za-z_][A-Za-z0-9_]*/ }; my $parser = new Parse::RecDescent $grammar; for () { print $_; print Dumper $parser->startrule($_); print "============\n"; } __DATA__ foo == bar || baz < bar foo == bar || baz < bar || foo && bar (foo || bar) || baz