FAQ
Hi all,

I've got another problem and I'm hoping someone can point me in the right
direction.

My grammar is for a "language" that includes an "if" type command. The "if"
command takes an expression, and two other commands. Depending on the values
of the expression, ONE of the commands is supposed to be executed. However,
what I'm seeing is that BOTH commands are being evaluated, but the results of
only one of the commands is being used.

Here is a snippet of the grammar:

===================================================================
if: "[#if(" boolean_expression "," command "," command ")]"
{
if ($item[2] eq "true") {
$return = $item[4];
} else {
$return = $item[6];
}
}

command: variable | include | word | quoted_string
{
$return = $item[1];
}

include: "[#include(" file_path ")]"
{
$return = main::parse_page($item[2]);
}
...
===================================================================

So, in the case where we have a true expression, both commands are being
evaluated, but only the results of one of the commands is returned. The
problem is that, as in the case of an "include" command, the commands might
have side-affects.

I'm sure this is a common design pattern. Perhaps there is an "easy" way to
deal with this?


--

Take care and have fun,
Mike Diehl.

Search Discussions

  • Mike Diehl at Sep 5, 2009 at 10:58 pm
    Well, I've continued to think about this and I've got some more questions.

    I did read up on the <defer: directive. I don't think that will help me. If
    I'm missing something, please let me know.

    So, I've come up with two different ways to handle this situation:

    1. Pass in a boolean areguement to each production, and if that arguement
    is "true" process the action, otherwise, simply return the TEXT of the
    matched expression.

    This way, my if statement passes [1] and [0] to the two clauses. This
    introduces substantial logic into my grammar, though.

    2. The other way is to build the "parse tree" inside the grammar and
    then "walk" the tree. This would entail almost completely rewriting my
    grammar actions. But this way would also, potentially?, allow me to compile
    my language and forgo the parser step alltogether.

    Which method would you recommend?

    TIA,

    Mike.
    On Thursday 03 September 2009 15:25:29 Mike Diehl wrote:
    Hi all,

    I've got another problem and I'm hoping someone can point me in the right
    direction.

    My grammar is for a "language" that includes an "if" type command. The
    "if" command takes an expression, and two other commands. Depending on the
    values of the expression, ONE of the commands is supposed to be executed.
    However, what I'm seeing is that BOTH commands are being evaluated, but the
    results of only one of the commands is being used.

    Here is a snippet of the grammar:

    ===================================================================
    if: "[#if(" boolean_expression "," command "," command ")]"
    {
    if ($item[2] eq "true") {
    $return = $item[4];
    } else {
    $return = $item[6];
    }
    }

    command: variable | include | word | quoted_string
    {
    $return = $item[1];
    }

    include: "[#include(" file_path ")]"
    {
    $return = main::parse_page($item[2]);
    }
    ...
    ===================================================================

    So, in the case where we have a true expression, both commands are being
    evaluated, but only the results of one of the commands is returned. The
    problem is that, as in the case of an "include" command, the commands might
    have side-affects.

    I'm sure this is a common design pattern. Perhaps there is an "easy" way
    to deal with this?


    --

    Take care and have fun,
    Mike Diehl.
  • Damian Conway at Sep 7, 2009 at 10:53 pm

    Mike Diehl pondered:

    Well, I've continued to think about this and I've got some more questions.

    I did read up on the <defer: directive.  I don't think that will help me.  If
    I'm missing something, please let me know.
    No, it won't help. The problem is that you want to *parse* every command, but
    not *execute* every command (only the ones in the correct branches of the if).

    So, I've come up with two different ways to handle this situation:

    1.  Pass in a boolean areguement to each production, and if that arguement
    is "true" process the action, otherwise, simply return the TEXT of the
    matched expression.

    This way, my if statement passes [1] and [0] to the two clauses.  This
    introduces substantial logic into my grammar, though.

    2.  The other way is to build the "parse tree" inside the grammar and
    then "walk" the tree.  This would entail almost completely rewriting my
    grammar actions.  But this way would also, potentially?, allow me to compile
    my language and forgo the parser step alltogether.

    Which method would you recommend?
    Definitely, the second approach. There's a good reason that people
    usually separate compilation and execution: namely that mixing them is
    both vastly more complex and considerably more error-prone.

    Damian
  • Mike Diehl at Sep 9, 2009 at 2:52 pm

    On Monday 07 September 2009 16:52:31 Damian Conway wrote:
    Mike Diehl pondered:
    Well, I've continued to think about this and I've got some more
    questions.

    I did read up on the <defer: directive.  I don't think that will help me.
    If I'm missing something, please let me know.
    No, it won't help. The problem is that you want to *parse* every command,
    but not *execute* every command (only the ones in the correct branches of
    the if).
    So, I've come up with two different ways to handle this situation:

    1.  Pass in a boolean areguement to each production, and if that
    arguement is "true" process the action, otherwise, simply return the TEXT
    of the matched expression.

    This way, my if statement passes [1] and [0] to the two clauses.  This
    introduces substantial logic into my grammar, though.

    2.  The other way is to build the "parse tree" inside the grammar and
    then "walk" the tree.  This would entail almost completely rewriting my
    grammar actions.  But this way would also, potentially?, allow me to
    compile my language and forgo the parser step alltogether.

    Which method would you recommend?
    Definitely, the second approach. There's a good reason that people
    usually separate compilation and execution: namely that mixing them is
    both vastly more complex and considerably more error-prone.

    Damian
    I did finally, rewrite the whole thing using the second approach. This was
    CONSIDERABLY more complex, as I had to navigate a fairly complex parse tree.
    I think I've done something wrong, as I'm still finding bugs... I'll do some
    more reading, though.

    Anyway, this is a nice final design, though. Because I now have a parse tree,
    I have the potential of serializing that data structure to an external file
    and saving the expense of launching the parser each time my program runs.
    This amounts to creating a JIT compiler! Should be MUCH more efficient,
    right?

    Any recommendations between the various modules for this purpose?
    Data::Dumper, Storable, Serialize?

    BTW Damian, RD is a nice piece of work. It's almost FUN to use.

    --

    Take care and have fun,
    Mike Diehl.
  • Damian Conway at Sep 10, 2009 at 10:49 am

    Mike Diehl reported back:

    I did finally, rewrite the whole thing using the second approach.  This was
    CONSIDERABLY more complex, as I had to navigate a fairly complex parse tree.
    I think I've done something wrong, as I'm still finding bugs...  I'll do some
    more reading, though.
    One way to make the job easier is to have P::RD bless each node in
    your parse tree
    (look up "Autotrees" in the module documentation or take a look at
    demo_LaTeXish.pl
    and demo_eval.pl that come with the module). Then you create methods
    in each of the
    node classes, and let them work out the tree traversal themselves.

    Anyway, this is a nice final design, though.  Because I now have a parse tree,
    I have the potential of serializing that data structure to an external file
    and saving the expense of launching the parser each time my program runs.
    This amounts to creating a JIT compiler!  Should be MUCH more efficient,
    right?
    Yes, it should be.

    Any recommendations between the various modules for this purpose?
    Data::Dumper, Storable, Serialize?
    I tend to use Data::Dumper myself.

    BTW Damian, RD is a nice piece of work.  It's almost FUN to use.
    Glad you're finding it useful.

    Damian

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouprecdescent @
categoriesperl
postedSep 3, '09 at 9:24p
activeSep 10, '09 at 10:49a
posts5
users2
websitemetacpan.org...

2 users in discussion

Mike Diehl: 3 posts Damian Conway: 2 posts

People

Translate

site design / logo © 2019 Grokbase