正则表达式拆分混合表达式

Regex Expression to split mix of mixed expression

我正在尝试将以下表达式拆分到每个数组中,以便我可以使用调车场算法转换为后缀并在稍后进行评估。 这是字符串的一部分。

    $string = '(fld_1010=="t" or fld_1010 != "test") and fld_1012 >= "18"

我正在使用以下模式

$pattern = "/([\(|\s]*)(fld_)([0-9]*)[\s]*(!=|==|>=|<=|=|>|<|like|in)(.*?)([\)|\s]*)( and| or|\z)/";
$found preg_match_all($pattern , $string , $result,PREG_SET_ORDER);

print_r($result);

但我得到了这个输出:

[
    [
        "(fld_1010==\"t\" or",
        "(",
        "fld_",
        "1010",
        "==",
        "\"t\"",
        "",
        " or"
    ],
    [
        " fld_1010 != \"test\") and",
        " ",
        "fld_",
        "1010",
        "!=",
        " \"test\"",
        ")",
        " and"
    ],
    [
        " fld_1012 >= \"18\"",
        " ",
        "fld_",
        "1012",
        ">=",
        " \"18\"",
        "",
        ""
    ]
]

我怎么能像这样拆分字符串?

[
"(",
"fld_1010",
"==",
"t",
"or",
"fld_1010",
"!=",
"test",
")",
"and",
"fld_1012",
">=",
"18"
]

我正在关注这个link,但它只适用于只有数字的数学表达式。

谢谢。

你应该分阶段解决这个问题。第一阶段确实是将输入标记化,但您不应尝试使用此步骤来验证标记的 order 是否有效。只关注单个标记语法,而不关注这些标记出现的 context。所以先不要检查括号是否平衡,或者运算符是否出现在两个操作数之间,...等等

要更改的另一件事是传递给 preg_match_all 的最后一个参数:使用 PREG_PATTERN_ORDER。这样您就可以将所有匹配项放在一个子数组中,并且所有潜在的捕获组都将收集在单独的子数组中。

我会保留一个捕获组来捕获任何不符合任何模式的东西。这将指示语法错误。

以下是您可以这样做的方法:

$string = '(fld_1010=="t" or fld_1010 != "test") and fld_1012 >= "18"';

// This pattern does not verify any order; just the valid tokens.
// The final (\S+) is a "catchall" for errors:
$pattern = '/[!=<>]=|[<>()]|\b(?:like|in|and|or|fld_[0-9]*)\b|"[^"]*"|(\S+)/';
// Use PREG_PATTERN_ORDER here
$found = preg_match_all($pattern , $string , $result, PREG_PATTERN_ORDER);
// Extract the second subarray, as it will have the matches with (\S+):
$errors = array_filter($result[1]);
if ($errors) {
    echo "following tokens are invalid:\n";
    print_r($errors);
}
$result = $result[0]; // just get the matches
print_r($result); // This outputs what you were looking for.

请注意,对于字符串文字,我没有做任何事情来允许双引号成为其中的一部分(带有一些转义字符)。如果您需要这个,您将需要扩展正则表达式来应对。

第二 阶段将验证这些令牌是否以有效顺序出现。我不会尝试使用正则表达式来执行此操作,而是使用 PHP 代码。表达式可能变得非常复杂,有很多嵌套的括号、潜在的函数调用(比如“abs()”)、一元运算符(比如“+”或“not”)和二元运算符、优先规则(例如先乘后加) ,结合性规则(例如从右到左求幂),...等等

另一个实现

仅供参考,我想指出 a Shunting-Yard implementation 我曾经在 JavaScript 中做过,其中所有运算符和函数都是动态定义的。也许这对您的目的来说太过分了,但它可以作为一种灵感。