0

ビューでクリーンでシンプルな構文を使用できるように、PHP で疑似変数パーサーを構築しており、if ステートメント用のエンジンを実装しています。ここで、ネストされた if ステートメントを使用できるようにしたいと考えています。私が考えた最も単純で最も洗練された解決策は、identation をブロックのマーカーとして使用することでした。

したがって、これは基本的に私がビューで探しているレイアウトです:

{if x is empty}
    {if y is array}
        Hello World
    {endif}
{endif}

スクリプトは最初の if 文を見つけて、同じ深さの endif と一致させます。true と評価された場合、内側のブロックも解析されます。

現在、次のコードで深さを使用する正規表現の設定に問題があります。

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?){endif}|s', $template, $match);

基本的に、ある種の変数を使用する([\t ]?)前に の最初の一致を配置し、 と同じ深さで一致がない場合、ステートメントが完了しないようにします。{endif}{endif}{if ...}

完成させるのを手伝ってくれませんか?

4

3 に答える 3

2

定義した言語は規則的ではないため、通常、この問題に正規表現を使用することはできません ( と の出現をカウントする必要があるため{if}) {endif}

あなたが持っているのは、古典的な対応する括弧の問題の変種です。

およびの発生を追跡するには、ある種の有限状態マシンを使用する方がよいでしょう。{if}{endif}

于 2009-11-17T11:42:50.697 に答える
0

\1 には最初の一致が含まれるため、次のようにすることができます。

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?)\1{endif}|s', $template, $match);

ただし、これは必ずしも {endif} の正しい発生と一致するとは限りません。正しい数のタブが前にある次の発生のみと一致します。

于 2009-11-17T11:45:55.397 に答える
0

明示的な「endif」ステートメントを使用している場合、ブロックは既に閉じられており、特別なインデントを行う必要はなく、「/{if.+?}(.+?){endif}/」と一致するだけです。1一方、Python に似たインデント ブロックを使用する場合は、{endif} (およびブラケット) を削除して、インデント レベルのみに一致させることができます。

  if condition
      this line is in the if block
      this one too
  this one not

あなたの表現はこのようになります

 /([\t]+)if(.+)\n((\1[\t]+.+\n)+)/

「条件」は一致 2 で、ステートメント本体は一致 3 です。

1実際には、これは/{if}((.(?!{if))+?){endif}/sネストされたifを適切に処理するようなものでなければなりません。

于 2009-11-17T11:59:10.677 に答える