CPython 파헤치기를 기본으로 공부하며 작성한 글입니다.
CPython
Cpython 이란?
기본적으로 우리가 많이 활용하는 파이썬으로, C언어로 작성된 파이썬 인터프리터를 의미한다.
Cpython이 파이썬이 아니라 C로 작성된 이유는 컴파일러의 작동 방식 때문인데, 새로운 프로그래밍 언어를 만들려면 컴파일러를 컴파일 할 수 있는 프로그램이 필요하고 이를 개발는 데에는 가장 안정적이고 오래된 언어로 먼저 작성되기 때문이다. 특히 윈도우와 리눅스 커널 API가 모두 C로 작성이 되어 있기 때문에 C로 선택하는 것이 꽤나 합리적인 선택이었다고 한다.
파이썬의 문법 파일은 파서 표현식 문법(Parsing Expression Grammer, PEG) 사양을 사용한다.
- * : 반복
- + : 최소한 한 번 반복
- [] : 선택적인 부분
- | : 대안
- () : 그룹
이 부분을 설명하면서 철도 다이어그램에 대한 이야기도 나오는데, 철도다이어그램(Railroad Diagram)은 형식 언어의 구문을 표시하는 그래픽 방식 중 하나라고 한다. 철도 다이어그램으로 검색하면 정말 열차가 어쩌고 하는 이야기들이 나오는데, 개인적으로는 railroad니까 철길다이어그램이 더 안 헷갈리는 표현은 아닐까하는 생각이 든다.
파서
파서란?
소스 코드를 분석하여, 그것을 이해할 수 있는 구문 트리(Syntax Tree)로 변환하는 프로그램 또는 모듈이다. 이렇게 생성된 구문트리는 컴파일러나 인터프리터 등에서 중간 코드를 생성하거나 실행하는 데 사용된다고 한다.
파서 생성기란?
파이썬 컴파일러는 문법 파일을 직접 사용하지 않고, 파서 생성기가 문법 파일에서 생성한 파서를 사용한다.
파이썬 3.9부터는 pegen이라고 하는 새로운 PEG생성기가 도입되었다.
Grammer에 있는 python.gram에서 문법을 살짝 변경해보는 예제


위의 문법을 참고해서 해석해보면 pass랑 proceed를 하나의 그룹으로 묶고, 그 두개는 서로 대안이 된다.
이렇게 변경한 이후 수정한 문법 파일의 빌드를 위해 터미널에서 PCbuild폴더로 이동하고
build.bat --regen
을 실행한다.
나는 vscode터미널에서 실행을 하는데, 왜인지는 모르겠지만 저렇게만 치면 안되고 .\build.bat --regen으로 하라는 안내가 나온다.

책에서는 parse.c파일이 생성되었다는 출력을 확인할 수 있다는데, 나에게는 그런 건 보이지 않았다.....
이후 컴파일을 하면 되는데 vscode에서는 F5를 눌러주면 된다.
그렇게 누르고 기다리면 (한국인에게는 시간이 좀 오래 걸리게 느껴짐) 창이뜨고, pass 처럼 proceed를 사용하는 함수를 만들어 볼 수 있다.

이렇게 proceed를 사용했는데도, pass를 쓴 것 같은 결과가 나오게 된다.
토큰
Grammer폴더의 Tokens파일은 파스 트리의 리프 노드에서 사용되는 고유한 토큰들을 정의하고 있다고 한다. 파스 트리는 파싱(구문분석)을 통해서 생성된 구문 트리라고 할 수 있는데, 구문 분석을 수행하는 파서는 소스 코드를 의미 있는 구문 단위로 분해해서 파스 트리를 생성한다. 파스트리의 리프 노드는 소스 코드의 각 토큰을 나타내고, 각 토큰은 고유한 의미를 가지고 있다.
tokenize모듈을 이용하면 토큰의 사용에 대해서 확인할 수 있는데, 4_test_tokens라는 파이썬 스크립트 파일을 만들어서 실행해보았다.
python -m tokenize -e 4_test_tokens.py
책에서는 ./가 python앞에 붙어있었는데, vscode터미널에서는 그걸 입력하면 인식하지 못해서 빼고 실행했다.
-e 플래그를 추가해서 정확한 토큰의 이름까지 출력해보고자 한다.

그럼 이런 식의 결과를 볼 수 있다.
tokenize모듈은 인코딩 토큰, 함수의 정의를 마치는 DEDENT, 파일의 끝을 뜻하는 ENDMARKER등 토큰을 자동으로 추가하기도 한다.
정리위에서 건드렸던 python.gram 파일의 pass를 원래대로 돌려 놓고,

다음 코드를 실행해서 코드를 정리하는 것 까지 끝
# cpython 상위 폴더로 이동해서
git checkout -- Grammar/python.gram
# PCbuild폴더로 이동해서
.\build.bat --regen
.\build.bat -t CleanAll
.\build.bat -t Build