ข้อดีและข้อเสียของการแยกวิเคราะห์ LL และ LR คืออะไร


27

เมื่อสร้าง parser เป็นภาษาการเขียนโปรแกรมสิ่งที่ฉันได้รับและสิ่งที่ฉันสูญเสียการเลือกอย่างใดอย่างหนึ่ง?


ไม่ใช่ "ตัวแยกวิเคราะห์ LL" และ "ตัวแยกวิเคราะห์แบบเรียกซ้ำ" สองสิ่งแยกกันหรือไม่ ดูเหมือนว่าไวยากรณ์ LL (k) สามารถแยกวิเคราะห์ได้โดยใช้ตัวแยกวิเคราะห์ RD แต่นั่นไม่ได้หมายความว่าตัวแยกวิเคราะห์ LL จะเหมือนกับตัวแยกวิเคราะห์ RD เป็นอย่างนั้นเหรอ? ดู: stackoverflow.com/questions/1044600/…
xji

@XiangJi: พวกเขาเป็นอย่างมากที่แตกต่างกันในการที่ทุกไวยากรณ์ LL สามารถแมปไปสู่การแยกวิเคราะห์ RD แต่ผกผันไม่จำเป็นต้องถือ (ตั้งแต่ทางเลือก RD parsers' ได้รับการสั่งซื้อและคน LL ไวยากรณ์มีไม่เรียงลำดับ )
ทิม Febas

คำตอบ:


42

ฉันจะเปรียบเทียบ LL และ LR ในการแยกสำหรับเกณฑ์จำนวนหนึ่ง:

ความซับซ้อน

LL ชนะที่นี่ลงมือแล้ว คุณสามารถเขียน parser LL ด้วยมือได้อย่างง่ายดาย อันที่จริงแล้วสิ่งนี้ทำกันโดยทั่วไป: คอมไพเลอร์ Microsoft C # เป็นตัวแยกวิเคราะห์แบบเขียนด้วยมือ recursive (แหล่งข้อมูลที่นี่ให้ค้นหาความคิดเห็นที่ทำโดย Patrick Kristiansen - โพสต์บล็อกน่าสนใจมากเช่นกัน)

การแยกวิเคราะห์ LR ใช้วิธีการตอบโต้ที่ค่อนข้างง่ายในการวิเคราะห์ข้อความ มันใช้งานได้ แต่ใช้เวลาพอสมควรที่จะพันหัวฉัน ดังนั้นการเขียนโปรแกรมแยกวิเคราะห์ด้วยมือจึงเป็นเรื่องยาก: คุณต้องใช้ตัวแยกวิเคราะห์ LR มากขึ้นหรือน้อยลง

สภาพทั่วไป

LR ชนะที่นี่: ทุกภาษา LL เป็นภาษา LR แต่มีภาษา LR มากกว่าภาษา LL (ภาษาเป็นภาษา LL ถ้ามันสามารถแยกวิเคราะห์ด้วยตัวแยกวิเคราะห์ LL และภาษาเป็นภาษา LR หากสามารถแยกวิเคราะห์ด้วย ตัวแยกวิเคราะห์ LR)

LL มีสิ่งรบกวนเล็กน้อยที่จะรบกวนคุณเมื่อใช้งานกับภาษาโปรแกรมใด ๆ ดูที่นี่สำหรับภาพรวม

มีภาษาที่ไม่คลุมเครือซึ่งไม่ใช่ภาษา LR แต่เป็นภาษาที่ค่อนข้างหายาก คุณแทบไม่เคยเจอภาษาแบบนี้เลย อย่างไรก็ตาม LALR มีปัญหาเล็กน้อย

LALR เป็นแฮ็คมากขึ้นหรือน้อยลงสำหรับตัวแยกวิเคราะห์ LR เพื่อทำให้ตารางเล็กลง ตารางสำหรับตัวแยกวิเคราะห์ LR สามารถเติบโตได้อย่างมหาศาล ตัวแยกวิเคราะห์ LALR ยอมแพ้ความสามารถในการแยกภาษา LR ทั้งหมดเพื่อแลกเปลี่ยนกับตารางที่เล็กกว่า ตัวแยกวิเคราะห์ LR ส่วนใหญ่ใช้ LALR จริง ๆ (ไม่ใช่แอบแฝง แต่คุณมักจะพบสิ่งที่มันใช้)

LALR สามารถร้องเรียนเกี่ยวกับความขัดแย้งแบบกะ - ลดและลด - ลด ปัญหานี้เกิดจากการแฮ็กตาราง: มัน 'พับ' รายการที่คล้ายกันเข้าด้วยกันซึ่งทำงานได้เนื่องจากรายการส่วนใหญ่ว่างเปล่า แต่เมื่อไม่ว่างเปล่ามันจะสร้างความขัดแย้ง ข้อผิดพลาดประเภทนี้ไม่เป็นธรรมชาติเข้าใจยากและการแก้ไขมักจะแปลกพอสมควร

ข้อผิดพลาดของคอมไพเลอร์และการกู้คืนข้อผิดพลาด

LL ชนะที่นี่ ในการแยกวิเคราะห์ LL มันค่อนข้างง่ายที่จะปล่อยข้อผิดพลาดคอมไพเลอร์ที่มีประโยชน์โดยเฉพาะใน parsers ที่เขียนด้วยมือ คุณรู้ว่าสิ่งที่คุณคาดหวังต่อไปดังนั้นหากมันไม่ปรากฏขึ้นคุณมักจะรู้ว่าสิ่งที่ผิดพลาดและสิ่งที่ผิดพลาดที่เหมาะสมที่สุดจะเป็น

นอกจากนี้ในการแยกวิเคราะห์ LL การกู้คืนข้อผิดพลาดนั้นง่ายกว่ามาก หากอินพุตแยกไม่ถูกต้องคุณสามารถลองข้ามไปข้างหน้าเล็กน้อยและคิดออกว่าส่วนที่เหลือของอินพุตแยกวิเคราะห์อย่างถูกต้องหรือไม่ หากเช่นบางคำสั่งการเขียนโปรแกรมมีรูปแบบไม่ถูกต้องคุณสามารถข้ามไปข้างหน้าและแยกคำสั่งถัดไปเพื่อให้คุณสามารถตรวจจับข้อผิดพลาดมากกว่าหนึ่ง

การใช้ตัวแยกวิเคราะห์ LR นี่ยากกว่ามาก คุณสามารถลองเพิ่มไวยากรณ์ของคุณเพื่อให้ยอมรับอินพุตที่ผิดพลาดและพิมพ์ข้อผิดพลาดในพื้นที่ที่สิ่งต่าง ๆ เกิดความผิดพลาด แต่โดยทั่วไปมักจะทำยาก โอกาสที่คุณจะจบลงด้วยไวยากรณ์ที่ไม่ใช่ LR (หรือที่ไม่ใช่ LALR) ก็เพิ่มขึ้นเช่นกัน

ความเร็ว

ความเร็วไม่ใช่ปัญหาที่เกิดขึ้นกับวิธีที่คุณแยกวิเคราะห์อินพุตของคุณ (LL หรือ LR) แต่ให้คุณภาพของโค้ดผลลัพธ์และการใช้ตาราง (คุณสามารถใช้ตารางทั้ง LL และ LR) LL และ LR จึงเทียบเคียงได้ในส่วนนี้

การเชื่อมโยง

นี่คือลิงค์ไปยังเว็บไซต์ที่ตัดกัน LL และ LR มองหาส่วนที่อยู่ใกล้ด้านล่าง

ที่นี่คุณสามารถค้นหาการสนทนาเกี่ยวกับความแตกต่าง ไม่ใช่ความคิดที่ดีที่จะวิจารณ์ความคิดเห็นที่เกิดขึ้นอย่างมีวิจารณญาณแม้ว่าจะมีสงครามศักดิ์สิทธิ์เกิดขึ้นที่นั่น

สำหรับข้อมูลเพิ่มเติมที่นี่และที่นี่เป็นสองโพสต์ของฉันเกี่ยวกับ parsers ถึงแม้ว่าพวกเขาจะไม่เคร่งครัดเกี่ยวกับความแตกต่างระหว่าง LL และ LR

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.