재귀 하강 파싱

문법 규칙을 그대로 코드로 옮길 수 있을까?

이 편의 문법

식의 문법 세 줄

이 편에서 쓸 식의 문법입니다. 2강에서 본 EBNF로 적었습니다. { }는 그 안이 0번 이상 되풀이된다는 뜻이고, | 는 '또는'입니다. EBNF로 적으면 BNF보다 비단말이 적게 듭니다.

교재의 문법입니다. id는 식별자 토큰, int_constant는 정수 리터럴 토큰입니다.

기본 생각

비단말 하나에 함수 하나

재귀 하강 파싱(recursive-descent parsing)은 하향식 파싱을 코드로 직접 짜는 방법입니다. 비단말마다 함수를 하나씩 두고, 그 함수가 그 비단말에 해당하는 부분을 파싱합니다. 아래로 내려가며 부르다가(하강), 괄호를 만나면 처음 함수로 돌아옵니다(재귀).

옮기는 법

규칙이 그대로 코드가 됩니다

규칙의 우변(오른쪽)을 앞에서부터 따라가며 그대로 적습니다. 비단말이 나오면 그 함수를 부르고, 되풀이 { }는 반복문이 됩니다. lex()는 어휘 분석기를 불러 다음 토큰을 받아 옵니다.

교재는 조건을 nextToken == ADD_OP || nextToken == SUB_OP 로 적습니다. nextToken이 미리보기 토큰입니다.

우변이 여럿이면

미리보기 토큰으로 고릅니다

우변이 여럿인 비단말은 먼저 어느 우변인지 골라야 합니다. 미리보기 토큰을, 각 우변이 시작할 수 있는 첫 토큰과 견주어 맞는 것을 고릅니다. 맞는 것이 없으면 구문 오류입니다.

우변 안의 단말도 같은 식으로 맞춰 봅니다. 괄호 쪽을 골랐다면 식 뒤에 ) 가 오는지 확인합니다.

따라가 보기

문법의 층이 호출의 층이 됩니다

교재의 파서가 (sum + 47) / total 을 읽으며 남긴 기록을 옮겼습니다. expr, term, factor 순서로 들어가고, 끝나면 거꾸로 factor, term, expr 순서로 나옵니다. 괄호 안에서는 expr부터 다시 들어갑니다.

다음 편

그런데 모든 문법을 이렇게 옮길 수 있는 것은 아닙니다

6편옮길 수 없는 문법도 있을까? 3강 목록