《GOF设计模式》—访问者(VISITOR)—Delphi源码示例:字符串搜索

示例:字符串搜索
代码:

clip_image002 
unit uStringExpression;

interface

uses
    SysUtils, Classes, Contnrs, Dialogs;

type
    TRegularExpression = class;
    TRegularExpressionVisitor = class;

    {文字流}
    TStream1 = class
    private
        FData: string;
        FPosition: Integer;
    public
        constructor Create(AData: string);
        //---
        function Copy: TStream1;
        {读入文字,推进输入流}
        function NextAvailable(ASize: integer): string;
        procedure Next(const AStep: integer = 1);
        function Eof: boolean;
        //---
        property Data: string read FData;
        property Position: Integer read FPosition;
    end;

    {流状态列表}
    TState = class(TObjectList)
    private
        function GetStream(Index: integer): TStream1;
    public
        constructor Create;
        destructor Destroy; override;
        //---
        procedure Add(AStream: TStream1);
        procedure AddAll(AState: TState);
        function Copy: TState;
        //---
        property Stream[Index: integer]: TStream1 read GetStream; default;
    end;

    TNode1 = class
    public
        function asRExp: TRegularExpression; virtual; abstract;
    end;
    TString1 = class(TNode1)
    private
        FLiterals: string;
    public
        constructor Create(const ALiterals: string);
        //---
        function Size: integer;
        function Equal(const ALiterals: string): Boolean;
        //---
        {'&'运算}
        function Sequence(ANode: TNode1): TRegularExpression;
        {'*'运算}
        function Repetition: TRegularExpression;
        {'|'运算}
        function Alternation(ANode: TNode1): TRegularExpression;
        //---
        function asRExp: TRegularExpression; override;
    end;

    {表达式}
    TRegularExpression = class(TNode1)
    public
        function Accept(const AVisitor: TRegularExpressionVisitor): TState; virtual;
            abstract;
        //---
        {'&'运算}
        function Sequence(ANode: TNode1): TRegularExpression;
        {'*'运算}
        function Repetition: TRegularExpression;
        {'|'运算}
        function Alternation(ANode: TNode1): TRegularExpression;
        //---
        function asRExp: TRegularExpression; override;
    end;
    {字符常量}
    TLiteralExpression = class(TRegularExpression)
    private
        FComponents: TString1;
    public
        constructor Create(AComponents: TString1);
        destructor Destroy; override;
        //---
        function Accept(const AVisitor: TRegularExpressionVisitor): TState; override;
        //---
        property Components: TString1 read FComponents;
    end;
    {'|'运算}
    TAlternationExpression = class(TRegularExpression)
    private
        FAlternative1: TRegularExpression;
        FAlternative2: TRegularExpression;
    public
        constructor Create(Alternative1, Alternative2: TRegularExpression);
        destructor Destroy; override;
        //---
        function Accept(const AVisitor: TRegularExpressionVisitor): TState; override;
        //---
        property Alternative1: TRegularExpression read FAlternative1;
        property Alternative2: TRegularExpression read FAlternative2;
    end;
    {'*'运算}
    TRepetitionExpression = class(TRegularExpression)
    private
        FRepetition: TRegularExpression;
    public
        constructor Create(ARepetition: TRegularExpression);
        destructor Destroy; override;
        //---
        function Accept(const AVisitor: TRegularExpressionVisitor): TState; override;
        //---
        property Repetition1: TRegularExpression read FRepetition;
    end;
    {'&'运算}
    TSequenceExpression = class(TRegularExpression)
    private
        FExpression1: TRegularExpression;
        FExpression2: TRegularExpression;
    public
        constructor Create(AExpression1, AExpression2: TRegularExpression);
        destructor Destroy; override;
        //---
        function Accept(const AVisitor: TRegularExpressionVisitor): TState; override;
        //---
        property Expression1: TRegularExpression read FExpression1;
        property Expression2: TRegularExpression read FExpression2;
    end;

    {表达式访问者}
    TRegularExpressionVisitor = class
    public
        function VisitSequence(const ASequenceExp: TSequenceExpression): TState; virtual; abstract;
        function VisitRepeat(const ARepeatExp: TRepetitionExpression): TState; virtual; abstract;
        function VisitAlternation(const AAlternateExp: TAlternationExpression): TState; virtual; abstract;
        function VisitLiteral(const ALiteralExp: TLiteralExpression): TState; virtual;
            abstract;
    end;
    TREMatchingVisitor = class(TRegularExpressionVisitor)
    private
        FInputState: TState;
    public
        constructor Create(AInputState: TState);
        //---
        function VisitAlternation(const AAlternateExp: TAlternationExpression): TState;
            override;
        function VisitLiteral(const ALiteralExp: TLiteralExpression): TState; override;
        function VisitRepeat(const ARepeatExp: TRepetitionExpression): TState;
            override;
        function VisitSequence(const ASequenceExp: TSequenceExpression): TState;
            override;
    end;

