php - Parsing Preformatted Formula to Array Recursively -


i trying create formula parser , stuck on how recursively convert code array of expressions. take following formula example:

$formula = "     @var[a, 3];     @if[ (a <= 3) & (a = 3) ]:         @var[a, + 4];         @if[ > 5 ]:             @use[a];         @endif     @elseif[ > 4 ]:         @var[a, 2];     @else:         @var[a, 5];     @endif     @var[a,5];     @use[a]; "; 

should output:

{     "0": "var[a, 3];",     "if[ (a <= 3) & (a = 3) ]:": {         "0": "var[a, + 4];",         "1": "endif",         "if[ > 5 ]:": [             "use[a];"         ]     },     "elseif[ > 4 ]:": [         "var[a, 2];"     ],     "else:": [         "var[a, 5];"     ],     "1": "endif",     "2": "var[a,5];",     "3": "use[a];", } 

so can iterate through each item , evaluate each expression.

i have following code, doesn't output expected format.

<?php  $formula = "     @var[a, 3];     @if[ (a <= 3) & (a = 3) ]:         @var[a, + 4];         @if[ > 5 ]:             @use[a];         @endif     @elseif[ > 4 ]:         @var[a, 2];     @else:         @var[a, 5];     @endif     @var[a,5];     @use[a]; ";  $formulas = explode( "@", $formula ); $result = parse( $formulas );  echo json_encode( $result ); function parse( $lines  ){     $exec_tree = array();     foreach( $lines $i => $block ){         unset( $lines[$i] );         $block = trim( str_replace( array(" ") , "" , preg_replace('/\s\s+/', ' ', $block) ) );         if( trim( $block ) != "" ){              // match variable assignments             if( preg_match('/var\[(.*)\]\;?/', $block ) ){                 $exec_tree[] = $block;                         }                // match use statements             if( preg_match('/use\[(.*)\]\;?/', $block ) ){                 $exec_tree[] = $block;             }                   // match ifs             if( preg_match('/^if\[(.*)\]\:/', $block ) ){                 $exec_tree[$block] = parse( $lines );             }                     // match elseifs             if( preg_match('/^elseif\[(.*)\]\:/', $block ) ){                 $exec_tree[$block] = parse( $lines );             }                 // match elses             if( preg_match('/^else:/', $block ) ){                 $exec_tree[$block] = parse( $lines );             }                   // match endifs             if( preg_match('/^endif/', $block ) ){                 break;             }         }     }     return $exec_tree; } 

the code recursive in nature, think missing termination of recursion. it's supposed end on endif keywords. can point me right direction appreciated.

this output now: (json formatted)

[ "var[a,3];", [     "if[(a<=3)&(a=3)]:",     [         "var[a,a+4];",         [             "if[a>5]:",             [                 "use[a];"             ]         ],         "use[a];"     ] ], "var[a,a+4];", [     "if[a>5]:",     [         "use[a];"     ] ], "use[a];" 

]

thanks,

jan

admittedly not entirely clean solution, working , easy refactor:

<?php  $formula = "     @var[a, 3];     @if[ (a <= 3) & (a = 3) ]:         @var[a, + 4];         @if[ > 5 ]:             @use[a];         @endif     @elseif[ > 4 ]:         @var[a, 2];     @else:         @var[a, 5];     @endif     @var[a,5];     @use[a]; ";  $formulas = explode( "@", $formula ); $rec = false; $result   = parse( $formulas, $rec );  echo json_encode( $result, json_pretty_print );  function parse( &$lines, &$rec ) {     $exec_tree = array();     while ( (bool) $lines === true ) {         $block = array_shift( $lines );          $block = trim( str_replace( array( " " ), "", preg_replace( '/\s\s+/', ' ', $block ) ) );         if ( trim( $block ) != "" ) {              // match variable assignments             if ( preg_match( '/var\[(.*)\]\;?/', $block ) ) {                 $exec_tree[] = $block;             } elseif ( preg_match( '/use\[(.*)\]\;?/', $block ) ) {                 $exec_tree[] = $block;             } elseif ( preg_match( '/^if\[(.*)\]\:/', $block ) ) {                 $rec = true;                 $exec_tree[ $block ] = parse( $lines, $rec );             } elseif ( preg_match( '/^elseif\[(.*)\]\:/', $block ) ) {                 $rec = !$rec;                 if ( $rec === false ) {                     array_unshift( $lines, $block );                     break;                 } else {                     $exec_tree[ $block ] = parse( $lines, $rec );                 }             } elseif ( preg_match( '/^else:/', $block ) ) {                 $rec = !$rec;                 if ( $rec === false ) {                     array_unshift( $lines, $block );                     break;                 } else {                     $exec_tree[ $block ] = parse( $lines, $rec );                 }             } elseif ( preg_match( '/^endif/', $block ) ) {                 $rec = !$rec;                 if ( $rec === false ) {                     array_unshift( $lines, $block );                     break;                 } else {                     $exec_tree[] = $block;                 }             }         }     }      return $exec_tree; } 

returns

{     "0": "var[a,3];",     "if[(a<=3)&(a=3)]:": {         "0": "var[a,a+4];",         "if[a>5]:": [             "use[a];"         ],         "1": "endif"     },     "elseif[a>4]:": [         "var[a,2];"     ],     "else:": [         "var[a,5];"     ],     "1": "endif",     "2": "var[a,5];",     "3": "use[a];" } 

the trick somehow keep track of whether or not you're in block , break out on else,elseif , endif, though still appending values end result.


Comments

Popular posts from this blog

javascript - Slick Slider width recalculation -

jsf - PrimeFaces Datatable - What is f:facet actually doing? -

angular2 services - Angular 2 RC 4 Http post not firing -