2

算術式をトークンに分割して、RPN に変換したいと考えています。

Java には StringTokenizer があり、オプションで区切り文字を保持できます。そうすれば、演算子を区切り記号として使用できます。残念ながら、strtok を備えた PHP でこれを行う必要がありますが、区切り文字が破棄されるため、自分で何かを作成する必要があります。

これは Compiler Design 101 の古典的な教科書の例のように思えますが、残念ながら、私はここで正式な教育を受けていません。あなたが私に指摘できる標準アルゴリズムはありますか?

私の他のオプションは、字句解析を読むか、利用可能な文字列関数を使って手早く汚いものをまとめることです。

4

3 に答える 3

2

これは役立つかもしれません。

トークナイザーの実際の使用

于 2008-09-29T08:59:59.407 に答える
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など)の数値を受け入れるには、もう少し作業が必要です。

于 2008-09-29T11:01:44.403 に答える
0

OK、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;
}
于 2008-09-29T13:39:22.247 に答える