Design pattern/행동 패턴

[디자인 패턴] 24장 인터프리터 패턴

미스터로즈 2021. 6. 19. 16:30

공부하기 위해서 요약정리해놓은 것입니다..

 

정확하고 꼼꼼한 자료는 쉽게 배워 바로 써먹는 디자인 패턴을 확인하시고

코드는 github.com/infohojin/patterns 을 참고해 주세요.

 

인터프리터 패턴은 간단한 언어적 문법을 표현하는 패턴입니다.

 

언어

이 세상에는 수많은 언어가 존재합니다. 컴퓨터는 0 과 1로 동작하는 시스템이지만, 실제 컴퓨터를 사용할 때는 추상화된 고급 언어로 코드를 작성합니다.

 

컴퓨터는 0과 1로 동작하는데 이를 기계어라고 합니다. 사람이 기계오로 프로그램을 작성하는 것은 어려우므로, 보다 쉽게 작성하기 위해 어셈블리와 같은 언어가 만들어졌습니다.

 

어셈블리어는 한 줄의 기계어에 한 줄의 명령어가 대응하는 구조입니다. 이를 저수준 언어라고 하거나, 기계어와 고급 언어 사이에 있어서 중간 언어라고 부르기도 합니다.

 

고급 언어를 사용하면 시스템 특성에 구속받지 않고 일반 사람도 프로그램을 작성할 수 있습니다. 대표적으로 C언어가 있습니다.

고급언어의 장점은 기계어나 어셈블리어보다 편리하게 동작을 이해하고 코드를 작성할 수 있다는 점입니다.

 

언어 설계

해석자 패턴은 간단한 미니 언어를 구현하는 패턴입니다. 간단한 언어의 문법을 정의하고 그 언어의 문장을 해석하는 방법을 구현합니다.

 

언어 설계의 첫 단추는 규칙을 작성하는 것입니다. 언어 규칙을 명백하게 표현해야 하므로 표기법을 작성합니다.

 

언어 문법을 표기하는 방법은 크게 두 종류입니다.

- 구문 도표 표기법 : 그림으로 표현

- 배커스 - 나우르 표기법 : 문자로 표현

 

BNF 표기법은 프로그래밍 언어를 정의할 때 사용하는 메타 표기법입니다. 문법을 수학적인 수식으로 표기할 때 많이 이용합니다.

정규화 표현을 처리하는 경우에도 많이 사용되며, 정규 표현 식은 패턴을 정의 하는데 사용됩니다.

 

해석자 패턴은 문장의 어휘를 해석하고 처리하기 위해 5가지 구성 요소를 갖고 있습니다.

- 추상 구문 트리 인터페이스

- 종료 기호

- 비종료 기호

- 해석기 정보

- 문장을 나타내는 추상 구문 트리

 

처리계

새로운 언어 모델을 BNF 표기법으로 설계했다면, 실제 해석하고 처리할 구현부를 작성해야 합니다.

해석자의 처리계는 크게 어휘 분석과 구문 분석으로 나뉩니다.

 

어휘 분석은 문장의 텍스트를 토큰으로 분리하는 작업입니다. 토큰은 문자열에서 각각의 의미와 위치를 구별하며, 어휘 분석에서 의미 있는 식별자를 구별합니다.

 

해석하기 위해서는 먼저 토큰 분리가 필요합니다.

연산식의 언어는 시작 식별자 안에 존재하며, 어휘는 각각의 공백으로 구분돼 있습니다.

토큰은 어휘에서 키워드, 식별자, 상수, 리터럴, 연산자 등을 구별하며 해석 처리를 위한 단위를 분리합니다.

 

토큰으로 분리된 1차원 배열은 구분 분석 단계를 통해 구문 트리를 작성합니다.

구문 트리는 하나의 자료 구조 입니다.

 

구문 트리는 이진 트리 구조이며, 구문 분석으로 생성된 트리 자료는 메모리에 저장됩니다.

 

처리계의 어휘 분석과 구문 분석은 상호 관계를 갖고 있습니다. 언어 처리는 보통 형태로 반복하면서 해석 처리를 수행합니다.

 

 

이때 구문 분석은 문장 해석 -> 표현식 해석을 주로 담당하고, 어휘 분석은 다음 토큰 읽기를 담당합니다.

 

해석자 패턴의 Context 클래스는 표현된 어휘를 해석하기 위한 정보를 포괄적으로 갖고 있습니다.

Context 클래스는 문자열로 표현된 어휘 문장의 구문을 해석하고 토큰의 전후 관계를 표시합니다.

 

<?php

class Context
{
    private $token;

    public function __construct($text)
    {
        $this->token = explode(" ",$text);
        echo "토큰분리\n";
        print_r($this->token);
    }

    // 시작기호 판별
    public function isStart()
    {
        if(current($this->token) == "{{") {
            next($this->token);
            return true;
        } else {
            return false;
        }
    }

    public function next()
    {
        $token = current($this->token);
        next($this->token);
        return $token;
    }
}

 

Context 클래스는 해석자에게 보내는 토큰 정보이며, 구분 해석을 위한 메서드를 제공합니다.

 

중간코드

언어를 해석해서 처리하는 컴파일러, 인터프리터와 같은 언어는 해석을 처리하는 여러 단계의 패스를 갖고 있습니다.

 

언어의 해석과 동작은 한 번에 처리할 수 없습니다. 패스는 해석과 수행을 처리하기 위한 중간 단계 과정입니다.

 

해석자는 구문 분석된 어휘를 처리하기 위해 중간 코드를 생성합니다.