标记字符串的标准算法,保留定界符(在PHP中)
时间:2020-03-06 14:51:59 来源:igfitidea点击:
我想将算术表达式拆分为标记,以将其转换为RPN。
Java具有StringTokenizer,它可以选择保留定界符。这样,我可以将运算符用作分隔符。不幸的是,我需要在具有strtok的PHP中执行此操作,但是这会丢掉定界符,因此我需要自己准备一些东西。
这听起来像是Compiler Design 101的经典教科书示例,但我担心这里缺少一些正规的教育。我们可以为我提供标准算法吗?
我的其他选择是在Lexical Analysis上阅读或者使用可用的字符串函数快速而又肮脏地汇总一些内容。
解决方案
这可能会有所帮助。
分词器的实际用途
通常,我只是使用正则表达式来做到这一点:
$expr = '(5*(7 + 2 * -9.3) - 8 )/ 11'; $tokens = preg_split('/([*\/^+-]+)\s*|([\d.]+)\s*/', $expr, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $tts = print_r($tokens, true); echo "<pre>x=$tts</pre>";
要接受带指数的数字(例如-9.2e-8),还需要做更多的工作。
好的,多亏了PhiLho,我的最终代码是这个,如果有人需要的话。甚至还不是很脏。 :-)
static function rgTokenize($s) { $rg = array(); // remove whitespace $s = preg_replace("/\s+/", '', $s); // split at numbers, identifiers, function names and operators $rg = preg_split('/([*\/^+\(\)-])|(#\d+)|([\d.]+)|(\w+)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); // find right-associative '-' and put it as a sign onto the following number for ($ix = 0, $ixMax = count($rg); $ix < $ixMax; $ix++) { if ('-' == $rg[$ix]) { if (isset($rg[$ix - 1]) && self::fIsOperand($rg[$ix - 1])) { continue; } else if (isset($rg[$ix + 1]) && self::fIsOperand($rg[$ix + 1])) { $rg[$ix + 1] = $rg[$ix].$rg[$ix + 1]; unset($rg[$ix]); } else { throw new Exception("Syntax error: Found right-associative '-' without operand"); } } } $rg = array_values($rg); echo join(" ", $rg)."\n"; return $rg; }