설명
어떤 언어를 구현하기 위해 사용되는 패턴 중에 하나이다.
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::string, bool> _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 를 통해서 구현할 수도 있음.
댓글 없음:
댓글 쓰기