프로그래밍/Compiler

[컴파일러] 1-2. 컴퓨터의 구조

Beginner:) 2024. 2. 10.
320x100

1-2. 컴파일러의 구조

컴파일러를 원시프로그램에서 목표프로그램으로 변환한다고 하였는데, 좀 더 자세히 설명하면 컴파일러는 분석과 통합을 한다는 것이다.

분석(전단부): 원시 프로그램을 구성요소들로 분리하여 그 정보를 심볼 테이블이라는 데이터 구조에 저장하고, 문법적인 구조를 부과한다. 이후 이 구조를 이용하여 원시 프로그램의 중간표현을 생성한다. 이 부분에서 원시프로그램이 구문적으로 잘못 작성 되었거나 의미적으로 불합리하다는 것을 탐지하면 유익한 메시지를 제공하여야 한다.

예를 들어 단어 단위로 끊어서 void는 타입, '='문자는 Assign, ';' 문자는 문장의 끝 등을 알리는 정보이고, 이 정보를 심볼테이블에 저장한다. 또한 타입 뒤에는 이름이 명시되어야 한다는 (int sum) 구조를 부과해야 한다.

 

통합(후단부): 중간표현과 심볼테이블에 있는 정보로부터 바람직한 목표프로그램을 구성한다. 

 

 

 

어휘분석

어휘분석(lexical anaysis) 또는 스캐닝(scanning)이라고 한다. 원시프로그램에서 문자열을 읽어 어휘항목(lexeme)이라 불리는 의미 있는 문자의 나열로 묶는다. 다음 단계 구문분석으로 전달하기 위해 토큰형식으로 출력한다. 토큰에서 첫 번째 요소인 <토큰-이름>은 구문 분석 중에 사용되는 추상기호이고, 두 번째 요소인 속성-값은 토큰을 위한 심볼 테이블에 있는 한 항목을 가리킨다.

아래의 코드를 예로 들어 토큰화를 한다면

position = inital + rate * 60;
<id, 1> <assign,=> <id, 2> <plus, +> <id, 3> <multi, *> <number, 60> <semicolon, ;>

여기서 id는 식별자(identifier)를 의미하며 숫자 1은 심볼테이블을 가르키는 index라 볼 수 있다.

 

구문분석

구분 문석(syntax anaysis) 또는 파싱(parsing)이라 한다. 어휘 분석기에서 생성된 첫 번째 요소를 사용하여 토큰 스트림의 문법 구조를 트리 모양의 중간 표현을 만든다.

 

의미분석

의미 분석기(semantic analyzer)는 구문 트리와 심볼 테이블에 있는 정보를 이용하여 프로그램이 언어 정의에 의미적으로 일치하는지 검사한다. 의미 분석 중 중요한 부분이 타입 검사(type checking)이다. 컴파일러는 연산자가 부합되는 는 피연산자를 갖는지 확인해야 한다. 예를 들어 배열에 인덱스에 부동 소수점이 오면 안 된다.

타입 검사 중에 허용되는 부분이 있을 수도 있다. 예를 들어 부동소수형 변수에 정수를 입력하는 것. C언어에서는 float형 변수에 정수 할당이 가능한데 그냥 할당되는 것이 아니고 정수를 float형으로 변환한 뒤 할당한다. 이를 강제변환(coercion)이라 한다. 위 그림에서는 연산자 *가 부동 소수점 rate와 정수 60을 적용하는데 60을 float으로 강제 변환하는 특별한 노드 inttofloat을 갖는다.

 

중간 코드 생성

컴파일러는 하나 이상의 다양한 형태의 중간표현을 구성하는데, 구문 트리는 중간 표현의 한 가지 형태이다. 중간 코드 생성의 중요한 특성으로는 생산하기 쉬워야 하고 목표 기계어로 번역하기도 쉬워야 한다.

3주소 코드(three-address code)라는 표현으로 예를 들어보자. (3주소 코드는 우변에 한 개의 연산자를 갖는 표현이다) 

position = inital + rate * 60;
t1 = int_to_float(60)
t2 = id3 * t1
t3 = id2 + t2
id1 = t3

 

코드 최적화

중간 코드를 보다 효율 좋게 개선한다. 그러나 대부분 이 작업에서 컴파일러 시간이 늘어난다.

예를 들어 위 예시에서 생성한 중간 코드를 개선하는 방법이다

t1 = int_to_float(60)
t2 = id3 * t1
t3 = id2 + t2
id1 = t3
t1 = id3 * 60.0
id1 = id2 + t1

 

 

코드생성

코드 생성은 원시프로그램의 중간 표현을 입력으로 사용하여 목표언어로 나타낸다. 

LDF R2, id3
MULF R2, R2, #60.0
LDF R1, id2
ADDF R1, R1, R2
STF id1, R1

 

심볼 테이블 관리

컴파일러의 중요한 기능은 원시프로그램에서 사용되는 변수 이름을 저장하고 각 이름의 속성에 관한 정보를 수집하는 것이다. 

 

컴파일러 - 구성 도구

컴파일러 작성자는 언어 편집기, 디버거, 버전 관리자, 프로파일러, 테스트 장비 등과 같은 도구를 포함하고 있는 소프트웨어 개발 환경을 편리하게 사용할 수 있다. 

파서 생성기 언어의 구문적인 서술로부터 구문 분석기를 자동적으로 생성한다.
스캐너 생성기 언어의 토큰의 정규식으로부터 어휘 분석기를 생성한다.
구문지시 번역 엔진 파스 트리를 순회하고 중간 코드를 생성하는 루틴의 집합을 생성
코드-생성기 생성기 중간코드의 각 연산을 목표 기계의 기계어로 변환하는 규칙의 집합으로부터 코드생성기를 생성
데이터흐름 분석 엔진 값들이 프로그램의 한부분에서 각기 다른 부분에 전달되는 방법에 관한 정보를 수집하는 작업을 수월하게 함
컴파일러-구성 도구 키트 컴파일러의 여러 단계를 구성하는 루틴의 통합적인 집합을 제공

 

반응형

댓글