実際に何をやっているかというと

TREBinCodeクラスに、今までなかったIsEqual関数を追加しました。その中にcase文で書いています。

もともとTRECodeの子供なのであって当然です。

今までなかった理由は、TREBinCodeはNFAを作った後は単に破棄していたためです。

構文木を作るためにしか使っていなかったのです。

今考えると何てもったいないことをと思います。

ちなみに、現時点では以下のような感じ。そのままコードを載せて置きます。ちゃんと見えなかったらごめんなさい。

function TREBinCode.IsEqual(var AStr: PWideChar): Boolean;
var
  SaveP, SubP: PWideChar;
  AMatchKind: TRELoopMatchKind;
  I, AMin, AMax: Integer;
begin
  case FOp of
    opEmply:
      Result := True;
    opConcat:
      begin
        SaveP := AStr;
        if FLeft.IsEqual(AStr) and FRight.IsEqual(AStr) then
          Result := True
        else
        begin
          AStr := SaveP;
          Result := False;
        end;
      end;
    opUnion:
      begin
        SaveP := AStr;
        Result := FLeft.IsEqual(AStr);
        if not Result then
        begin
          AStr := SaveP;
          Result := FRight.IsEqual(AStr);
        end;
        if not Result then
        begin
          AStr := SaveP;
          Result := False;
        end;
      end;
    opLoop:
      begin
        Result := False;
        SaveP := AStr;
        AMatchKind := FMatchKind;
        AMin := FMin;
        AMax := FMax;
        // Min一致
        if AMin > 0 then
        begin
          for I := 1 to AMin do
            if not FLeft.IsEqual(AStr) then
              Exit;
          // {n}ならばバックトラックの必要がないので真を返す
          if (AMin = AMax) then
          begin
            Result := True;
            Exit;
          end;
          if (AMatchKind = lmMin) then
          begin
            Result := FRight.IsEqual(AStr);
            if Result then
              Exit;
          end;
          // 最小値が指定されているときは、PrevPを現在位置に設定
          SaveP := AStr;
        end
        else
        begin
          // 最小値が0ならばマッチ成功
          if AMatchKind = lmMin then
          begin
            Result := FRight.IsEqual(AStr);
            if Result then
              Exit;
          end;
        end;
        I := AMin;
        repeat
          if (AMatchKind = lmMin) then
          begin
            Result := FRight.IsEqual(AStr);
            if Result then
              Exit;
          end;
          if not FLeft.IsEqual(AStr) then
            Break;
          Inc(I);
        until (I = AMax);
        if (AMatchKind lmMax) and not FNoBackTrack then
        begin
          Result := FRight.IsEqual(AStr);
          while (not Result) and (AStr > SaveP) do
          begin
            Dec(AStr);
            FRegExp.FMatchData.Back;
            SubP := AStr;
            Result := FRight.IsEqual(AStr);
            if not Result then
              AStr := SubP;
          end;
          if not Result then
            AStr := SaveP;
        end
        else
          Result := True;
      end;
    opLHead:
      ;
    opLTail:
      ;
    opGroup:
      begin
        SaveP := AStr;
        Result := FLeft.IsEqual(AStr);
        if Result then
        begin
          FRegExp.FMatchData.StartP[FGroupIndex] := SaveP;
          FRegExp.FMatchData.EndP[FGroupIndex] := AStr;
        end
        else
          AStr := SaveP;
      end;
    opGroupCall:
      ;
    opAheadMatch:
      begin
        SaveP := AStr;
        Result := FLeft.IsEqual(AStr);
        AStr := SaveP;
      end;
    opAheadNoMatch:
      begin
        SaveP := AStr;
        Result := not FLeft.IsEqual(AStr);
        AStr := SaveP;
      end;
    opBehindMatch:
      ;
    opBehindNoMatch:
      ;
    opNoBackTrack:
      ;
  end;
end;

ループの部分は、TSkREgExp.MatchPrim関数のコードをほぼそのまま持ってきました。

美しいと思いませんか? 0.9.3と比べて。

すいません、今完全にハイになっています。

コメントを残す

メールアドレスが公開されることはありません。