《GOF设计模式》—解释器 (INTERPRETER)—Delphi源码示例:对布尔表达式进行操作和求值

示例:对布尔表达式进行操作和求值
说明:
(1)、文法
     在这个语言中终结符是布尔变量,即常量true和false。"非终结符表示"包含运算符and,or和not的布尔表达式。
BooleanExp ::= VariableExp | Constant | OrExp | AndExp | NotExp | '(' BooleanExp ')'
AndExp ::= BooleanExp 'and' BooleanExp
OrExp ::= BooleanExp 'or' BooleanExp
NotExp ::= 'not' BooleanExp
Constant ::= 'true' | 'false'
VariableExp ::= 'A' | 'B' | 'C' | ……  | 'X' | 'Y' | 'Z'

(2)、表示
     BooleanExp类为所有定义一个布尔表达式的类定义了一个接口。
     VariableExp表示一个有名变量。
     Constant类表示布尔常量。
     AndExp表示由两个布尔表达式"与"操作得到的表达式。
     OrExp表示由两个布尔表达式"或"操作得到的表达式。
     NotExp表示由一个布尔表达式"求反"操作得到的表达式。

(3)、解释器
     这里我们定义布尔表达式上的两个操作。第一个操作是求值(evaluate),即在一个上下文中求一个布尔表达式的值,当然,该上下文必须为每个变量都赋以一个"真"或"假"的布尔值。第二个操作是替换(replace),即用一个表达式来替换一个变量以产生一个新的布尔表达式。替换操作说明了解释器模式不仅可以用于求表达式的值,而且还可用作其它用途。在这个例子中,它就被用来对表达式本身进行操作。

(4)、句子
(true and x) or (y and (not x))

代码:
 clip_image002
unit uBooleanExpression;

interface

type
    TBoolArray = array[0..25] of Boolean;

    TContext = class;

    {布尔表达式}
    TBooleanExp = class
    public
        constructor Create;
        destructor Destroy; override;
        //---
        {求值}
        function Evaluate(AContext: TContext): Boolean; virtual; abstract;
        {替换}
        function Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp; virtual; abstract;
        function Copy(): TBooleanExp; virtual; abstract;
    end;
    {变量表达式}
    TVariableExp = class(TBooleanExp)
    private
        FName: Char;
    public
        constructor Create(const AName: Char);
        //--
        function Evaluate(AContext: TContext): Boolean; override;
        function Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp; override;
        function Copy: TBooleanExp; override;
        //---
        property Name: Char read FName;
    end;
    {与运算}
    TAndExp = class(TBooleanExp)
    private
        FOperand1: TBooleanExp;
        FOperand2: TBooleanExp;
    public
        constructor Create(op1,op2: TBooleanExp);
        //---
        function Evaluate(AContext: TContext): Boolean; override;
        function Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp; override;
        function Copy(): TBooleanExp; override;
    end;
    {求反运算}
    TNotExp = class(TBooleanExp)
    private
        FOperand: TBooleanExp;
    public
        constructor Create(op: TBooleanExp);
        //---
        function Evaluate(AContext: TContext): Boolean; override;
        function Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp; override;
        function Copy(): TBooleanExp; override;
    end;
    {或运算}
    TOrExp = class(TBooleanExp)
    private
        FOperand1: TBooleanExp;
        FOperand2: TBooleanExp;
    public
        constructor Create(op1,op2: TBooleanExp);
        function Evaluate(AContext: TContext): Boolean; override;
        function Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp; override;
        function Copy(): TBooleanExp; override;
    end;
    {常量}
    TConstantExp = class(TBooleanExp)
    private
        FValue: Boolean;
    public
        constructor Create(const AValue: Boolean);
        //---
        function Evaluate(AContext: TContext): Boolean; override;
        function Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp; override;
        function Copy(): TBooleanExp; override;
    end;
    
    TContext = class
    private
        FVariables: TBoolArray;
    public
        function Lookup(const AName: Char): Boolean;
        procedure Assign(const AVariable: TVariableExp; const Value: Boolean);
    end;

implementation

uses
    Contnrs;

var
    FTempExps: TObjectList;

function TContext.Lookup(const AName: Char): Boolean;
begin
    Result := FVariables[ord(AName) - ord('A')];
end;

procedure TContext.Assign(const AVariable: TVariableExp; const Value: Boolean);
begin
    FVariables[Ord(AVariable.Name) - ord('A')] := Value;
end;

constructor TVariableExp.Create(const AName: Char);
begin
    inherited Create;
    //---
    FName := AName;
end;

function TVariableExp.Evaluate(AContext: TContext): Boolean;
begin
    Result := AContext.Lookup(FName);
end;

function TVariableExp.Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp;
begin
    if AName = FName then
        Result := AExpression.Copy()
    else
        Result := TVariableExp.Create(FName);
end;

function TVariableExp.Copy: TBooleanExp;
begin
    Result := TVariableExp.Create(FName);
end;

