Macro
- Macro trong Rust được dùng để loại bỏ mã trùng lặp và giảm bớt các phần lặp lại.
- Các nút câu lệnh của
sqleibniz phải triển khai trait Node, điều này dẫn đến nhiều mã bị lặp.
- Có thể dùng macro để tự động hóa việc định nghĩa struct và triển khai trait
Node.
Macro loại bỏ mã trùng lặp
- Macro định nghĩa struct, thêm chú thích tài liệu và triển khai các hàm đáp ứng trait
Node.
- Macro có thể thêm nhiều trường khác nhau thông qua các định nghĩa metavariable lặp lại.
Kiểm thử
- Trong Rust, có thể triển khai cách làm tương tự như kiểm thử dạng bảng của Go.
- Có thể dùng các macro
test_group_pass_assert! và test_group_fail! để kiểm thử nhiều cặp đầu vào và đầu ra kỳ vọng.
Kiểm thử parser
- Trong mô-đun parser cũng dùng các macro tương tự để kiểm thử kết quả của các câu lệnh SQL.
- Hàm
sql_stmt_prefix được dùng để kiểm thử câu lệnh SQL EXPLAIN.
Nhược điểm của macro
rust-analyzer không hoạt động tốt bên trong macro, và tài liệu còn thiếu.
So khớp ký tự
- Có thể dùng macro
matches! của Rust để so sánh ký tự một cách dễ dàng.
- Có ví dụ kiểm tra xem một ký tự cho trước có phải là chữ số theo chuẩn SQLite hay không.
So khớp token
- Sau khi lexer chuyển đổi luồng ký tự thành luồng token, parser sẽ dùng chúng để tạo cây cú pháp.
- Dùng câu lệnh
match để nhận diện loại token.
Hiển thị lỗi
- Thông qua xử lý lỗi, có thể cung cấp cho người dùng thông báo lỗi rõ ràng.
Tính năng tùy chọn
- Có thể dùng kiểu
Option của Rust để kiểm tra sự tồn tại của giá trị, kiểm tra điều kiện hoặc cung cấp giá trị mặc định.
- Các phương thức như
is_some_and, map, map_or giúp cải thiện độ dễ đọc của mã.
Iterator
- Có thể dùng iterator của Rust để lọc ký tự và xử lý theo quy tắc phân tích số của SQLite.
1 bình luận
Bình luận Hacker News
Gặp khó khăn khi dùng Rust do borrow checker và sự phức tạp của quản lý bộ nhớ. Thích các yếu tố lập trình hàm (FP) của Rust nhưng cuối cùng quyết định tìm ngôn ngữ khác. Sau đó phát hiện ra OCaml và cảm thấy hài lòng
Có vẻ như tác giả chưa có nhiều kinh nghiệm với Rust và các ý tưởng PL. AST có lẽ sẽ đơn giản hơn nếu được định nghĩa bằng kiểu dữ liệu đại số. Macro hoạt động khác nhau ở hầu hết các ngôn ngữ, nhưng chủ yếu được dùng để loại bỏ trùng lặp mã và giảm lặp lại
Trình phân tích cú pháp viết bằng Haskell rất nổi bật về độ đơn giản và tính dễ đọc. Nó gần như đọc giống BNF, hầu như không có các bước thủ tục kỹ thuật nên có thể tập trung vào chính ngữ pháp thực tế
Đã có kinh nghiệm viết parser bằng Ragel, Go, Java, C++, C. Viết parser JSON bằng C có thể còn đơn giản hơn mã Rust. Hạ tầng parser đã phát triển đến mức có thể tạo parser từ eBNF
Đã viết một trình disassembler và emulator eBPF bằng Rust, và cho rằng Rust phù hợp với công việc parsing. Tuy nhiên, việc dùng macro lại mang cảm giác khác với làm việc trong chính ngôn ngữ
Thích bài nói chuyện của Rob Pike về lexical scanning trong Go. Đây là một cách tiếp cận mang tính giáo dục và thanh lịch
Có thể dùng thư viện parser combinator để triển khai parser giao thức hiệu năng cao trong môi trường nhúng. Cũng có thể dùng cùng thư viện đó để viết parser giao thức nhúng
Khi viết một parser AST hoàn chỉnh bằng Rust, việc biểu diễn hệ phân cấp của các kiểu AST cụ thể khá khó khăn. Phải dùng những mẹo kiểu dữ liệu kỳ lạ và macro
Phân tích cú pháp sqlite là một công việc khó. sqlite là một nguồn cảm hứng. Sơ đồ railroad rất hữu ích, và trình tạo parser Lemon chưa được đánh giá đúng mức
Các ngôn ngữ có kiểu dữ liệu đại số rất phù hợp để phân tích cú pháp sqlite. TypeScript cũng có thể là một lựa chọn tốt. Đã viết một phần giới thiệu ngắn về cách viết parser bằng Rust