เมื่อสร้าง parser เป็นภาษาการเขียนโปรแกรมสิ่งที่ฉันได้รับและสิ่งที่ฉันสูญเสียการเลือกอย่างใดอย่างหนึ่ง?
เมื่อสร้าง parser เป็นภาษาการเขียนโปรแกรมสิ่งที่ฉันได้รับและสิ่งที่ฉันสูญเสียการเลือกอย่างใดอย่างหนึ่ง?
คำตอบ:
ฉันจะเปรียบเทียบ 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