GN⁺: 토큰화 및 구문 분석에 Rust를 사용하는 이유
(xnacly.me)매크로
- Rust의 매크로는 코드 중복 제거와 반복 감소를 위해 사용됨.
-
sqleibniz
의 문장 노드는Node
트레이트를 구현해야 하며, 이는 많은 코드 중복을 초래함. - 매크로를 사용하여 구조체 정의와
Node
트레이트 구현을 자동화할 수 있음.
코드 중복 제거 매크로
- 매크로는 구조체를 정의하고, 문서 주석을 추가하며,
Node
트레이트를 만족시키는 함수를 구현함. - 매크로는 반복적인 메타변수 정의를 통해 다양한 필드를 추가할 수 있음.
테스트
- Rust에서는 Go의 테이블 기반 테스트와 유사한 방식을 구현할 수 있음.
-
test_group_pass_assert!
와test_group_fail!
매크로를 사용하여 다양한 입력과 예상 출력 쌍을 테스트할 수 있음.
파서 테스트
- 파서 모듈에서도 유사한 매크로를 사용하여 SQL 문장의 결과를 테스트함.
-
EXPLAIN
SQL 문장을 테스트하기 위해sql_stmt_prefix
함수가 사용됨.
매크로의 단점
-
rust-analyzer
는 매크로 내부에서 잘 작동하지 않으며, 문서화가 부족함.
문자 매칭
- Rust의
matches!
매크로를 사용하여 문자를 쉽게 비교할 수 있음. - 주어진 문자가 SQLite 숫자인지 확인하는 예시가 있음.
토큰 매칭
- 렉서가 문자 스트림을 토큰 스트림으로 변환한 후, 파서는 이를 사용하여 구문 트리를 생성함.
-
match
문을 사용하여 토큰 유형을 인식함.
오류 표시
- 오류 처리를 통해 사용자에게 명확한 오류 메시지를 제공함.
선택적 기능
- Rust의
Option
타입을 사용하여 값이 존재하는지 확인하고, 조건을 체크하거나 기본값을 제공할 수 있음. -
is_some_and
,map
,map_or
등의 메서드를 사용하여 코드 가독성을 높임.
반복자
- Rust의 반복자를 사용하여 문자를 필터링하고, SQLite의 숫자 파싱 규칙에 맞게 처리함.
Hacker News 의견
-
Rust의 차용 검사기(borrow checker)와 메모리 관리의 어려움으로 인해 Rust 사용에 어려움을 겪음. Rust의 함수형 프로그래밍(FP) 요소를 좋아했지만, 다른 언어를 찾기로 결정함. OCaml을 발견하고 만족스러움을 느낌
-
Rust와 PL 아이디어에 대한 경험이 부족한 것으로 보임. AST는 대수적 데이터 타입으로 정의하는 것이 더 간단할 것이라고 생각함. 매크로는 대부분의 언어에서 다르게 작동하지만, 주로 코드 중복 제거와 반복 감소를 위해 사용됨
-
Haskell로 작성한 파서는 단순성과 가독성 면에서 뛰어남. BNF와 거의 비슷하게 읽히며 기술적인 절차가 거의 없어 실제 문법에 집중할 수 있음
-
Ragel, Go, Java, C++, C로 파서를 작성한 경험이 있음. C로 JSON 파서를 작성하는 것이 Rust 코드보다 더 간단할 수 있음. eBNF로 파서를 만들 수 있는 포화점에 도달할 때까지 파서 인프라가 발전함
-
Rust로 eBPF 디스어셈블러와 에뮬레이터를 작성했으며, Rust가 파싱 작업에 적합하다고 생각함. 그러나 매크로 사용이 언어 내에서의 작업과는 다르게 느껴짐
-
Rob Pike의 Go에서의 렉시컬 스캐닝에 대한 강연을 좋아함. 교육적이고 우아한 접근법임
-
파서 조합기 라이브러리를 사용하여 고성능 프로토콜 파서를 임베디드 환경에 배포할 수 있음. 동일한 라이브러리를 사용하여 임베디드 프로토콜 파서를 작성할 수 있음
-
Rust에서 전체 AST 파서를 작성할 때 구체적인 AST 타입의 계층 구조를 표현하는 것이 어려웠음. 이상한 타입 트릭과 매크로를 사용해야 했음
-
sqlite 구문을 파싱하는 것은 어려운 작업임. sqlite는 영감을 주는 소스임. 레일로드 다이어그램이 매우 유용하며, 레몬 파서 생성기는 충분한 인정을 받지 못함
-
대수적 데이터 타입을 가진 언어는 sqlite 구문 파싱에 적합함. Typescript도 좋은 선택이 될 수 있음. Rust로 파서를 작성하는 방법에 대한 간단한 소개를 작성함