procedure Test;
procedure Test2(ALines:TStrings);

implementation

var
    FTempStates: TObjectList;

procedure Test;
{正则表达式: ( ( 'dog' | 'cat' ) repeat & 'weather')  }
var
    AExpression: TRegularExpression;
    AInState, AOutState: TState;
    AVisitor: TREMatchingVisitor;
begin
    AExpression := TString1.Create('dog').Alternation(TString1.Create('cat')).Repetition.Sequence(TString1.Create('weather'));
    try
        AInState := TState.Create;
        try
            AInState.Add(TStream1.Create('dog dog cat weather'));
            //---
            AVisitor := TREMatchingVisitor.Create(AInState);
            try
                AOutState := AExpression.Accept(AVisitor);
                if AOutState.Count > 0 then
                    ShowMessage('字符串匹配')
                else
                    ShowMessage('字符串不匹配');
                AOutState.Free;
            finally
                AVisitor.Free;
            end;
        finally
            AInState.Free;
        end;
    finally
        AExpression.Free;
    end;
end;

procedure Test2(ALines:TStrings);
{正则表达式: ( ( 'dog' | 'cat' ) repeat & 'weather')  }
var
    AExpression: TRegularExpression;
    AInStream: TStream1;
    AStartPosition,AEndPosition: integer;
    //---
    function _FindString(AInStream: TStream1): integer;
    var
        AInState,AOutState: TState;
        AVisitor: TREMatchingVisitor;
    begin
        AInState := TState.Create;
        try
            AInState.Add(AInStream.Copy);
            //---
            AVisitor := TREMatchingVisitor.Create(AInState);
            try
                AOutState := AExpression.Accept(AVisitor);
                if AOutState.Count > 0 then
                    Result := AOutState[0].Position
                else
                    Result := 0;
                AOutState.Free;
            finally
                AVisitor.Free;
            end;
        finally
            AInState.Free;
        end;
    end;
begin
    AExpression := TString1.Create('dog').Alternation(TString1.Create('cat')).Repetition.Sequence(TString1.Create('weather'));
    try
        AInStream := TStream1.Create('12345 dog dog cat weather 12345 cat weather 12345 dog weather cat weather');
        try
            ALines.Clear;
            //---
            with AInStream do
            begin
                while not Eof do
                begin
                    AStartPosition := Position;
                    AEndPosition := _FindString(AInStream);
                    if AEndPosition > 0 then
                    begin
                        ALines.Add(format('起始位置:%.2d  内容:%s', [AStartPosition,System.Copy(Data,AStartPosition,AEndPosition - AStartPosition + 1)]));
                        Next(AEndPosition - AStartPosition + 1);
                    end
                    else
                        Next;
                end;
            end;
        finally
            AInStream.Free;
        end;
    finally
        AExpression.Free;
    end;
end;

function TLiteralExpression.Accept(
    const AVisitor: TRegularExpressionVisitor): TState;
begin
    Result := AVisitor.VisitLiteral(Self);
end;

constructor TLiteralExpression.Create(AComponents: TString1);
begin
    FComponents := AComponents;
end;

destructor TLiteralExpression.Destroy;
begin
    FComponents.Free;
    //---
    inherited;
end;

{ TSequenceExpression }

constructor TSequenceExpression.Create(AExpression1, AExpression2:
    TRegularExpression);
begin
    FExpression1 := AExpression1;
    FExpression2 := AExpression2;
end;

destructor TSequenceExpression.Destroy;
begin
    FExpression1.Free;
    FExpression2.Free;
    //---
    inherited;
end;

function TSequenceExpression.Accept(const AVisitor: TRegularExpressionVisitor):
    TState;
begin
    Result := AVisitor.VisitSequence(Self);
end;

{ TAlternationExpression }

function TAlternationExpression.Accept(
    const AVisitor: TRegularExpressionVisitor): TState;
begin
    Result := AVisitor.VisitAlternation(Self);
end;

constructor TAlternationExpression.Create(Alternative1, Alternative2:
    TRegularExpression);
begin
    FAlternative1 := Alternative1;
    FAlternative2 := Alternative2;
end;

destructor TAlternationExpression.Destroy;
begin
    FAlternative1.Free;
    FAlternative2.Free;
    //---
    inherited;
end;

{ TRepetitionExpression }

function TRepetitionExpression.Accept(
    const AVisitor: TRegularExpressionVisitor): TState;
begin
    Result := AVisitor.VisitRepeat(self);
end;

constructor TRepetitionExpression.Create(ARepetition: TRegularExpression);
begin
    FRepetition := ARepetition;
end;

destructor TRepetitionExpression.Destroy;
begin
    FRepetition.Free;
    //---
    inherited;
end;

constructor TStream1.Create(AData: string);
begin
    FData := AData;
    FPosition := 1;
end;

function TStream1.Copy: TStream1;
begin
    Result := TStream1.Create(FData);
    Result.FPosition := self.FPosition;
end;

