in reply to To make the Model WORK

but I can't see where it's going south and returning an array (or the string expression of an array). In other similar cases (outside the ifthenelse-decoder) sub-expression results are returned properly.
ifthenelse: if elsif(s?) else(?) endif
Since there may be more than one elsif, and else may be optional, these corresponding subexpressions return arrays (see Subrules from P::RD's docs). For example, in this production, $item[2] is an array of the semantic values of all the elsif nonterminals that were found at this point.

Two points:

use Parse::RecDescent; use Data::Dumper; my $parser = Parse::RecDescent->new(<<'END_GRAMMAR'); expr: /\d+/ { $item[1] } | ifthenelse { $item[1] } ifthenelse: "if" expr "then" expr elsif(s?) else(?) "endif" { [ if => [@item[2,4]], @{$item[5]}, ref $item[6] ? $item[6][0] : undef ] } elsif: "elsif" expr "then" expr { [ @item[2,4] ] } else: "else" expr { $item[2] } END_GRAMMAR for (<DATA>) { print $_; print Dumper $parser->expr($_); } __DATA__ if 1 then 2 else 3 endif if 1 then 2 endif if 1 then 2 elsif 3 then 4 elsif 5 then 6 endif if 1 then 2 elsif 3 then 4 else 5 endif
This returns an array that is structured like this:
[ "if", [ cond1, result1 ], # first "if" condition/result expression + pair [ cond2, result2 ], # 0 or more "elsif" expression pairs ... otherwise ] # else branch expression, or undef if no +ne
This data structure is fairly uniform, and should be easy to evaluate for whatever it is you're doing.

blokhead

Replies are listed 'Best First'.
Re^2: To make the Model WORK
by ikegami (Patriarch) on Jul 13, 2005 at 16:48 UTC

    The function evaluating the parse tree can be simplified if you eliminate elsif at compile time. Keep in mind that

    if cond1 then action1 elsif cond2 then action2 elsif cond3 then action3 else action4 endif

    is equivalent to

    if cond1 then action1 else if cond2 then action2 else if cond3 then action3 else action4 endif endif endif

    except the latter is easier to evaluate because the parse tree is simply

    [ if => cond1, action1, [ if => cond2, action2, [ if => cond3, action3, action4 ] ] ]

    See my reply below (under the heading "The following returns a nice tree for expr to evaluate") for an implementation.

Re^2: To make the Model WORK
by samizdat (Vicar) on Jul 13, 2005 at 16:18 UTC
    Ahhh... *thanks*, blokhead. Thanks, also, for your comments. Of necessity, I've compressed my example way down (expr has 16 alternate forms, for example), but gems of wisdom are always worth my time to consider.