파서 조합기 - 작은 파서를 조합해 구조화된 데이터를 만드는 방법

2 hours ago 5

파서 조합기(parser combinator) 는 작은 파싱 함수를 조합해 복잡한 텍스트를 구조화된 데이터로 변환하는 방식으로, 정규식으로는 복잡하고 tree-sitter를 쓰기에는 과한 작업에 적합함 기본 단위인 부분 파서는 입력 문자열에서 일부를 읽고, 파싱한 값과 남은 문자열을 함께 반환하며 내부에서 정규식을 사용해도 됨 pSeq 는 여러 파서를 순서대로 연결하고, pMap 은 파싱 결과를 원하는 형태로 바꾸며, pRepeat는 같은 파서를 더 이상 적용할 수 없을 때까지 반복함 TypeScript 예제는 이 조합기들로 ping 출력을 파싱해 헤더, 패킷 목록, 전송 통계와 RTT 정보를 담은 객체를 생성함 중첩된 파싱을 함수 조합으로 구성하면 정규식보다 정확성과 유지보수성을 확보하기 쉬우며, 파서 조합기는 역추적과 전방 탐색도 지원할 수 있음 부분 파서와 순차 연결 파싱은 텍스트처럼 구조가 약한 입력을 객체처럼 더 구조화된 데이터로 바꾸는 작업임 정규식은 복잡한 작업에서 다루기 어려워지고, 코드 편집기의 구문 강조에도 쓰이는 tree-sitter는 이런 작업에 과할 수 있음 부분 파서의 타입은 type Parser<T> = (input: string) => [T, string]으로, 파싱한 값과 남은 입력을 튜플로 반환함 pInteger는 /^\d+/로 앞부분의 숫자를 읽고 숫자형 값으로 변환함 "10 20 30"을 입력하면 [10, " 20 30"]을 반환하며, 일치하는 숫자가 없으면 예외를 던짐 순차 연결은 앞선 파서가 남긴 문자열을 다음 파서의 입력으로 넘기는 방식임 "Hello 100"에 pHello, pIgnoreWhitespace, pInteger를 차례로 적용하면 "Hello", null, 100을 얻고 남은 입력은 빈 문자열이 됨 pHello는 "Hello" 접두사를 확인하고, pIgnoreWhitespace는 하나 이상의 공백 문자를 소비한 뒤 null을 반환함 이 연결 전체를 pHello100 이라는 새 파서로 감싸면 Parser<[string, null, number]>가 되며, 다른 파서와 같은 방식으로 조합할 수 있음 pSeq와 함수 조합 pSeq 는 여러 파서를 받아 순서대로 실행하는 새 파서를 생성함 각 파서의 결과를 배열에 모으고, 남은 입력을 다음 파서로 전달한 뒤 최종 결과와 나머지 문자열을 반환함 pSeq(pHello, pIgnoreWhites...

Read Entire Article