ภาษาสมัยใหม่ยังใช้เครื่องแยกวิเคราะห์หรือไม่?


38

ฉันกำลังค้นคว้าเกี่ยวกับชุดคอมไพเลอร์ gcc ในวิกิพีเดียที่นี่เมื่อสิ่งนี้เกิดขึ้น:

GCC เริ่มต้นใช้ตัวแยกวิเคราะห์ LALR ที่สร้างด้วย Bison แต่ค่อย ๆ เปลี่ยนเป็นตัวแยกวิเคราะห์แบบสืบเชื้อสายแบบเขียนด้วยมือซ้ำ; สำหรับ C ++ ในปี 2004 และสำหรับ C และ Objective-C ในปี 2549 ปัจจุบันส่วนหน้าทั้งหมดใช้ตัวแยกวิเคราะห์ที่เขียนด้วยมือแบบเรียกซ้ำ

ดังนั้นด้วยประโยคสุดท้ายนั้น (และสำหรับที่ฉันไว้ใจ wikipedia) ฉันสามารถพูดได้อย่างแน่นอนว่า "C (gcc), C ++ (g ++), Objective-C, Objective-C ++, Fortran (gfortran), Java (gcj), Ada (GNAT), Go (gccgo), Pascal (gpc), ... Mercury, Modula-2, Modula-3, PL / I, D (gdc) และ VHDL (ghdl) "เป็นส่วนหน้าทั้งหมดที่ไม่มี ใช้ตัวแยกวิเคราะห์อีกต่อไป นั่นคือพวกเขาทั้งหมดใช้ตัวแยกวิเคราะห์ที่เขียนด้วยมือ

คำถามของฉันคือการปฏิบัตินี้แพร่หลายหรือไม่? โดยเฉพาะฉันกำลังมองหาคำตอบที่แน่นอนในการ "การดำเนินการตามมาตรฐาน / อย่างเป็นทางการของ x มีตัวแยกวิเคราะห์ที่เขียนด้วยมือ" สำหรับ x ใน [Python, Swift, Ruby, Java, Scala, ML, Haskell] หรือไม่ (ที่จริงแล้วข้อมูลเกี่ยวกับภาษาอื่น ๆ ก็ยินดีต้อนรับที่นี่ด้วย) ฉันแน่ใจว่าฉันสามารถหาได้ด้วยตัวเองหลังจากขุดมามาก แต่ฉันก็มั่นใจว่าชุมชนจะตอบคำถามนี้ได้ง่าย ขอบคุณ!


3
จุดข้อมูล: CPython มีตัวสร้างการแยกวิเคราะห์ LALR ในบ้าน (pgen) ไม่รู้เรื่องที่เหลือ

8
จุดข้อมูล: Ghc (haskell) ใช้เครื่องมือสร้างตัวแยกวิเคราะห์ LALR (มีความสุข) เช่นเดียวกับ OCaml
Twan van Laarhoven

1
ควรจะ"ทำคอมไพเลอร์ประสิทธิภาพสูงที่ทันสมัย ​​... "หรือคล้ายกันเพราะภาษาเป็นข้อมูลจำเพาะที่ไม่ใช้งานในขณะที่มันเป็นคอมไพเลอร์ที่ทำหรือไม่ใช้เครื่องแยกวิเคราะห์ที่สร้างขึ้น
dmckee

@dmckee ใช่คุณถูกต้อง อย่างไรก็ตามการตั้งชื่อเริ่มต้นที่จะยาวและตรงประเด็นน้อยลง อย่าลังเลที่จะแก้ไขแม้ว่าคุณจะสร้างสรรค์มากกว่าฉัน!
eatonphil

เกี่ยวกับ ML: MLton ใช้ตัวแยกวิเคราะห์ที่เฉพาะเจาะจงกับ ML ฉัน 90% แน่ใจว่า SML / NJ ทำเช่นกันแม้ว่าฉันจะไม่ค่อยคุ้นเคยกับมัน คุณอาจจะหรืออาจไม่ต้องการพิจารณาว่า "เขียนด้วยมือ"
Patrick Collins

คำตอบ:


34

AFAIK, GCC ใช้ parsers ที่เขียนด้วยมือโดยเฉพาะเพื่อปรับปรุงการวินิจฉัยข้อผิดพลาดทางไวยากรณ์ (เช่นการให้ข้อความที่มีความหมายของมนุษย์เกี่ยวกับข้อผิดพลาดทางไวยากรณ์)

ทฤษฎีการแยกวิเคราะห์ (และเครื่องกำเนิดไฟฟ้าแยกวิเคราะห์ลงมาจาก) เป็นส่วนใหญ่เกี่ยวกับการรับรู้และการแยกวิเคราะห์วลีการป้อนข้อมูลที่ถูกต้อง แต่เราคาดหวังจากคอมไพเลอร์ว่าพวกเขาให้ข้อความแสดงข้อผิดพลาดที่มีความหมาย (และพวกเขาสามารถแยกวิเคราะห์ส่วนที่เหลืออย่างมีความหมายหลังจากข้อผิดพลาดทางไวยากรณ์) สำหรับอินพุตที่ไม่ถูกต้อง

