needmoreeasy EN 한국어
배우기

28 — 첫 컴파일러 — 아주 작은 언어

★★★★☆ (4/5)컴파일러
선수 지식
26 — 모험, 23 — 모듈
결과물
add 2 3 같은 줄을 읽고 답을 출력하는 아주 작은 언어

컴파일러는 글을 읽고 그 뜻을 판단합니다. 여러분은 이미 그중 가장 어려운 부분을 27에서 썼습니다: 줄을 나누고, 첫 단어를 읽고, 그 단어로 갈라지는 것입니다. 컴파일러는 그 일을 프로그램의 모든 줄에 되풀이할 뿐입니다. 이 가이드는 진짜 컴파일러의 씨앗 — addmul 명령이 있는 아주 작은 언어 — 을 만들고 examples/tiny-compiler.nme 예제와 비교합니다.

단계

  1. 파이프라인을 보세요. 아무리 큰 컴파일러라도 반복 속에서 세 단계만 합니다: 글 줄을 읽고, 단어로 나누고, 단어를 해석합니다. 여러분 언어의 유일한 일은 각 줄에 답하는 것입니다:

    # 파이프라인: 읽기, 나누기, 해석
    line = "add 2 3"
    parts = line.split()
    말해 int(parts[1]) + int(parts[2])
    
    실행해 보기 →

    실행하면 5가 출력됩니다 — 언어가 add 2 3 줄에 줄 답과 같습니다.

  2. 해석기 전체를 mini.ko.nme 한 파일로 저장합니다:

    # 아주 작은 계산기 언어: add 2 3, mul 4 5, 또는 quit.
    # 실행: nme 실행 mini.ko
    
    def run_command(parts):
        verb = parts[0]
        if verb == "add":
            return int(parts[1]) + int(parts[2])
        elif verb == "mul":
            return int(parts[1]) * int(parts[2])
        else:
            return "모르는 명령입니다"
    
    
    말해 "미니 언어 — add 2 3, mul 4 5, 또는 quit."
    
    while True:
        물어봐 line, "다음 줄? "
        만약 line == "quit":
            말해 "안녕히 가세요!"
            break
        parts = line.split()
        if len(parts) == 3:
            result = run_command(parts)
            말해 result
        else:
            말해 "형식: add 2 3 또는 mul 4 5"
    
    실행해 보기 →
  3. 실행하고 작은 프로그램을 넣어 보세요:

    printf 'add 2 3\nmul 4 5\nsub 9 2\nquit\n' | nme 실행 mini.ko
    
    미니 언어 — add 2 3, mul 4 5, 또는 quit.
    다음 줄? 5
    다음 줄? 20
    다음 줄? 모르는 명령입니다
    다음 줄? 안녕히 가세요!
    

    add 2 35로, mul 4 520으로 답하고, sub 9 2는 아직 명령이 아니라 모르는 명령 메시지를 받습니다.

  4. 해석은 함수입니다. verb = parts[0]이 첫 단어에 이름을 붙이고, 동사에 대한 if가 명령마다 갈래 하나로 나눕니다. 둘째와 셋째 단어는 int(parts[1])int(parts[2])로 숫자가 됩니다:

    def run_command(parts):
        verb = parts[0]
        if verb == "add":
            return int(parts[1]) + int(parts[2])
        elif verb == "mul":
            return int(parts[1]) * int(parts[2])
        else:
            return "모르는 명령입니다"
    
    실행해 보기 →

    마지막 else가 오류 처리입니다: 모르는 동사는 크래시 대신 메시지로 돌아옵니다.

  5. 반복이 파이프라인입니다. 물어봐로 줄을 읽고, quit에서 멈추고, .split()으로 나누고, len(parts) == 3으로 모양을 지키고, 해석해 출력합니다:

    while True:
        물어봐 line, "다음 줄? "
        만약 line == "quit":
            말해 "안녕히 가세요!"
            break
        parts = line.split()
        if len(parts) == 3:
            result = run_command(parts)
            말해 result
        else:
            말해 "형식: add 2 3 또는 mul 4 5"
    
    실행해 보기 →
  6. examples/tiny-compiler.nme 예제는 진짜 (아주 작은) 컴파일러입니다: 터미널 대신 목록에서 소스 줄을 읽고, 출력으로 Python 코드를 만듭니다:

    # examples/tiny-compiler.nme의 일부
    python_lines = []
    for line in tiny_source:
        words = line.split()
        if words[0] == "말하기":
            text = " ".join(words[1:])
            python_lines.append(f"print({text!r})")
    
    실행해 보기 →

    각 줄을 나누고 첫 단어를 확인해 print(...) 줄을 만듭니다 — 숫자 대신 만들어진 Python이 답일 뿐 같은 읽기 → 나누기 → 해석 파이프라인입니다. 숫자 대신 answer = 5를 만드는 생성 갈래를 더하면 해석기가 컴파일러로 바뀝니다.

  7. 영어 쌍둥이 mini.nme는 같은 def를 쓰고 반복을 ask, if, show로 씁니다:

    def run_command(parts):
        verb = parts[0]
        if verb == "add":
            return int(parts[1]) + int(parts[2])
    
    
    while True:
        ask line, "Next line? "
        if line == "quit":
            show "Goodbye!"
            break
        parts = line.split()
        result = run_command(parts)
        show result
    
    실행해 보기 →

    같은 파이프 입력이 두 언어에서 답합니다.

직접 해보기

run_commandsubdiv 명령을 더해 보세요: sub는 뺄셈 (int(parts[1]) - int(parts[2]))이고 div는 나눗셈입니다. 그다음 프로그램에 sub 9 2div 12 3을 넣어 모르는 명령 메시지가 사라지는 것을 보세요.

배운 것

  • 컴파일러는 글을 읽고 단어로 나누고 각 줄을 해석합니다.
  • 동사에 대한 if가 달린 run_command(parts) 함수가 분기입니다.
  • split()은 줄을 자르고 int()는 글을 숫자로 바꿉니다.
  • 읽기 → 나누기 → 해석 파이프라인이 진짜 컴파일러의 씨앗입니다.

GitHub에서 이 문서 보기