Trình phân tích cú pháp LR không thể xử lý các quy tắc ngữ pháp mơ hồ, theo thiết kế. (Làm cho lý thuyết trở nên dễ dàng hơn vào những năm 1970 khi các ý tưởng đang được thực hiện).
Cả C và C ++ đều cho phép tuyên bố sau:
x * y ;
Nó có hai phân tích khác nhau:
- Nó có thể là khai báo của y, như con trỏ để gõ x
- Nó có thể là bội số của x và y, ném đi câu trả lời.
Bây giờ, bạn có thể nghĩ rằng cái sau là ngu ngốc và nên được bỏ qua. Hầu hết sẽ đồng ý với bạn; tuy nhiên, có những trường hợp nó có thể có tác dụng phụ (ví dụ: nếu bội số bị quá tải). Nhưng đó không phải là vấn đề. Vấn đề là ở đó là hai phân tích khác nhau, và do đó một 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ày nên đã được phân tích cú pháp.
Trình biên dịch phải chấp nhận thông tin phù hợp trong các trường hợp thích hợp và trong trường hợp 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 này phải làm gì. Do đó, một ngữ pháp phải cho phép điều này. Và điều đó làm cho ngữ pháp mơ hồ.
Do đó, phân tích cú pháp thuần túy không thể xử lý việc này. Cũng không thể có nhiều trình tạo trình 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 túy".
Có rất nhiều trường hợp phức tạp hơn (cú pháp phân tích cú pháp yêu cầu tìm kiếm 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ỉ mất một ví dụ để bắn hạ phân tích thuần túy (hoặc các mẫu khác).
Hầu hết các trình phân tích cú pháp C / C ++ thực sự xử lý ví dụ này bằng cách sử dụng một số loại trình phân tích cú pháp xác định có thêm một hack: chúng đan xen phân tích cú pháp với bộ sưu tập bảng ký hiệu ... để đến lúc gặp "x", trình phân tích cú pháp biết nếu x là một loại hoặc không, và do đó có thể chọn giữa hai phân tích tiềm năng. Nhưng một trình phân tích cú pháp không thực hiện ngữ cảnh này và các trình phân tích cú pháp LR (các trình phân tích thuần túy, v.v.) không có ngữ cảnh (tốt nhất).
Người ta có thể gian lận và thêm các kiểm tra ngữ nghĩa theo thời gian giảm theo quy tắc trong các trình phân tích cú pháp LR để thực hiện đị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 để làm điều này.
Và nếu bạn gian lận đủ, 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 một lúc, nhưng đã từ bỏ việc 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.
Mặc dù vậy, có một cách tiếp cận khác, rất hay và sạch và phân tích cú pháp C và C ++ tốt mà không cần bất kỳ trình hack bảng biểu tượng nào: trình phân tích cú pháp GLR . Đây là các trình phân tích cú pháp miễn phí ngữ cảnh đầy đủ (có cái nhìn vô hạn hiệu quả). Các trình phân tích cú pháp GLR đơn giản chấp nhận cả hai phân tích cú pháp, tạo ra một "cây" (thực ra là một biểu đồ chu kỳ có hướng chủ yếu giống như cây) đại diện cho phân tích mơ hồ. Một vượt qua 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 giao diện C và C ++ cho Tookit Tái cấu trúc phần mềm DMS của chúng tôi (tính đến tháng 6 năm 2017, chúng xử lý đầy đủ C ++ 17 theo phương ngữ MS và GNU). Chúng đã được sử dụng để xử lý hàng triệu dòng hệ thống C và C ++ lớn, với các phân tích cú pháp chính xác, đầy đủ tạo ra AST với các chi tiết đầy đủ về mã nguồn. (Xem phân tích vexing nhất của AST cho C ++. )