Lưu ý: Khi tôi sử dụng "phức tạp" trong tiêu đề, tôi có nghĩa là biểu thức có nhiều toán tử và toán hạng. Không phải là bản thân biểu thức là phức tạp.
Gần đây tôi đã làm việc trên một trình biên dịch đơn giản để lắp ráp x86-64. Tôi đã hoàn thành giao diện chính của trình biên dịch - trình phân tích cú pháp và trình phân tích cú pháp - và giờ đây tôi có thể tạo đại diện Cây Cú pháp Tóm tắt cho chương trình của mình. Và vì ngôn ngữ của tôi sẽ được gõ tĩnh, bây giờ tôi đang thực hiện giai đoạn tiếp theo: gõ kiểm tra mã nguồn. Tuy nhiên, tôi đã gặp phải một vấn đề và không thể tự mình giải quyết nó một cách hợp lý.
Hãy xem xét ví dụ sau:
Trình phân tích cú pháp của trình biên dịch của tôi đã đọc dòng mã này:
int a = 1 + 2 - 3 * 4 - 5
Và chuyển đổi nó thành AST sau:
=
/ \
a(int) \
-
/ \
- 5
/ \
+ *
/ \ / \
1 2 3 4
Bây giờ nó phải gõ kiểm tra AST. nó bắt đầu bằng kiểu đầu tiên kiểm tra =
toán tử. Đầu tiên nó kiểm tra phía bên trái của toán tử. Nó thấy rằng biến a
được khai báo là một số nguyên. Vì vậy, bây giờ nó phải xác minh rằng biểu thức phía bên phải ước tính thành một số nguyên.
Tôi hiểu làm thế nào điều này có thể được thực hiện nếu biểu thức chỉ là một giá trị duy nhất, chẳng hạn như 1
hoặc 'a'
. Nhưng làm thế nào điều này sẽ được thực hiện cho các biểu thức có nhiều giá trị và toán hạng - một biểu thức phức tạp - chẳng hạn như biểu thức ở trên? Để xác định chính xác giá trị của biểu thức, có vẻ như trình kiểm tra loại thực tế sẽ phải tự thực hiện biểu thức và ghi lại kết quả. Nhưng điều này rõ ràng dường như đánh bại mục đích tách các giai đoạn biên dịch và thực hiện.
Cách khác duy nhất tôi tưởng tượng điều này có thể được thực hiện là kiểm tra đệ quy lá của từng biểu hiện phụ trong AST và xác minh tất cả các loại lá phù hợp với loại toán tử dự kiến. Vì vậy, bắt đầu với =
toán tử, trình kiểm tra kiểu sau đó sẽ quét tất cả các AST AST bên tay trái và xác minh rằng các lá đều là số nguyên. Sau đó, nó sẽ lặp lại điều này cho mỗi toán tử trong biểu thức con.
Tôi đã thử nghiên cứu chủ đề trong bản sao "Cuốn sách rồng" của mình , nhưng dường như nó không đi sâu vào chi tiết, và chỉ đơn giản nhắc lại những gì tôi đã biết.
Phương thức thông thường được sử dụng khi trình biên dịch là kiểu kiểm tra biểu thức với nhiều toán tử và toán hạng là gì? Có bất kỳ phương pháp tôi đã đề cập ở trên được sử dụng? Nếu không, các phương pháp là gì và chính xác chúng sẽ hoạt động như thế nào?
double a = 7/2
sẽ cố gắng diễn giải phía bên phải là gấp đôi, do đó sẽ cố gắng giải thích tử số và mẫu số là gấp đôi và chuyển đổi chúng nếu cần; kết quả là a = 3.5
. Từ dưới lên sẽ thực hiện phân chia số nguyên và chỉ chuyển đổi ở bước cuối cùng (gán), vì vậy a = 3.0
.
int a = 1 + 2 - 3 * 4 - 5
mà làint a = 5 - ((4*3) - (1+2))