---
title: "구문 분석은 1 + 2 × 3의 구조를 어떻게 알아낼까"
author: "Lee"
published_at: "2026-10-19T12:44:04.152Z"
updated_at: "2026-09-30T10:08:01.234Z"
tags: ["컴퓨터공학","프로그래밍언어"]
canonical_url: "https://ariser.io/@writer_a1cd615ab19e/%EA%B5%AC%EB%AC%B8-%EB%B6%84%EC%84%9D%EC%9D%80-1-2-3%EC%9D%98-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%95%8C%EC%95%84%EB%82%BC%EA%B9%8C"
ai_assisted: false
---

# 구문 분석은 1 + 2 × 3의 구조를 어떻게 알아낼까

[원문](https://ariser.io/@writer_a1cd615ab19e/%EA%B5%AC%EB%AC%B8-%EB%B6%84%EC%84%9D%EC%9D%80-1-2-3%EC%9D%98-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%95%8C%EC%95%84%EB%82%BC%EA%B9%8C)

`1 + 2 * 3`에는 숫자 세 개와 연산자 두 개가 있다. 토큰의 순서만으로는 어떤 계산을 먼저 묶어야 하는지가 완전히 설명되지 않는다. 구문 분석은 토큰 나열이 언어의 문법에 맞는지 판단하고, 표현식과 문장의 계층 구조를 만드는 과정이다. 이를 수행하는 파서는 이후 단계가 코드의 구조를 다룰 수 있도록 트리 같은 표현을 만든다.

![1 + 2 * 3을 덧셈 아래에 곱셈이 들어가는 트리로 분석한 그림](/api/v1/media/b8f6e71f-0e76-4705-b82a-99b01d76d19a)

*구문 분석은 토큰의 순서에서 우선순위와 중첩 구조를 만들어 낸다.*

## 문법은 가능한 모양을 정한다

문맥 자유 문법에서는 문법 기호를 다른 기호들의 나열로 바꾸는 생성 규칙을 사용한다. 표현식은 덧셈 표현식일 수 있고, 곱셈 표현식은 숫자나 괄호로 둘러싸인 표현식으로 구성될 수 있다. 규칙을 재귀적으로 적용하면 임의로 깊은 괄호와 중첩된 문장을 설명할 수 있다. 이는 토큰 하나가 어떻게 생겼는지를 다루는 어휘 규칙과 다른 수준이다.

곱셈이 덧셈보다 우선하는 문법이라면 `1 + 2 * 3`은 덧셈의 왼쪽 자식이 1, 오른쪽 자식이 곱셈인 구조가 된다. 그 곱셈의 자식은 2와 3이다. `1 + 2`부터 묶는 트리는 다른 의미를 갖는다. 우선순위 외에 결합 방향도 중요하다. 일반적인 뺄셈에서 `8 - 3 - 1`은 왼쪽부터 묶어 4가 되며, 오른쪽부터 묶으면 6이 된다.

## 파서가 토큰을 소비하는 방법

재귀 하강 파서는 문법의 주요 단위마다 함수를 두고 토큰을 읽는다. 표현식 함수가 항 함수를, 항 함수가 숫자나 괄호 함수를 호출하는 식이다. 다음 토큰을 미리 보는 방식으로 대안을 선택할 수 있지만, 왼쪽 재귀가 있는 문법을 그대로 구현하면 끝없이 자신을 호출할 수 있어 변형이 필요하다. 표현식에는 연산자 우선순위를 직접 처리하는 기법도 널리 쓰인다.

LR 계열의 상향식 파서는 토큰을 스택에 쌓고, 완성된 부분을 문법 기호로 줄여 나간다. 어떤 입력을 줄이고 언제 다음 토큰을 읽을지 표를 활용할 수 있다. [LLVM의 파서 교육 자료](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl02.html)는 재귀 하강과 연산자 우선순위를 함께 사용해 작은 언어의 구조를 만드는 사례를 제공한다. 한 방법이 모든 문법과 도구에 가장 적합한 것은 아니다.

## 모호함과 오류를 다루는 일

같은 토큰 나열에 서로 다른 구문 트리가 허용되면 문법이 모호하다고 한다. 중첩된 조건문에서 `else`가 어느 `if`와 연결되는지, 연산자의 우선순위와 결합 방향은 어떻게 정하는지 명시해야 한다. 도구의 충돌 경고를 단순히 무시하면 우연히 선택된 구조가 언어의 의도가 될 수 있다. 규칙을 다듬거나 명확한 우선순위 정책을 주는 이유다.

구문적으로 올바르다고 실행도 올바른 것은 아니다. `name + 1`은 문법상 덧셈 표현식이어도 `name`이 정의되지 않았거나 덧셈을 허용하지 않는 값을 가질 수 있다. 이런 문제는 이름 해석, 타입 검사 또는 실행 단계에서 다룬다. 파서는 주로 코드의 모양을 판단하며 변수의 모든 의미와 프로그램의 목적을 증명하지 않는다.

좋은 파서는 오류가 난 첫 위치에서 끝나는 데 그치지 않고 문장 경계 같은 지점을 찾아 분석을 이어 가기도 한다. 그러면 편집기가 한 번에 여러 오류를 보여 줄 수 있다. 다만 복구 과정에서 생긴 추가 오류를 원래 문제와 혼동하지 않도록 설계해야 한다. 구문 분석은 계산 결과를 만드는 준비 작업인 동시에, 개발자가 코드를 이해하고 수정하도록 돕는 언어 도구의 기반이다.

### 참고 자료

- [LLVM Tutorial — Implementing a Parser and AST](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl02.html)
