我想将算术表达式拆分为标记,将其转换为RPN。
Java有StringTokenizer,它可以选择保留分隔符。这样,我可以使用运算符作为分隔符。不幸的是,我需要在PHP中执行此操作,它具有strtok,但是会抛弃分隔符,因此我需要自己酿造一些东西。
这听起来像编译器设计101的经典教科书示例,但我担心我在这里缺少一些正规教育。您可以指点我的标准算法吗?
我的其他选择是阅读Lexical Analysis或使用可用的字符串函数快速和脏乱。
答案 0 :(得分:2)
这可能会有所帮助。
答案 1 :(得分:1)
通常,我会使用正则表达式来执行此操作:
$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)。
答案 2 :(得分:0)
好的,多亏了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;
}