2008-09-29 58 views
2

我想將算術表達式拆分爲標記,將其轉換爲RPN。標記字符串的標準算法,保留分隔符(在PHP中)

Java有StringTokenizer,它可以選擇保留分隔符。這樣,我可以使用運營商作爲分隔符。不幸的是,我需要在PHP中這樣做,它具有strtok,但是拋棄了分隔符,所以我需要自己醞釀一些東西。

這聽起來像是編譯器設計101的經典教科書示例,但恐怕我在這裏缺乏一些正式的教育。有沒有一種標準的算法可以指向我?

我的其他選項是在Lexical Analysis上閱讀或使用可用的字符串函數彙總快速和髒東西。

回答

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)。

+0

嘿,謝謝!我忽略了PREG_SPLIT_DELIM_CAPTURE,現在很簡單。 – 2008-09-29 12:09:51

2

這可能有幫助。

Practical Uses of Tokenizer

+0

標記生成器是好的,但它的某些方面的方式有:a)您必須包裝串入「」 b)您必須重新格式化令牌和除冰劑/陣列重新編碼令牌類型,如果您沒有碰巧使用與PHP相同的格式。 – 2008-09-29 13:42:49

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; 
} 
相關問題