การเขียนคอมไพเลอร์คอมไพเลอร์ - ความเข้าใจด้านการใช้งานและคุณสมบัติ


10

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

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

ฉันมาถึงจุดที่ฉันจะเริ่มแยกต้นไม้แยกออกจากไวยากรณ์ที่กำหนดตามด้วย Recursive Descent parser ซึ่งใช้ DFA เพื่อแยกแยะเส้นทางข้างหน้า (คล้ายกับ ANTLR 4's LL (*)) ดังนั้นฉันจึง คิดว่าฉันจะเปิดมันเพื่อรับข้อมูลเชิงลึก

ในคอมไพเลอร์ตัวแยกวิเคราะห์คุณลักษณะชนิดใดที่เหมาะที่สุด?

จนถึงตอนนี้เป็นภาพรวมคร่าวๆของสิ่งที่นำไปใช้:

  1. แม่แบบ
  2. ดูการคาดการณ์ล่วงหน้ารู้ว่าอะไรถูกต้อง ณ จุดที่กำหนด
  3. Rule 'Deliteralization' ใช้ตัวอักษรในกฎและแก้ไขโทเค็นที่มา
  4. Automata ของ Nondeterministic
  5. Automata ที่กำหนด
  6. เครื่องสถานะศัพท์ง่ายสำหรับการรับรู้โทเค็น
  7. วิธีอัตโนมัติของ Token:
    • สแกน - มีประโยชน์สำหรับความคิดเห็น: ความคิดเห็น: = "/ *" สแกน ("* /");
    • ลบ - มีประโยชน์สำหรับตัวระบุ: ตัวระบุ: = ลบ (IdentifierBody, คำหลัก);
      • ตรวจสอบให้แน่ใจว่าตัวระบุไม่ยอมรับคำหลัก
    • Encode - เข้ารหัสระบบอัตโนมัติเป็นจำนวนชุด X ของการเปลี่ยน N ฐาน
      • UnicodeEscape: = "\\ u" BaseEncode (IdentifierCharNoEscape, 16, 4);
        • ทำให้การหลบหนีแบบ Unicode เป็นเลขฐานสิบหกโดยมีการเปลี่ยนเป็นแบบ hex 4 จุด ความแตกต่างระหว่างสิ่งนี้และ: [0-9A-Fa-f] {4} คือการทำให้เป็นอัตโนมัติที่เกิดขึ้นพร้อม Encode จะ จำกัด ชุดค่าเลขฐานสิบหกที่อนุญาตให้อยู่ในขอบเขตของ IdentifierCharNoEscape ดังนั้นถ้าคุณให้มัน \ u005c เวอร์ชันการเข้ารหัสจะไม่ยอมรับค่า สิ่งนี้มีข้อแม้ที่ร้ายแรง: ใช้เท่าที่จำเป็น ระบบอัตโนมัติที่เกิดขึ้นอาจมีความซับซ้อนมาก

สิ่งที่ไม่ได้ดำเนินการคือการสร้าง CST ฉันต้องปรับระบบอัตโนมัติที่กำหนดไว้เพื่อดำเนินการตามบริบทที่เหมาะสมเพื่อให้การทำงานนี้เป็นไปได้

สำหรับทุกคนที่สนใจฉันได้อัปโหลดพิมพ์สวยของรูปแบบเดิมของ T * โครงการy♯ แต่ละไฟล์ควรเชื่อมโยงไปยังไฟล์อื่น ๆ ทั้งหมดฉันเริ่มที่จะเชื่อมโยงในกฏแต่ละข้อเพื่อติดตามพวกมัน แต่มันใช้เวลานานเกินไป (จะง่ายกว่าที่จะทำให้เป็นอัตโนมัติ!

หากต้องการบริบทเพิ่มเติมกรุณาโพสต์ตามความเหมาะสม

แก้ไข 5-14-2013 : ฉันได้เขียนโค้ดเพื่อสร้างกราฟ GraphViz สำหรับเครื่องสถานะภายในภาษาที่กำหนด นี่คือเดี่ยว GraphViz ของ AssemblyPart สมาชิกที่เชื่อมโยงในคำอธิบายภาษาควรมี rulename.txt ในโฟลเดอร์ที่สัมพันธ์กับ digraph สำหรับกฎนั้น คำอธิบายภาษาบางส่วนมีการเปลี่ยนแปลงตั้งแต่ฉันโพสต์ตัวอย่างนี้เกิดจากการทำให้สิ่งที่เกี่ยวกับไวยากรณ์ง่ายขึ้น ที่นี่เป็นที่น่าสนใจภาพ Graphviz


8
ข้อความของวอลล์ อย่าใช้วิธีนี้ผิดฉันขอขอบคุณสำหรับปัญหาที่อธิบายอย่างละเอียด ในกรณีนี้มันเป็นเพียง verbose น้อยเกินไป จากสิ่งที่ฉันรวบรวมคุณกำลังถามว่าคุณลักษณะใดที่ควรรวมอยู่ในตัวแยกวิเคราะห์ไวยากรณ์หรือวิธีสร้างโดยไม่เริ่มต้นจากศูนย์? โปรดแก้ไขเพื่อตอบคำถามต่อไปนี้ (คุณไม่จำเป็นต้องเขียนใหม่เพียงแค่ต่อท้ายโดยสรุป): ปัญหาของคุณคืออะไร คุณมีข้อ จำกัด อะไรบ้างในการแก้ไขปัญหาของคุณที่อาจเกิดขึ้น (ต้องเร็วต้องเป็น LL * เป็นต้น)
Neil

1
ฉันขอข้อมูลเชิงลึกเกี่ยวกับชุดคุณลักษณะ โฟกัสอยู่ที่การใช้งานง่าย ความยากลำบากอยู่ที่การรับคนที่ไม่รู้จักโครงการทำความเข้าใจกับโครงการเพื่อให้พวกเขาได้รับข้อมูลเกี่ยวกับจุดสนใจ ฉันไม่ได้ถามว่า 'ต้องทำอย่างไร' ฉันกำลังขอให้เกี่ยวข้องกับการใช้งาน ข้อเสนอแนะเกี่ยวกับวิธีการตัดคำถามที่ได้รับการชื่นชม
Allen Clark Copeland Jr

1
สำหรับฉันมันไม่ชัดเจนว่าโครงการเกี่ยวกับอะไร ตัวอย่างเช่นตั้งแต่ยุคของ yacc เราได้เห็นตัวแยกวิเคราะห์มากมาย OILexer ของคุณต่างกันอย่างไร ใหม่คืออะไร
Ingo

1
เป้าหมายของโครงการนี้คือการทำให้การแยกวิเคราะห์ง่ายขึ้น ใช่ไปยัง YACC / Bison และ FLEX / LEX ความแตกต่างที่สำคัญคือการหลีกเลี่ยงความซับซ้อนที่เกี่ยวข้องในโปรแกรมเหล่านั้น การทำให้สิ่งต่าง ๆ ง่ายและตรงประเด็นคือเป้าหมายหลัก นี่คือเหตุผลที่ฉันสร้างรูปแบบที่ปราศจากการแบ่งส่วนแบบแปลก ๆ แต่เป้าหมายคือการทำให้มันคล้ายกับการเขียนโปรแกรมปกติ: เฉพาะสำหรับการพัฒนาภาษาเท่านั้น โทเค็นถูกกำหนดโดยใช้ ': =' หลังจากชื่อของพวกเขากฎจะถูกกำหนดโดยใช้ :: = หลังจากชื่อของพวกเขา เทมเพลตใช้ '<' และ '>' สำหรับอาร์กิวเมนต์ตามด้วย ":: =" เนื่องจากมีการแชร์ไวยากรณ์กฎ
Allen Clark Copeland Jr

3
การมุ่งเน้นที่การแยกวิเคราะห์แบบชั่วร้ายนี้ดูเหมือนผิดไป มันเป็นปัญหาที่แก้ไขได้ดีและแทบจะไม่บุบสิ่งที่คุณต้องการในการประมวลผลภาษาโปรแกรม Google สำหรับบทความของฉันเกี่ยวกับ "ชีวิตหลังการแจง"
Ira Baxter

คำตอบ:


5

นี่เป็นคำถามที่ยอดเยี่ยม

ฉันได้ทำงานในการแยกวิเคราะห์จำนวนมากเมื่อเร็ว ๆ นี้และ IMHO บางส่วนของคุณสมบัติที่สำคัญคือ:

  • API เชิงโปรแกรม - ดังนั้นจึงสามารถใช้งานได้จากภายในภาษาการเขียนโปรแกรมโดยเพียงแค่นำเข้าไลบรารี มันสามารถมี GUI หรืออินเทอร์เฟซเหมือน BNF ได้เช่นกัน แต่โปรแกรมแบบเป็นกุญแจสำคัญเพราะคุณสามารถใช้เครื่องมือ, IDE, การวิเคราะห์แบบคงที่, การทดสอบ, สิ่งอำนวยความสะดวกด้านภาษา, ความคุ้นเคยของโปรแกรมเมอร์, เครื่องมือสร้างเอกสาร, กระบวนการสร้าง เป็นต้นนอกจากนี้คุณสามารถเล่นกับ parsers เล็ก ๆ แบบโต้ตอบซึ่งช่วยลดเส้นโค้งการเรียนรู้ เหตุผลเหล่านี้วางไว้ที่ด้านบนของรายการ "คุณสมบัติที่สำคัญ" ของฉัน

  • การรายงานข้อผิดพลาดตามที่ @guysherman พูดถึง เมื่อพบข้อผิดพลาดฉันต้องการทราบว่าข้อผิดพลาดนั้นอยู่ที่ใดและเกิดอะไรขึ้นเมื่อเกิดข้อผิดพลาด น่าเสียดายที่ฉันไม่สามารถค้นหาแหล่งข้อมูลที่ดีสำหรับการอธิบายวิธีการสร้างข้อผิดพลาดที่เหมาะสมเมื่อมีการย้อนรอยเล่น (แม้ว่าหมายเหตุ @ ความคิดเห็นของ Sk-logic ด้านล่าง)

  • ผลลัพธ์บางส่วน เมื่อการวิเคราะห์คำล้มเหลวฉันต้องการเห็นสิ่งที่แยกวิเคราะห์ได้สำเร็จจากส่วนของอินพุตที่อยู่ก่อนตำแหน่งของข้อผิดพลาด

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

  • ฉันเห็นด้วยกับ # 2 ของคุณ (การคาดการณ์ล่วงหน้า) ฉันคิดว่ามันช่วยในการสร้างรายงานข้อผิดพลาดที่ดี มันมีประโยชน์สำหรับสิ่งอื่นใดอีกหรือไม่?

  • การสนับสนุนสำหรับการสร้างต้นไม้แยกเป็นแยกเกิดขึ้นอาจจะ:

    • แผนผังไวยากรณ์ที่เป็นรูปธรรมซึ่งโครงสร้างของทรีสอดคล้องกับไวยากรณ์โดยตรงและรวมถึงข้อมูลเลย์เอาต์สำหรับการรายงานข้อผิดพลาดของเฟสในภายหลัง ในกรณีนี้ลูกค้าไม่ควรทำอะไรเพื่อให้ได้โครงสร้างต้นไม้ที่เหมาะสม - มันควรขึ้นอยู่กับไวยากรณ์โดยตรง
    • ต้นไม้ไวยากรณ์ที่เป็นนามธรรม ในกรณีนี้ผู้ใช้สามารถเล่นซอกับต้นไม้ใด ๆ และแยกทั้งหมด
  • การบันทึกบางชนิด ฉันไม่แน่ใจเกี่ยวกับอันนี้; อาจแสดงร่องรอยของกฎที่ parser ได้ลองหรือติดตามโทเค็นขยะเช่นช่องว่างหรือความคิดเห็นในกรณี (ตัวอย่าง) คุณต้องการใช้โทเค็นเพื่อสร้างเอกสาร HTML

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

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

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


ฉันได้แก้ไขเนื้อหาคำถามเพื่อรวมลิงค์ไปยัง PrecedenceHelper ในหัวข้อย่อยที่อ่าน 'เทมเพลต' อนุญาตให้พารามิเตอร์อาร์เรย์ tuples ดังนั้นหากคุณมีสี่พารามิเตอร์แต่ละพารามิเตอร์อาร์เรย์จะต้องใช้แม่แบบในชุดอาร์กิวเมนต์สี่
Allen Clark Copeland Jr

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

ฉันได้แก้ไขคำถามอีกครั้งในหัวข้อของฟังก์ชันในตัวที่ใช้งานได้
Allen Clark Copeland Jr

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

1
ฉันพบวิธีการหนึ่งที่มีประโยชน์อย่างยิ่งสำหรับการรายงานข้อผิดพลาดด้วยการย้อนรอยไม่สิ้นสุด (Packrat): กฎการผลิตแต่ละรายการมีหมายเหตุกำกับข้อผิดพลาด (ใช้คำว่า "blah-blah-blah คาดว่า") และเมื่อความล้มเหลว เป็นโทเค็นที่บันทึกความจำ หากความล้มเหลวทั้งหมดไม่สามารถกู้คืนได้ (การแยกวิเคราะห์ถูกยกเลิกก่อนถึงจุดสิ้นสุดของสตรีม) ข้อความแสดงข้อผิดพลาดทางขวาสุด (หรือชุดของข้อความดังกล่าว) จะเหมาะสมที่สุด นั่นเป็นสิ่งที่ง่ายที่สุดที่จะทำแน่นอนว่ามีวิธีในการปรับแต่งเพิ่มเติมพร้อมคำอธิบายเพิ่มเติม
SK-logic

5

ฉันไม่ได้มีประสบการณ์ในการออกแบบภาษา แต่ฉันเคยเขียน parser สักครั้งเมื่อฉันสร้างและ IDE สำหรับเอ็นจิ้นเกม

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

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

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


นี่คือสิ่งหนึ่งที่ฉันวางแผนจะทำ เพื่อช่วยในเรื่องความรู้เกี่ยวกับโดเมนของฉันเพื่อนคนหนึ่งของฉันแนะนำให้เขียนโปรแกรมแยกวิเคราะห์จริงด้วยมือเพื่อหยุดการทำงานอัตโนมัติ สิ่งหนึ่งที่ฉันรู้ได้อย่างรวดเร็วคือตัวแยกวิเคราะห์มีความซับซ้อนและมีสิ่งที่เราทำด้วยมือซึ่งทำให้กระบวนการง่ายขึ้น กฎและเทมเพลตใช้ไวยากรณ์เดียวกัน อย่างไรก็ตามมีองค์ประกอบภาษาที่ถูกต้องในเทมเพลต แต่ไม่ใช่กฎมีสถานะภายในที่จัดการงานนี้ สิ่งที่นำมาสู่ความคิด: กฎควรจะสามารถระบุเส้นทางโรคเอดส์เพื่อให้การแบ่งกฎย่อยง่ายขึ้น
Allen Clark Copeland Jr

... สิ่งนี้ควรจะง่ายต่อการดำเนินการในระบบอัตโนมัติ แต่จะต้องมีระบบอัตโนมัติที่จะมีเงื่อนไขตามรัฐ ฉันจะทำงานกับเรื่องนี้และกลับไปหาคุณ ANTLR ใช้การทำงานอัตโนมัติแบบ จำกัด ของรัฐเพื่อจัดการวงจรการพูดว่า: "T" * ซึ่งฉันจะใช้มันเพื่อจัดการกระบวนการวิเคราะห์ส่วนใหญ่เนื่องจากการลดลงควรจะสะอาดกว่าในขณะที่สหรัฐฯมี 800+ รูปแบบในกฎ เร็วที่สุดเท่ารหัสสปาเก็ตตี้ในรูปแบบมาตรฐานถ้า / อื่น ๆ )
Allen Clark Copeland Jr

0

ไวยากรณ์ต้องไม่มีข้อ จำกัด เช่น "ไม่มีกฎแบบเรียกซ้ำ" มันเป็นเรื่องน่าขันว่าเครื่องมือใช้กันอย่างแพร่หลายในวันนี้มีเพียงนี้และสามารถเข้าใจดูดไวยากรณ์ LL - เกือบ 50 ปีหลังจากyaccทำมันขวา

ตัวอย่างสำหรับการเรียกซ้ำที่ถูกต้อง (ใช้ไวยากรณ์ yacc):

list: 
      elem                  { $$ = singleton($1); }
    | elem ',' list         { $$ = cons($1, $2);  }
    ;

ตัวอย่างสำหรับการเรียกซ้ำทางซ้าย (ใช้ yacc synatx):

funapp:
    term                    { $$ = $1; }
    | funapp term           { $$ = application($1, $2); }
    ;

ตอนนี้อาจจะ "refactored" กับสิ่งอื่น แต่ในทั้งสองกรณีการเรียกซ้ำแบบเฉพาะเป็นเพียงวิธี "ถูกต้อง" ในการเขียนสิ่งนี้เนื่องจากรายการ (ในภาษาตัวอย่าง) จะถูกเรียกซ้ำในขณะที่ฟังก์ชันของโปรแกรมประยุกต์ถูกเรียกซ้ำ .

หนึ่งสามารถคาดหวังจากเครื่องมือขั้นสูงที่พวกเขาสนับสนุนวิธีที่เป็นธรรมชาติในการเขียนข้อมูลลงแทนที่จะต้องมีหนึ่งในการ "refactor" ทุกอย่างที่จะซ้าย / ขวา recursive รูปแบบเครื่องมือที่กำหนดลงบนหนึ่ง


ใช่มันเป็นเรื่องดีที่จะไม่มีข้อ จำกัด ตามอำเภอใจเช่นนั้น อย่างไรก็ตามตัวอย่างของการเรียกซ้ำทางซ้ายที่ไม่สามารถแทนที่ด้วยโอเปอเรเตอร์การทำซ้ำ (เช่น regexes *หรือ+quantifiers) คืออะไร ฉันยอมรับอย่างอิสระว่าความรู้ของฉันในพื้นที่นี้มี จำกัด แต่ฉันไม่เคยพบเจอกับการใช้การเรียกซ้ำทางซ้ายที่ไม่สามารถ refactored ในการทำซ้ำ และฉันก็พบว่าเวอร์ชันการทำซ้ำมีความชัดเจนมากขึ้นเช่นกัน (แม้ว่าจะเป็นเพียงการตั้งค่าส่วนตัว)

1
@MattFenwick ดูการแก้ไขของฉัน สังเกตวิธีที่ directy ไวยากรณ์นำไปสู่การกระทำ semantic ที่ง่ายและเป็นธรรมชาติ (เช่น) สำหรับการสร้างแผนผังไวยากรณ์ ในขณะที่มีการทำซ้ำ (ซึ่งไม่สามารถใช้ได้ใน yacc, btw) ฉันคิดว่าคุณมักจะต้องตรวจสอบว่าคุณมีรายการว่างเปล่าซิงเกิล ฯลฯ
Ingo

ขอบคุณสำหรับคำตอบ ฉันคิดว่าฉันเข้าใจดีขึ้นในขณะนี้ - ฉันต้องการเขียนตัวอย่างเหล่านั้นเป็นlist = sepBy1(',', elem)และfunapp = term{+}(และแน่นอนsepBy1และ+จะถูกนำไปใช้ในแง่ของการเรียกซ้ำซ้าย / ขวา / และสร้างต้นไม้ไวยากรณ์มาตรฐาน) ดังนั้นไม่ใช่ว่าฉันคิดว่าการเรียกซ้ำซากซ้ายและขวานั้นแย่ฉันแค่รู้สึกว่าพวกมันอยู่ในระดับต่ำและต้องการใช้สิ่งที่เป็นนามธรรมในระดับที่สูงกว่าหากเป็นไปได้เพื่อทำให้สิ่งต่าง ๆ ชัดเจนขึ้น ขอบคุณอีกครั้ง!

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