in reply to •Re: Solution: Parse::RecDescent and mini-language parsing
in thread Parse::RecDescent and mini-language parsing

Ok, I ran the benchmark, and it seems the regex form is faster. I have tested it several times with the following code and results:

use Parse::RecDescent; use Date::Calc qw(:all); use Benchmark ':all'; use strict; use warnings; my $grammar1 = q~ logic: expression eod { $return = $item[1]; } expression: <leftop: term termop term> termop: /and/i | /xor/i | /or/i term: '(' <commit> expression ')' { $return = $item[3]; } #[@item[1,3,4]]; } # Only include eleme +nts important to later processing | condition condition: element comparison element { $return = main::process(@item[1..3]); } element: '<' <commit> /-?\w+/ '>' { $return = "<$item[3]>"; } #Return this so that the conditio +n value can be set | /\d+/ # num is automatically returned comparison: /(=[><]=)/ <commit> <error: Unable to match comparison, + $1> | /=?[><]=?/ | '=' | '!=' eod: /^\Z/ ~; my $grammar2 = q~ logic: expression eod { $return = $item[1]; } expression: <leftop: term termop term> termop: /and/i | /xor/i | /or/i term: '(' <commit> expression ')' { $return = $item[3]; } #[@item[1,3,4]]; } # Only include eleme +nts important to later processing | condition condition: element comparison element { $return = main::process(@item[1..3]); } element: '<' <commit> /-?\w+/ '>' { $return = "<$item[3]>"; } #Return this so that the conditio +n value can be set | /\d+/ # num is automatically returned comparison: '<=' | '<' | '=' | '>=' | '>' | '!=' eod: /^\Z/ ~; my $parser1 = new Parse::RecDescent($grammar1) or die; my $parser2 = new Parse::RecDescent($grammar2) or die; my $test = '<DAY> = 4 or <DAY> > 4 or <DAY> < 4 or <DAY> >= 4 or <DAY> + <= 4 or <DAY> != 4'; cmpthese(10000,{ 'regex' => sub { $parser1->logic($test); }, 'quote' => sub { $parser2->logic($test); }, });

Yielded:

Rate quote regex quote 116/s -- -5% regex 123/s 6% --

This one added the =>= which I wanted to avoid, and while it slowed down both slightly, the regex was still in the lead.

use Parse::RecDescent; use Date::Calc qw(:all); use Benchmark ':all'; use strict; use warnings; my $grammar1 = q~ logic: expression eod { $return = $item[1]; } expression: <leftop: term termop term> termop: /and/i | /xor/i | /or/i term: '(' <commit> expression ')' { $return = $item[3]; } #[@item[1,3,4]]; } # Only include eleme +nts important to later processing | condition condition: element comparison element { $return = main::process(@item[1..3]); } element: '<' <commit> /-?\w+/ '>' { $return = "<$item[3]>"; } #Return this so that the conditio +n value can be set | /\d+/ # num is automatically returned comparison: /(=[><]=)/ <commit> <error: Unable to match comparison, + $1> | /=?[><]=?/ | '=' | '!=' eod: /^\Z/ ~; my $grammar2 = q~ logic: expression eod { $return = $item[1]; } expression: <leftop: term termop term> termop: /and/i | /xor/i | /or/i term: '(' <commit> expression ')' { $return = $item[3]; } #[@item[1,3,4]]; } # Only include eleme +nts important to later processing | condition condition: element comparison element { $return = main::process(@item[1..3]); } element: '<' <commit> /-?\w+/ '>' { $return = "<$item[3]>"; } #Return this so that the conditio +n value can be set | /\d+/ # num is automatically returned comparison: '<=' | '<' | '=' | '>=' | '>' | '!=' eod: /^\Z/ ~; my $parser1 = new Parse::RecDescent($grammar1) or die; my $parser2 = new Parse::RecDescent($grammar2) or die; my $test = '<DAY> = 4 or <DAY> > 4 or <DAY> < 4 or <DAY> >= 4 or <DAY> + <= 4 or <DAY> != 4 or <DAY> =<= 4'; cmpthese(10000,{ 'regex' => sub { $parser1->logic($test); }, 'quote' => sub { $parser2->logic($test); }, });

Yielded:

Rate quote regex quote 104/s -- -7% regex 113/s 8% --

I admit, neither is as fast as I would like, but it certainly appears that the regex is the fastest method there, unless I made a mistake.

Edit: If you feel this was biased in any way, feel free to suggest another string, or another test altogether. I don't use the benchmark module frequently, and I may have inadevertently allowed for some bias.



My code doesn't have bugs, it just develops random features.

Flame ~ Lead Programmer: GMS (DOWN) | GMS (DOWN)

Replies are listed 'Best First'.
•Re: Re: •Re: Solution: Parse::RecDescent and mini-language parsing
by merlyn (Sage) on Apr 05, 2003 at 04:17 UTC
    OK, so alternations are not as fast as I'd like {grin}. Try this... it means the same thing, but in one regex:
    comparison: / <=? | = | >=? | != /x
    It's important to understand that a regex is matched left-to-right for alternatives, so you have precise control over the possible matches.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.