본문 바로가기

Coding Note

[Design pattern] Interpreter

Interpreter pattern : interpreter 구현 구조를 OOP에 맞게 표현한 형태이다. 주로 특화된 언어나 프로토콜등 규칙에 따라 해석되는 언어의 해석기(interpreter)를 구조화 할 때 사용된다.


언어를 해석할때는 BNF(Backus Naur Form) 형태로 나타내는 경우가 많다. 대부분의 언어 구조가 이 형태로 표현할 수 있기 때문인데, 그렇기 때문에 Interpreter pattern도 BNF 구조의 언어를 해석하기에 알맞은 해석기를 표현할 수 있게끔 디자인되었다.


BNF에서 Terminal expression 과 Non-Terminal expression이 존재한다. 그리고 하나의 문장은 BNF구조의 최상위 루트의 expression을 나타낸다. Interpreter pattern은 이 구조에 맞게 Expression을 나타내는 인터페이스와 이를 상속하여 말단표현을 나타내거나 비말단 표현을 나타내는 클래스를 파생한다. 이런 구조때문에 Interpreter pattern은 Composite pattern을 모방한다고 볼 수 있다.




위와 같은 구조를 가지며(Composite pattern과 똑같다.) 클라이언트는 상위 추상클래스(혹은 인터페이스)를 통하여 Context를 해석할 수 있다. 일반적으로 Interpreter pattern에서는 parser를 정의하지 않지만, 필요에 디자인 구조에 포함하기도 한다.


영어의 문장 형식을 다음과 같이 BNF로 표현했을 때,


<sentence> ::= <fmt_1> | <fmt_2> | <fmt_3> | <fmt_4> | <fmt_5>

<fmt_1> ::= <subject> <verb> | <subject> <verb> <predicate>

<fmt_2> ::= <subject> <verb> <subjective_complement> | <subject> <verb> <subjective_complement> <predicate>

...

<subject> ::= <noun> | <supine> | <gerund> | <that_clause> | <what_clause> | ...  //(definite articles)

<that_clause> ::= that <subject> <verb>

<what_clause> ::= what <verb> | what <subject> <verb>

...


모두 표현하자면 끝도 없으니, 적당히 끊고. 이를 Interpreter pattern을 적용하여 해석기 모델을 설계해 보았다. 구조를 익히기 위한 예제라 별 의미는 없지만, 패턴이 어떤식으로 적용되는지는 볼 수 있을것이다.


public abstract class Expression {

protected String rawString;

public abstract String interpret(Dictionary dic);

}


public class Dictionary {

public class Voca{

public String name;

public Class<?> type;

}

private Map<String, Voca> dictionary;


public Dictionary(){

dictionary = new HashMap<String, Voca>();

}


public String findMeaning(String key){

return dictionary.get(key).name;

}


public Class<?> checkType(String key){

return dictionary.get(key).type;

}

}


public class Sentence extends Expression {

private Expression root;


public Sentence(String sentence){

rawString = sentence;

}


private void parse(Dictionary dic){

// ...

}


@Override

public String interpret(Dictionary dic) {

parse(dic);


return root.interpret(dic);

}

}


public class Format1Sentence extends Expression {

private Expression subject;

private Expression verb;

private Expression predicate;


public Format1Sentence(Expression subject, Expression verb, Expression predicate){

this.subject = subject;

this.verb = verb;

this.predicate = predicate;

}


@Override

public String interpret(Dictionary dic) {

if(predicate != null)

return subject.interpret(dic) + verb.interpret(dic) + predicate.interpret(dic);

else

return subject.interpret(dic) + verb.interpret(dic);

}

}


public class Subject extends Expression {

private Expression definiteArticle; //정관사


public Subject(Expression definiteArticle){

this.definiteArticle = definiteArticle;

}


@Override

public String interpret(Dictionary dic) {

return definiteArticle.interpret(dic);

}

}


public class Noun extends Expression {

public Noun(String noun){
rawString = noun;
}

@Override
public String interpret(Dictionary dic) {
return dic.findMeaning(rawString);
}
}

Dictionary에 의미있는 정보가 담겨있다면, Sentence 에 대해 interpret(..)를 호출했을 때, 그 문장에 대한 의미를 해석할 수 있게 바꿀 수 있을것이다. 한글 뜻을 담고 각 요소마다의 해석순서(어법)에 변화를 준다면 초급수준의 번역기를 구현할 수 있지 않을까?

한줄요약 : 거의 쓸일이없다는게 함정. 굳이 따로 패턴이라고 때어논 의도르 모르겠다.

'Coding Note' 카테고리의 다른 글

[Design pattern] Memento  (0) 2013.03.26
[Design pattern] Mediator  (0) 2013.03.25
[Design pattern] Proxy  (1) 2013.03.07
[Design pattern] Flyweight  (3) 2013.03.05
[Design pattern] Facade  (0) 2013.03.04