ตัวแยกวิเคราะห์ LR ไม่สามารถจัดการกฎไวยากรณ์ที่คลุมเครือได้โดยการออกแบบ (ทำให้ทฤษฎีย้อนกลับไปง่ายขึ้นในทศวรรษ 1970 เมื่อความคิดต่าง ๆ ถูกนำมาใช้)
ทั้ง C และ C ++ อนุญาตให้ใช้คำสั่งต่อไปนี้:
x * y ;
มีการแยกวิเคราะห์สองแบบ:
- มันสามารถประกาศ y เป็นตัวชี้ไปยังพิมพ์ x
- มันสามารถคูณ x และ y ได้โดยละทิ้งคำตอบ
ตอนนี้คุณอาจคิดว่าคนหลังนี้โง่และควรถูกเพิกเฉย ส่วนใหญ่จะเห็นด้วยกับคุณ อย่างไรก็ตามมีบางกรณีที่มันอาจมีผลข้างเคียง (เช่นหากทวีคูณมากเกินไป) แต่นั่นไม่ใช่ประเด็น ประเด็นก็คือมีอยู่สองจะแยกวิเคราะห์ที่แตกต่างกันและดังนั้นโปรแกรมที่อาจหมายถึงสิ่งที่แตกต่างกันขึ้นอยู่กับวิธีนี้ควรได้รับการแยกวิเคราะห์
คอมไพเลอร์จะต้องยอมรับสิ่งที่เหมาะสมภายใต้สถานการณ์ที่เหมาะสมและในกรณีที่ไม่มีข้อมูลอื่น ๆ (เช่นความรู้เกี่ยวกับประเภทของ x) จะต้องรวบรวมทั้งคู่เพื่อตัดสินใจในภายหลังว่าจะทำอย่างไร ดังนั้นไวยากรณ์ต้องอนุญาตนี้ และนั่นทำให้ไวยากรณ์ไม่ชัดเจน
ดังนั้นการแยก LR บริสุทธิ์จึงไม่สามารถจัดการสิ่งนี้ได้ หรือตัวแยกวิเคราะห์อื่น ๆ ที่มีอยู่อย่างกว้างขวางเช่น Antlr, JavaCC, YACC หรือ Bison ดั้งเดิมหรือแม้แต่ตัวแยกวิเคราะห์สไตล์ PEG ที่ใช้ในวิธี "บริสุทธิ์"
มีกรณีที่ซับซ้อนมากขึ้น (ไวยากรณ์ของเทมเพลตการแยกวิเคราะห์ต้องใช้ lookahead โดยพลการในขณะที่ LALR (k) สามารถมองไปที่โทเค็นส่วนใหญ่ได้) แต่มีเพียงตัวอย่างเดียวเท่านั้นที่จะยิงLR บริสุทธิ์ (หรืออื่น ๆ )
ตัวแยกวิเคราะห์ C / C ++ ที่แท้จริงส่วนใหญ่จัดการตัวอย่างนี้โดยใช้ตัวแยกวิเคราะห์ที่กำหนดค่าบางชนิดที่มีการแฮ็กเพิ่มเติม: พวกมันรวมการแยกวิเคราะห์กับการรวบรวมตารางสัญลักษณ์ ... ดังนั้นเมื่อถึงเวลา "x" ตัวแยกวิเคราะห์รู้ว่า x เป็นประเภท หรือไม่และสามารถเลือกระหว่าง parses ที่มีศักยภาพสองแบบ แต่ตัวแยกวิเคราะห์ที่ทำสิ่งนี้ไม่ได้เป็นบริบทฟรีและตัวแยกวิเคราะห์ LR (อันที่จริง ฯลฯ ) เป็นบริบทที่ดีที่สุด
หนึ่งสามารถโกงและเพิ่มการตรวจสอบความหมายลดเวลาต่อกฎใน parsers LR เพื่อทำ disambiguation นี้ (รหัสนี้มักจะไม่ง่าย) ตัวแยกวิเคราะห์ชนิดอื่นส่วนใหญ่มีวิธีการเพิ่มการตรวจสอบความหมายที่จุดต่าง ๆ ในการแยกวิเคราะห์ซึ่งสามารถใช้ในการทำเช่นนี้ได้
และถ้าคุณโกงมากพอคุณสามารถทำให้ตัวแยกวิเคราะห์ LR ใช้งานได้กับ C และ C ++ พวก GCC ทำมานานแล้ว แต่ยอมแพ้สำหรับการแยกวิเคราะห์ด้วยมือฉันคิดว่าเพราะพวกเขาต้องการการวินิจฉัยข้อผิดพลาดที่ดีขึ้น
มีอีกวิธีหนึ่งคือแม้ว่าซึ่งเป็นสิ่งที่ดีและสะอาดและแยกวิเคราะห์ C และ C ++ ได้ดีโดยไม่ต้องมี hackery ตารางสัญลักษณ์: parsers จี เหล่านี้เป็นตัวแยกวิเคราะห์บริบทแบบเต็ม (มี lookahead ไม่มีที่สิ้นสุดอย่างมีประสิทธิภาพ) ตัวแยกวิเคราะห์ GLR เพียงยอมรับตัวแยกวิเคราะห์ทั้งสองสร้าง "ต้นไม้" (อันที่จริงกราฟกราฟกำกับที่ส่วนใหญ่เป็นต้นไม้) ที่แสดงถึงการแยกวิเคราะห์ที่ไม่ชัดเจน โพสต์การแยกวิเคราะห์สามารถแก้ไขความคลุมเครือ
เราใช้เทคนิคนี้ในส่วนหน้า C และ C ++ สำหรับ DMS Software Reengineering Tookit (ณ เดือนมิถุนายน 2560 สิ่งเหล่านี้จัดการ C ++ 17 เต็มในภาษา MS และ GNU) พวกมันถูกใช้เพื่อประมวลผลบรรทัดของระบบ C และ C ++ ขนาดใหญ่หลายล้านบรรทัดด้วยการแยกวิเคราะห์ที่สมบูรณ์และแม่นยำซึ่งสร้าง AST พร้อมรายละเอียดของซอร์สโค้ดอย่างสมบูรณ์ (ดูAST สำหรับการแยกวิเคราะห์ที่รำคาญที่สุดของ C ++ )