in reply to To make the Model WORK

ifthenelse: if elsif(s?) else(?) endif { ... }

Because of the (s), elsif(s?) returns a reference to an array of "stuff that elsif matches". The array may contain 0 or more elements. That means the line identified below will always return true for $item[2]

ifthenelse: if elsif(s?) else(?) endif { $return = 'NIL'; for (my $i = 1; $i < @item; $i++) { print " iftest: $i '" . $item[$i] . "'\n"; if ($item[$i] ne 'NIL') { # Always true for $item[2]. $return = $item[$i]; # Always an array ref for $item[2]. last; # Always gets here for $item[2]. } } ... }

Comments:

By the way, why are you using 'NIL'? It would be more convenient to use a false value. Only undef will fail the production, so you can use 0 and '' safely.

Also, do you realize the above allows for if if var then var endif then var endif? if is rarely considered an expression. The ternary conditional operator in Perl (... ? ... : ...) and in Excel (@IF(..., ..., ...)) are examples of where ifs are expressions.

Finally, I find it very odd that you evaluate at compile time. For example, in
if cond then action1 else action2 endif
you unconditionally evaluate action1 first, then you unconditionally evaluate action2, then you decide which value to return based on cond. That is dangerous.

The following returns a nice tree for expr to evaluate:

expr : if { # I doubt this should be in the grammar. $return = evaluate($main::c_v, $item[1]); } if : /if/i expr /then/i expr if_(?) { [ if => @item[2, 4, 5] ] } if_ : elsif { $item[1] } | else { $item[1] } elsif : /elsif/i expr /then/i expr if_ { [ if => @item[2, 4, 5] ] } else : /else/i expr { $item[2] }

Replies are listed 'Best First'.
Re^2: To make the Model WORK
by samizdat (Vicar) on Jul 13, 2005 at 16:32 UTC
    25-year programmer showing graying roots. :) Real returned values might be '0', as well. That would fail.

    I'm fortunate that, the way I've built this, now all I need to do is to 'flatten' the @item from IFTHENELSE into a one-dimensional array and then iterate. The first non-NIL result found will be returned, and I don't care which elsif or else clause gave it to me. Thanks to you and blokhead both, I see light illuminating repeated subrules. :D
      Real returned values might be '0', as well. That would fail.

      Nope. '0' will not fail a production. Only undef.

      I stand corrected:

      use Parse::RecDescent; my $parser; $parser = Parse::RecDescent->new(q` test: { $return = 1 } `); print($parser->test('') ? 'ok' : 'fail', "\n"); # ok $parser = Parse::RecDescent->new(q` test: { $return = 0 } `); print($parser->test('') ? 'ok' : 'fail', "\n"); # fail $parser = Parse::RecDescent->new(q` test: { $return = '0' } `); print($parser->test('') ? 'ok' : 'fail', "\n"); # fail $parser = Parse::RecDescent->new(q` test: { $return = undef } `); print($parser->test('') ? 'ok' : 'fail', "\n"); # fail $parser = Parse::RecDescent->new(q` test: /\d+/ `); print($parser->test('1') ? 'ok' : 'fail', "\n"); # ok print($parser->test('0') ? 'ok' : 'fail', "\n"); # fail

      I never got into that situation, because I'd be returning
      [ ident   => ident ]
      or
      [ literal => literal ]
      or
      [ '*'     => expr, expr ]
      or
      [ '/'     => expr, expr ]
      or
      ...

Re^2: To make the Model WORK
by samizdat (Vicar) on Jul 13, 2005 at 17:16 UTC

    Finally, I find it very odd that you evaluate at compile time. For example, in if cond then action1 else action2 endif you unconditionally evaluate action1 first, then you unconditionally evaluate action2, then you decide which value to return based on cond. That is dangerous.



    My task is to reduce a whole bunch of SPICE equations from static files to parameter values. None of these have side-effects, so the 'danger' seems minimal. I built a monster hash with local and non-local variables and their values, and my goal is to recursively reduce them until I hit a variable which is undefined by the fab process team or resolves to divide-by-zero. The grammar is very ill-defined, but P::RD is actually handling it quite well.

    I wish I'd had an easier task than this for my first P::RD work, but, well, "Needs must when the customer drives." Thanks for all your patience and examples! I will peruse to grok further!:D