นอกจากนี้ภาษาดั้งเดิมเก่าเช่น C11 หรือ C ++ 11- (ซึ่งเป็นแนวคิดรวบยอดแม้ว่าการแก้ไขล่าสุดของพวกเขาคือเพียงสามปี) ก็ไม่ได้อยู่ในบริบทใด ๆ เลย การจัดการกับความรู้สึกไวบริบทว่าในไวยากรณ์สำหรับเครื่องกำเนิดไฟฟ้า parser (เช่นวัวกระทิงหรือแม้กระทั่งการเดินเส้น ) เป็นเรื่องยากที่น่าเอือมระอา


2
เห็นพ้อง การกู้คืนที่ดีจากข้อผิดพลาดในการแยกวิเคราะห์ (เมื่อคุณไม่ต้องการหยุดการแยกวิเคราะห์ที่ข้อผิดพลาดแรกคือ La Borland Pascal เก่า) และการสร้างข้อความแสดงข้อผิดพลาดคุณภาพดี (รวมถึงคำแนะนำและคำแนะนำสำหรับการแก้ไขเช่นมนุษย์ต้องการ) - ความไวต่องานการแก้ปัญหา พวกเขาสามารถทำได้บนตัวแยกวิเคราะห์หุ้น parser เอาท์พุทบ้าง แต่มันเป็นหวด
Jonathan Eunice

2
Dealing with that context sensitiveness in grammars for parser generators is boringly difficult. นอกจากนี้ยังเป็นไปไม่ได้มากหรือน้อยที่เครื่องมือเหล่านี้จะสร้างตัวแยกวิเคราะห์ที่ไม่มีบริบท สถานที่ที่ถูกต้องในการตรวจสอบว่ามีข้อ จำกัด ตามบริบททั้งหมดหรือไม่หลังจากที่คุณสร้างทรีแยกวิเคราะห์หากคุณใช้เครื่องมือแบบนี้
dtech

7

เครื่องกำเนิดไฟฟ้าแยกวิเคราะห์และเครื่องมือแยกวิเคราะห์ค่อนข้างทั่วไป ข้อดีของการใช้งานทั่วไปคือการสร้างเครื่องมือแยกวิเคราะห์ที่รวดเร็วและทำให้การทำงานง่ายขึ้นในโครงการโดยรวม

เครื่องยนต์ parser ตัวเองทนทุกข์ทรมานกับประสิทธิภาพการทำงานด้านหน้าเพราะมันเป็นเรื่องทั่วไป รหัสที่เขียนด้วยมือใด ๆ จะเร็วกว่าเครื่องมือแยกวิเคราะห์ตารางอย่างมีนัยสำคัญเสมอ

พื้นที่ที่สองที่ parser generators / engine มีปัญหาคือภาษาโปรแกรมจริงทั้งหมดนั้นมีความอ่อนไหวตามบริบท ภาษา LR ไม่มีบริบทหมายความว่ามีรายละเอียดปลีกย่อยมากมายเกี่ยวกับการวางตำแหน่งและสภาพแวดล้อมที่ไม่สามารถถ่ายทอดได้อย่างถูกต้องในไวยากรณ์ ความพยายามที่จะอธิบายถึงกฎพื้นฐานของภาษาเช่น "ประกาศก่อนการใช้งาน" ฯลฯ การใช้ความไวตามบริบทนี้ในการเขียนด้วยมือนั้นจะส่งตรงไปยังโค้ด


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

2
และเกี่ยวกับพื้นที่ที่สอง: ภาษาการเขียนโปรแกรมที่สำคัญหลายภาษาไม่ได้คำนึงถึงบริบทในทุกแง่มุมที่ใช้ (คุณต้องอ้างถึงชุดของโปรแกรมที่ถูกต้องทั้งหมดหลังจากการตรวจสอบประเภทและสิ่งที่ไม่เคยเขียนด้วยมือหรือ parser ที่สร้างขึ้นพยายามแยกวิเคราะห์) เป็นความจริงที่ parsers ที่เขียนด้วยมือมีความยืดหยุ่นมากกว่าและเป็นประโยชน์สำหรับบางภาษา แต่ส่วนใหญ่จะอยู่ในขอบเขตของการกู้คืนข้อผิดพลาดและการรายงานการเพิ่มขึ้น ฯลฯ - เครื่องกำเนิดไฟฟ้า parser มักจะละทิ้งเพราะพลังการจดจำต้องการเขียนไวยากรณ์ดังกล่าวเป็นเรื่องที่แตกต่างกัน) -1

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

1
C และ C ++ ต้องการข้อมูลตารางสัญลักษณ์ระหว่างการวิเคราะห์คำ (หรือยอมรับแผนผังการแยกวิเคราะห์ที่เฉพาะเจาะจงน้อยกว่าซึ่งไม่มีความแตกต่างระหว่างตัวอย่างเช่นคำสั่งการแสดงออกและการประกาศตัวแปร) แต่ฉันไม่ได้คิดถึงสิ่งเหล่านั้น ภาษาเช่น Java, Lisps, JavaScript, Ruby, Python, Go, Rust, Scala, Swift, Haskell (และอาจมีอีกหลายอย่างที่อาจจะเป็น C # และ ML เช่นกัน) ไม่ต้องการข้อมูลใด ๆ เพื่อสร้าง AST ที่คุณต้องการ ต้องการอยู่แล้ว หลายคนมี LL (1) ไวยากรณ์จริงหรือแม้แต่ไวยากรณ์ LALR

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