Trình phân tích cú pháp LR không thể xử lý các quy tắc ngữ pháp không rõ ràng, theo thiết kế. (Làm cho lý thuyết trở lại dễ dàng hơn vào những năm 1970 khi các ý tưởng được đưa ra).
C và C++ cả cho phép tuyên bố sau:
x * y ;
Nó có hai phân tích khác nhau:
- Nó có thể là việc kê khai của y, như con trỏ đến gõ x
- Nó có thể là một nhân của x và y, ném đi câu trả lời.
Bây giờ, bạn có thể nghĩ điều sau là ngu ngốc và nên bỏ qua. Hầu hết sẽ đồng ý với bạn; tuy nhiên, có những trường hợp có thể có tác dụng phụ (ví dụ: nếu nhân bị quá tải). nhưng đó không phải là vấn đề. Vấn đề là có là hai phân tích cú pháp khác nhau và do đó chương trình có thể có nghĩa là những thứ khác nhau tùy thuộc vào cách nên này đã được phân tích cú pháp.
Trình biên dịch phải chấp nhận thích hợp trong các trường hợp thích hợp và không có bất kỳ thông tin nào khác (ví dụ: kiến thức về loại x) phải thu thập cả hai để quyết định sau phải làm gì. Vì vậy, một ngữ pháp phải cho phép điều này. Và điều đó làm cho ngữ pháp trở nên mơ hồ.
Do đó việc phân tích cú pháp LR thuần túy không thể xử lý việc này. Cũng không phải nhiều trình tạo phân tích cú pháp có sẵn rộng rãi khác, như Antlr, JavaCC, YACC, hoặc Bison truyền thống, hoặc thậm chí các trình phân tích cú pháp kiểu PEG, được sử dụng theo cách "thuần khiết". Có rất nhiều trường hợp phức tạp hơn (cú pháp khuôn mẫu phân tích cú pháp đòi hỏi tùy ý, trong khi LALR (k) có thể nhìn về phía trước ở hầu hết các mã thông báo k), nhưng chỉ có một ví dụ để quay xuống tinh khiết LR (hoặc những người khác) phân tích cú pháp.
C++ Hầu hết các phân tích cú pháp/thực C xử lý ví dụ này bằng cách sử dụng một số loại phân tích cú pháp xác định với thêm một hack: họ xen lẫn vào nhau phân tích với bảng biểu tượng bộ sưu tập ... để đến thời gian "x" là gặp, sự trình phân tích cú pháp biết nếu x là một kiểu hay không, và do đó có thể chọn giữa hai phân tích cú pháp tiềm năng. Nhưng một trình phân tích cú pháp thực hiện điều này không phải là ngữ cảnh tự do và các trình phân tích cú pháp LR (các trình đơn thuần túy, v.v.) là ngữ cảnh hoàn toàn miễn phí.
Người ta có thể gian lận và thêm kiểm tra ngữ nghĩa theo thời gian giảm quy tắc trong các trình phân tích cú pháp đến LR để thực hiện việc định hướng này. (Mã này thường không đơn giản). Hầu hết các loại trình phân tích cú pháp khác có một số phương tiện để thêm kiểm tra ngữ nghĩa tại các điểm khác nhau trong phân tích cú pháp, có thể được sử dụng để thực hiện việc này.
Và nếu bạn lừa đủ, bạn có thể làm cho trình phân tích cú pháp LR hoạt động cho C và C++. Các anh chàng GCC đã làm trong một thời gian, nhưng đã cho nó cho phân tích cú pháp bằng tay, tôi nghĩ bởi vì họ muốn chẩn đoán lỗi tốt hơn.
Có một cách tiếp cận khác, tuy nhiên, tốt đẹp và sạch sẽ và phân tích C và C++ tốt mà không có bất kỳ bảng biểu tượng hackery: GLR parsers. Đây là các trình phân tích ngữ cảnh hoàn toàn miễn phí (có hiệu quả vô hạn lookahead).Trình phân tích cú pháp GLR chỉ cần chấp nhận cả hai phân tích, tạo một "cây" (thực tế là biểu đồ tuần hoàn hướng chủ yếu là cây) đại diện cho phân tích không rõ ràng. Đoạn sau phân tích cú pháp có thể giải quyết sự mơ hồ.
Chúng tôi sử dụng kỹ thuật này trong C và C++ trước kết thúc cho DMS Phần mềm Tái cấu trúc Toolkit của chúng tôi (tính đến tháng 6 năm 2017 những xử lý đầy đủ C++ 17 trong MS và GNU tiếng địa phương). Chúng đã được sử dụng để xử lý hàng triệu dòng của các hệ thống C và C++ lớn, với các phân tích đầy đủ, chính xác tạo ra các AST với đầy đủ chi tiết về mã nguồn. (Xem the AST for C++'s most vexing parse.)
Cũng giống như: bạn cần phải hiểu đệ quy để tìm hiểu đệ quy ;-). –
"Bạn sẽ hiểu các trình phân tích cú pháp khi bạn phân tích cú pháp cụm từ này". –