function TStream1.NextAvailable(ASize: integer): string;
    //---去掉空白字符
    procedure _SkipBlanks;
    begin
        while FPosition <= Length(FData) do
        begin
            if FData[FPosition] = ' ' then
                inc(FPosition)
            else
                break;
        end;
    end;
begin
    _SkipBlanks;
    //---
    if FPosition + ASize - 1 > Length(FData) then
        Result := ''
    else
    begin
        Result := System.Copy(FData, FPosition, ASize);
        FPosition := FPosition + ASize;
    end;
end;

{ TState }

procedure TState.Add(AStream: TStream1);
begin
    inherited Add(AStream);
end;

procedure TState.AddAll(AState: TState);
var
    i: Integer;
begin
    with AState do
    begin
        for i := 0 to Count - 1 do
            self.Add(Stream[i].Copy);
    end;
end;

function TState.Copy: TState;
begin
    Result := TState.Create;
    Result.AddAll(self);
end;

constructor TState.Create;
begin
    inherited;
    //---
    FTempStates.Add(self);
end;

destructor TState.Destroy;
begin
    if not FTempStates.OwnsObjects then
        FTempStates.Remove(self);
    //---
    inherited;
end;

function TState.GetStream(Index: integer): TStream1;
begin
    Result := TStream1(Items[Index]);
end;

function TRegularExpression.Sequence(ANode: TNode1): TRegularExpression;
begin
    Result := TSequenceExpression.Create(self, ANode.asRExp);
end;

function TRegularExpression.Repetition: TRegularExpression;
begin
    Result := TRepetitionExpression.Create(self);
end;

function TRegularExpression.Alternation(ANode: TNode1): TRegularExpression;
begin
    Result := TAlternationExpression.Create(self, ANode.asRExp);
end;

function TRegularExpression.asRExp: TRegularExpression;
begin
    Result := self;
end;

constructor TString1.Create(const ALiterals: string);
begin
    FLiterals := ALiterals;
end;

function TString1.Alternation(ANode: TNode1): TRegularExpression;
begin
    Result := TAlternationExpression.Create(self.asRExp, ANode.asRExp);
end;

function TString1.asRExp: TRegularExpression;
begin
    Result := TLiteralExpression.Create(self);
end;

function TString1.Size: integer;
begin
    Result := Length(FLiterals);
end;

function TString1.Equal(const ALiterals: string): Boolean;
begin
    Result := FLiterals = ALiterals;
end;

function TString1.Repetition: TRegularExpression;
begin
    Result := TRepetitionExpression.Create(self.asRExp);
end;

function TString1.Sequence(ANode: TNode1): TRegularExpression;
begin
    Result := TSequenceExpression.Create(self.asRExp, ANode.asRExp);
end;

procedure TStream1.Next(const AStep: integer = 1);
begin
    FPosition := FPosition + AStep;
end;

function TStream1.Eof: boolean;
begin
    Result := FPosition > Length(FData);
end;

constructor TREMatchingVisitor.Create(AInputState: TState);
begin
    FInputState := AInputState;
end;

function TREMatchingVisitor.VisitAlternation(const AAlternateExp:
    TAlternationExpression): TState;
var
    AOriginalState, AFinalState: TState;
begin
    AOriginalState := FInputState;
    AFinalState := AAlternateExp.Alternative1.Accept(Self);
    //---
    FInputState := AOriginalState;
    AFinalState.AddAll(AAlternateExp.Alternative2.Accept(Self));
    //---
    Result := AFinalState;
end;

function TREMatchingVisitor.VisitLiteral(const ALiteralExp:
    TLiteralExpression): TState;
var
    AFinalState: TState;
    AStream: TStream1;
    i: Integer;
begin
    AFinalState := TState.Create;
    //---
    with FInputState do
    begin
        for i := 0 to Count - 1 do
        begin
            AStream := Stream[i].Copy;
            if ALiteralExp.Components.Equal(AStream.NextAvailable(ALiteralExp.Components.Size)) then
                AFinalState.Add(AStream)
            else
                AStream.Free;
        end;
    end;
    //---
    Result := AFinalState;
end;

function TREMatchingVisitor.VisitRepeat(const ARepeatExp:
    TRepetitionExpression): TState;
var
    AFinalState: TState;
begin
    AFinalState := FInputState.Copy;
    while FInputState.Count > 0 do
    begin
        FInputState := ARepeatExp.Repetition1.Accept(self);
        AFinalState.AddAll(FInputState);
    end;
    //---
    Result := AFinalState;
end;

function TREMatchingVisitor.VisitSequence(const ASequenceExp:
    TSequenceExpression): TState;
begin
    FInputState := ASequenceExp.Expression1.Accept(self);
    Result := ASequenceExp.Expression2.Accept(self);
end;

initialization
    FTempStates := TObjectList.Create;
    FTempStates.OwnsObjects := false;

finalization
    FTempStates.OwnsObjects := true;
    FTempStates.Free;

end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值