constructor TAndExp.Create(op1,op2: TBooleanExp);
begin
    inherited Create;
    //---
    FOperand1 := op1;
    FOperand2 := op2;
end;

function TAndExp.Evaluate(AContext: TContext): Boolean;
begin
    Result := (FOperand1.Evaluate(AContext) and (FOperand2.Evaluate(AContext)));
end;

function TAndExp.Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp;
begin
    result := TAndExp.Create(FOperand1.Replace(AName,AExpression),FOperand2.Replace(AName,AExpression));
end;

function TAndExp.Copy(): TBooleanExp;
begin
    Result := TAndExp.Create(FOperand1.Copy(),FOperand2.Copy());
end;

constructor TNotExp.Create(op: TBooleanExp);
begin
    inherited Create;
    //---
    FOperand := op;
end;

function TNotExp.Evaluate(AContext: TContext): Boolean;
begin
    result := not FOperand.Evaluate(AContext);
end;

function TNotExp.Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp;
begin
    result := TNotExp.Create(FOperand.Replace(AName,AExpression));
end;

function TNotExp.Copy(): TBooleanExp;
begin
    result := TNotExp.Create(FOperand.Copy());
end;

constructor TOrExp.Create(op1,op2: TBooleanExp);
begin
    inherited Create;
    //---
    FOperand1 := op1;
    FOperand2 := op2;
end;

function TOrExp.Evaluate(AContext: TContext): Boolean;
begin
    result := FOperand1.Evaluate(AContext) or FOperand2.Evaluate(AContext);
end;

function TOrExp.Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp;
begin
    result := TOrExp.Create(FOperand1.Replace(AName,AExpression),FOperand2.Replace(AName,AExpression));
end;

function TOrExp.Copy(): TBooleanExp;
begin
    result := TOrExp.Create(FOperand1.Copy(),FOperand2.Copy());
end;

constructor TConstantExp.Create(const AValue: Boolean);
begin
    inherited Create;
    //---
    FValue := AValue;
end;

function TConstantExp.Evaluate(AContext: TContext): Boolean;
begin
    Result := FValue;
end;

function TConstantExp.Replace(const AName: Char; AExpression: TBooleanExp): TBooleanExp;
begin
    Result := TConstantExp.Create(FValue);
end;

function TConstantExp.Copy(): TBooleanExp;
begin
    Result := TConstantExp.Create(FValue);
end;

constructor TBooleanExp.Create;
begin
    FTempExps.Add(self);
end;

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

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

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

end.

procedure TForm1.Button3Click(Sender: TObject);
{
布尔表达式"(true and x) or (y and (not x))"
,并对给定的以true或false赋值的x和y求这个表达式值。
}
var
    AExpression: TBooleanExp;
    AContext: TContext;
    x,y: TVariableExp;
    AResult: Boolean;
begin
    AContext := TContext.Create;
    //---
    x := TVariableExp.Create('X');
    y := TVariableExp.Create('Y');
    //---
    AExpression := TOrExp.Create(
        TAndExp.Create(TConstantExp.Create(true),x),
        TAndExp.Create(y,TNotExp.Create(x)));
    //---
    AContext.Assign(x,false);
    AContext.Assign(y,true);
    //---
    AResult := AExpression.Evaluate(AContext);
    if AResult then
        ShowMessage('true')
    else
        ShowMessage('false');
    //---
    AExpression.Free;
    AContext.Free;
end;

procedure TForm1.Button4Click(Sender: TObject);
{
计算布尔表达式"(true and x) or (y and (not x))"}
var
    AExpression: TBooleanExp;
    AContext: TContext;
    //---
    procedure Test1;
    {对给定的以true或false赋值的x和y求这个表达式值。}
    var
        x,y: TVariableExp;
        AResult: Boolean;
    begin
        x := TVariableExp.Create('X');
        y := TVariableExp.Create('Y');
        //---
        AExpression := TOrExp.Create(
            TAndExp.Create(TConstantExp.Create(true),x),
            TAndExp.Create(y,TNotExp.Create(x)));
        //---
        AContext.Assign(x,false);
        AContext.Assign(y,true);
        //---
        AResult := AExpression.Evaluate(AContext);
        if AResult then
            ShowMessage('true')
        else
            ShowMessage('false');
    end;
    //---
    procedure Test2;
    {用一个新的表达式替换变量y,并重新求值。}
    var
        AReplacement: TBooleanExp;
        z: TVariableExp;
        not_z: TNotExp;
        AResult: Boolean;
    begin
        z := TVariableExp.Create('Z');
        not_z := TNotExp.Create(z);
        //---
        AReplacement := AExpression.Replace('Y',not_z);
        //---
        AContext.Assign(z,true);
        //---
        AResult := AReplacement.Evaluate(AContext);
        if AResult then
            ShowMessage('true')
        else
            ShowMessage('false');
    end;
begin
    AContext := TContext.Create;
    //---
    Test1;
    Test2;
    //---
    AExpression.Free;
    AContext.Free;
end;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值