2020년 7월 7일 화요일

GOF Design Pattern - Interpreter






설명


어떤 언어를 구현하기 위해 사용되는 패턴 중에 하나이다.

AbstractExpression 클래스를 상속받는 클래스들로 언어를 구성한다.

TerminalExpression 은 논리상수가 해당되고, NonterminalExpression 은 변수 등이 해당된다.


Expression 의 메소드의 재귀적인 호출로 전체문장을 해석하게 된다.


문제는 정의할 문법이 간단할 때만 적용이 가능하단 점이고,

raw expression 을 위의 클래스의 재귀적 트리로 만드는 건 이 패턴의 역할이 아닌 점이다.





예제 코드



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Context
{
public:
    bool Lookup(std::string_view s) const;
    void Assign(class VariableExp* exp, bool b);
 
private:
    std::map<std::stringbool> _dict;
};
 
class BooleanExp
{
public:
    BooleanExp() = default;
    virtual ~BooleanExp() = default;
 
    virtual bool Evaluate(Context&= 0;
};
 
class VariableExp : public BooleanExp
{
public:
    VariableExp(std::string_view name) { _name = name; }
    virtual ~VariableExp() = default;
 
    virtual bool Evaluate(Context& c) { return c.Lookup(_name); }
 
    std::string_view GetName() { return _name; }
private:
    std::string _name;
};
 
class AndExp : public BooleanExp
{
public:
    AndExp(BooleanExp* op1, BooleanExp* op2) : _operand1(op1) , _operand2(op2) {}
    virtual ~AndExp() = default;
 
    virtual bool Evaluate(Context& c) { return _operand1->Evaluate(c) && _operand2->Evaluate(c); }
 
private:
    BooleanExp* _operand1;
    BooleanExp* _operand2;
};
 
class OrExp : public BooleanExp
{
public:
    OrExp(BooleanExp* op1, BooleanExp* op2) : _operand1(op1), _operand2(op2) {}
    virtual ~OrExp() = default;
 
    virtual bool Evaluate(Context& c) { return _operand1->Evaluate(c) || _operand2->Evaluate(c); }
 
private:
    BooleanExp* _operand1;
    BooleanExp* _operand2;
};
 
 
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void main()
{
    BooleanExp* expression;
    Context context;
 
    VariableExp* x = new VariableExp("X");
    VariableExp* y = new VariableExp("Y");
 
    // (X && X) || (X && Y)
    expression = new OrExp(new AndExp(x, x), new AndExp(y, x));
 
    context.Assign(x, true);
    context.Assign(y, false);
 
    bool result = expression->Evaluate(context);
    std::cout << (result ? "true" : "false"<< std::endl;
}
cs


위는 Boolean 문법을 해체해서 결과를 얻는 함수이다.

복잡해보이지만 main 함수를 위주로 보면 쉽게 이해할 수 있다.


Context 는 변항의 논리값을 지정하기 위한 Dictionary 이고, Assign 함수를 메인에서 호출해서 기록해둔다.

전체 Expression 은 Terminal Expression 인 OrExp, AndExp 과 변항을 나타내는 VarialbeExp 로 재귀적으로 구성된다.

이를 Evaluate 함수를 호출하면 마찬가지로 재귀적으로 결과값을 계산하여 값을 도출한다.





추가 설명

 
 사실상 Composite 패턴의 특수한 경우임.

 Terminal Expression 은 FlyWeight 를 통해서 구현할 수도 있음.




댓글 없음:

댓글 쓰기

List