---
title: "파서의 무한 루프 문제를 assert로 해결하는 새로운 기법"
published: 2025-12-29T23:29:35.000Z
canonical: https://jeff.news/article/1257
---
# 파서의 무한 루프 문제를 assert로 해결하는 새로운 기법

matklad가 resilient LL 파싱에서 발생하는 무한 루프/재귀 문제의 새로운 해결책을 제시함. 파서가 토큰을 소비했는지 assert로 검증하면 즉시 에러 감지가 되고, 암묵적 계약이 코드에 명시적으로 드러남.

- matklad(rust-analyzer 개발자)가 크리스마스 연휴에 또 토이 파서를 만들다가 발견한 꿀팁. Resilient LL Parsing 방식에서 골치 아픈 무한 루프/재귀 문제를 깔끔하게 해결하는 방법임
- 문제의 핵심: 에러 복구(resilient parsing)를 위해 토큰을 소비하지 않고 넘어가는 경우가 있는데, 이게 루프나 Pratt 재귀 호출 안에서 발생하면 무한 루프에 빠짐. 디버거 없이는 원인 찾기도 힘든 짜증나는 버그
- 기존 해결책 두 가지: (1) Fuel 패턴 — `Cell<u32>` 필드를 lookahead마다 감소시키고 토큰 소비 시 충전하는 방식. 크래시는 나지만 문제 지점에서 스택 프레임 몇 개 떨어진 곳에서 터짐 (2) 어떤 함수가 토큰을 반드시 소비하는지 머릿속으로 추적하기. 사람이 하는 거라 실수가 잦음
- 새로운 해법: 파서가 실제로 전진(advance)했는지 assert로 검증하는 것. 전진하지 않았으면 즉시 에러가 나고, 더 중요한 건 "이 함수는 토큰을 소비해야 한다"는 암묵적 계약이 코드에 명시적으로 드러난다는 점
- 돌이켜보면 당연한 아이디어인데 파서를 여러 개 만들고 나서야 떠올랐다고. API 설계 예시와 실제 버그 수정 과정까지 글에 포함되어 있음

## 핵심 포인트

- Resilient parsing에서 토큰 미소비 시 무한 루프에 빠지는 문제
- 기존 해법: Fuel 패턴(Cell<u32>)과 머릿속 함수 추적
- 새 해법: advance assert로 즉시 에러 감지 + 계약의 코드 명시화
- 파서 API 설계 예시와 실제 버그 수정 과정 포함

## 인사이트

단순한 assert 하나가 디버깅 난이도를 극적으로 낮추는 좋은 사례. '당연한 아이디어'가 오래 걸린 이유는 암묵지를 형식지로 바꾸는 발상 전환이 필요했기 때문.
