خوارزمية قياسية لترميز سلسلة ما، والاحتفاظ بالمحددات (في PHP)

StackOverflow https://stackoverflow.com/questions/147988

  •  02-07-2019
  •  | 
  •  

سؤال

أريد تقسيم التعبير الحسابي إلى رموز لتحويله إلى RPN.

تحتوي Java على StringTokenizer، والذي يمكنه الاحتفاظ بالمحددات بشكل اختياري.بهذه الطريقة، يمكنني استخدام العوامل كمحددات.لسوء الحظ، أحتاج إلى القيام بذلك في لغة PHP، التي تحتوي على strtok، لكن هذا يؤدي إلى التخلص من المحددات، لذلك أحتاج إلى إعداد شيء ما بنفسي.

يبدو هذا كمثال كتابي كلاسيكي لـ Compiler Design 101، لكن أخشى أنني أفتقر إلى بعض التعليم الرسمي هنا.هل هناك خوارزمية قياسية يمكنك توجيهي إليها؟

خياراتي الأخرى هي القراءة التحليل المعجمي أو لف شيء سريع وقذر باستخدام وظائف السلسلة المتاحة.

هل كانت مفيدة؟

المحلول

كما هو الحال في كثير من الأحيان، أود فقط استخدام تعبير عادي للقيام بذلك:

$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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top