Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Deferred interpretation?

1 view
Skip to first unread message

Mike Diehl

unread,
Sep 3, 2009, 5:25:29 PM9/3/09
to recde...@perl.org
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.

Mike Diehl

unread,
Sep 5, 2009, 6:59:37 PM9/5/09
to recde...@perl.org
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.

Damian Conway

unread,
Sep 7, 2009, 6:52:31 PM9/7/09
to Mike Diehl, recde...@perl.org
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

unread,
Sep 9, 2009, 10:54:17 AM9/9/09
to Damian Conway, recde...@perl.org

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.

Damian Conway

unread,
Sep 10, 2009, 6:49:04 AM9/10/09
to Mike Diehl, recde...@perl.org
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

0 new messages