Tôi đã đọc một số bài báo, bài báo và phần 4.1.4, chương 4 của Trình biên dịch: Nguyên tắc, Kỹ thuật và Công cụ (Ấn bản 2) (còn gọi là "Cuốn sách rồng"), tất cả đều thảo luận về chủ đề phục hồi lỗi trình biên dịch cú pháp. Tuy nhiên, sau khi thử nghiệm với một số trình biên dịch hiện đại, tôi đã thấy rằng chúng cũng phục hồi từ các lỗi ngữ nghĩa , cũng như các lỗi cú pháp.
Tôi hiểu khá rõ các thuật toán và kỹ thuật đằng sau trình biên dịch phục hồi từ các lỗi liên quan đến cú pháp, tuy nhiên tôi không hiểu chính xác làm thế nào trình biên dịch có thể phục hồi từ một lỗi ngữ nghĩa.
Tôi hiện đang sử dụng một biến thể nhỏ của mẫu khách truy cập để tạo mã từ cây cú pháp trừu tượng của mình. Hãy xem xét trình biên dịch của tôi biên dịch các biểu thức sau:
1 / (2 * (3 + "4"))
Trình biên dịch sẽ tạo cây cú pháp trừu tượng sau:
op(/)
|
-------
/ \
int(1) op(*)
|
-------
/ \
int(2) op(+)
|
-------
/ \
int(3) str(4)
Giai đoạn tạo mã sau đó sẽ sử dụng mẫu khách truy cập để duyệt qua cây cú pháp trừu tượng và thực hiện kiểm tra kiểu. Cây cú pháp trừu tượng sẽ được duyệt qua cho đến khi trình biên dịch đến phần trong cùng của biểu thức; (3 + "4")
. Trình biên dịch sau đó kiểm tra từng mặt của biểu thức và thấy rằng chúng không tương đương về mặt ngữ nghĩa. Trình biên dịch làm tăng một loại lỗi. Đây là vấn đề nằm ở đâu. Bây giờ trình biên dịch nên làm gì ?
Để trình biên dịch phục hồi từ lỗi này và tiếp tục gõ kiểm tra các phần bên ngoài của biểu thức, nó sẽ phải trả về một số loại ( int
hoặc str
) từ việc đánh giá phần trong cùng của biểu thức, đến phần trong cùng tiếp theo của biểu thức. Nhưng nó chỉ đơn giản là không có một loại để trở lại . Vì một lỗi loại xảy ra, không có loại nào được suy ra.
Một giải pháp khả thi mà tôi đã đưa ra, đó là nếu xảy ra lỗi loại, lỗi sẽ được đưa ra và một giá trị đặc biệt biểu thị rằng đã xảy ra lỗi loại, nên được trả về các lệnh gọi ngang qua cây cú pháp trừu tượng trước đó. Nếu các cuộc gọi truyền tải trước gặp phải giá trị này, họ biết rằng lỗi loại xảy ra sâu hơn trong cây cú pháp trừu tượng và nên tránh cố gắng suy ra một loại. Trong khi phương pháp này dường như không hoạt động, nó dường như rất không hiệu quả. Nếu phần trong cùng của một biểu thức nằm sâu trong cây cú pháp trừu tượng, thì trình biên dịch sẽ phải thực hiện nhiều lệnh gọi đệ quy để nhận ra rằng không có tác phẩm thực sự nào có thể được thực hiện và chỉ cần trả về từ mỗi một.
Là phương pháp tôi mô tả ở trên được sử dụng (tôi nghi ngờ nó). Nếu vậy, nó không hiệu quả? Nếu không, chính xác các phương thức được sử dụng khi trình biên dịch phục hồi từ các lỗi ngữ nghĩa là gì?