Php 递归解析预格式化公式到数组
我正在尝试创建一个公式解析器,而我目前正在研究如何将代码递归地转换为表达式数组。以下面的公式为例:Php 递归解析预格式化公式到数组,php,recursion,Php,Recursion,我正在尝试创建一个公式解析器,而我目前正在研究如何将代码递归地转换为表达式数组。以下面的公式为例: $formula = " @VAR[a, 3]; @IF[ (a <= 3) & (a = 3) ]: @VAR[a, a + 4]; @IF[ a > 5 ]: @USE[a]; @ENDIF @ELSEIF[ a > 4 ]: @VAR[a, 2];
$formula = "
@VAR[a, 3];
@IF[ (a <= 3) & (a = 3) ]:
@VAR[a, a + 4];
@IF[ a > 5 ]:
@USE[a];
@ENDIF
@ELSEIF[ a > 4 ]:
@VAR[a, 2];
@ELSE:
@VAR[a, 5];
@ENDIF
@VAR[a,5];
@USE[a];
";
$formula=”
@VAR[a,3];
@如果[(a)5]:
@使用[a];
@恩迪夫
@其他[a>4]:
@VAR[a,2];
@其他:
@VAR[a,5];
@恩迪夫
@VAR[a,5];
@使用[a];
";
应输出:
{
"0": "VAR[a, 3];",
"IF[ (a <= 3) & (a = 3) ]:": {
"0": "VAR[a, a + 4];",
"1": "ENDIF",
"IF[ a > 5 ]:": [
"USE[a];"
]
},
"ELSEIF[ a > 4 ]:": [
"VAR[a, 2];"
],
"ELSE:": [
"VAR[a, 5];"
],
"1": "ENDIF",
"2": "VAR[a,5];",
"3": "USE[a];",
}
{
“0”:“变量[a,3];”,
“如果[(a 5)]:”:[
“使用[a];”
]
},
“ELSEIF[a>4]:”:[
“变量[a,2];”
],
“否则:”:[
“变量[a,5];”
],
“1”:“ENDIF”,
“2”:“VAR[a,5];”,
“3”:“使用[a];”,
}
这样我就可以遍历每个项并计算每个表达式
我目前有以下代码,它没有输出预期的格式
不可否认,这不是一个完全干净的解决方案,但可以工作且易于重构:
<?php
$formula = "
@VAR[a, 3];
@IF[ (a <= 3) & (a = 3) ]:
@VAR[a, a + 4];
@IF[ a > 5 ]:
@USE[a];
@ENDIF
@ELSEIF[ a > 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;
}
我只想澄清一下,&$rec有什么用?噢,这是一个递归标志,用于监视是否已到达最后一个案例。
<?php
$formula = "
@VAR[a, 3];
@IF[ (a <= 3) & (a = 3) ]:
@VAR[a, a + 4];
@IF[ a > 5 ]:
@USE[a];
@ENDIF
@ELSEIF[ a > 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;
}
{
"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];"
}