locked_user sundialsvc4 has asked for the wisdom of the Perl Monks concerning the following question:

I have to deal with a file containing possibly thousands of SQL statements.   Right now, I’m using a right-recursive rule:

DDL_stmtlist: DDL_statement(?) /;/ <commit> DDL_stmtlist

... and getting a warning message about “deep recursion,” which I would like to avoid.

I admit that I wrote one parser this way, and I have stuck to it (for better or worse) without seriously re-visiting the question of if there might be a cleaner, better way.   I’m sure there is . . .

Urgh... my fading memory.   Of course I know about (s /;/), and I seem to remember that there was a perfectly-good reason why I could not use it...   Maybe this post makes zero sense at all, which is what I get for posting at the end of a day.

Replies are listed 'Best First'.
Re: Better way than tail-recursion in Parse::RecDescent?
by JavaFan (Canon) on Oct 30, 2010 at 00:08 UTC
    Why not:
    DDL_stmtlist: <leftop: DDL_statement(?) ';' DDL_statement(?)>

      I haven’t spent enough time looking at <leftop> although I am given to understand that the (s /;/) syntax is supposed to be equivalent...

      One issue that, as I now recall, was one reason for my latching-on to tail recursion ... was error messages.   If there was an error somewhere some statement, deep down in the file, the only error-message that actually popped-out was from the <error> production of the outermost rule.   I freely admit that I think I have built stuff that “works, sort of ...”   Well, actually it works very well, in terms of the results that it now allows us to obtain.   But I know that it was not built properly and I would like to fix it now rather than later.   Yes, I am running this thing on a machine that’s big enough to run 20 or more SAS® jobs at once.   But, because the results are already well on their way to being “mission critical” for this workgroup, I know that insufficiency in these parsers will definitely come back to bite me soon.

      Can anyone point me to some really good, in depth material on substantial applications/case-studies of Parse::RecDescent?   I need to sip from a firehose on how to really use this thing right.   I need to read war-stories in detail.

        I presume you have

        { use strict; use warnings; }

        inside your grammar. Add

        no warnings 'recursion';

        to that block.

        You are precompiling, right? You can see the generated parser by looking at that .pm file.

        How about something like:
        { my @stmterrs; } DDL_stmtlist: DDL_statement(s? /;/) { if (@stmterrs) { push(@{$thisparser->{errors}}, @stmterrs); undef; } else { 1; } } DDL_statement: whatever | { push(@stmterrs, ["something fishy", $thisline]); } <resync: /[^;]*/s >
        DDL_statement will now "succeed" until the end of the input. But you get to keep every error you encounter along the way.