Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/239.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 递归解析预格式化公式到数组_Php_Recursion - Fatal编程技术网

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];"
}