2 คะแนน โดย GN⁺ 2024-11-09 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

แมโคร

  • แมโครของ Rust ใช้เพื่อลดการเขียนโค้ดซ้ำและลดงานที่ต้องทำซ้ำ
  • โหนดของประโยคใน sqleibniz ต้อง implement เทรต Node ซึ่งทำให้เกิดโค้ดซ้ำจำนวนมาก
  • สามารถใช้แมโครเพื่อทำให้การประกาศ struct และการ implement เทรต Node เป็นอัตโนมัติได้

แมโครสำหรับกำจัดโค้ดซ้ำ

  • แมโครทำหน้าที่ประกาศ struct, เพิ่มคอมเมนต์เอกสาร และ implement ฟังก์ชันที่ทำให้ตรงตามเทรต Node
  • แมโครสามารถเพิ่มฟิลด์ได้หลากหลายผ่านการประกาศ metavariable แบบทำซ้ำ

การทดสอบ

  • ใน Rust สามารถทำรูปแบบที่คล้ายกับ table-driven test ของ Go ได้
  • สามารถใช้แมโคร test_group_pass_assert! และ test_group_fail! เพื่อทดสอบคู่ของอินพุตและเอาต์พุตที่คาดหวังได้หลายแบบ

การทดสอบพาร์เซอร์

  • ในโมดูลพาร์เซอร์ก็ใช้แมโครลักษณะคล้ายกันเพื่อทดสอบผลลัพธ์ของคำสั่ง SQL
  • มีการใช้ฟังก์ชัน sql_stmt_prefix เพื่อทดสอบคำสั่ง SQL EXPLAIN

ข้อเสียของแมโคร

  • rust-analyzer ทำงานได้ไม่ดีภายในแมโคร และเอกสารประกอบก็ยังมีไม่มาก

การจับคู่ตัวอักษร

  • สามารถใช้แมโคร matches! ของ Rust เพื่อเปรียบเทียบตัวอักษรได้อย่างง่ายดาย
  • มีตัวอย่างการตรวจสอบว่าอักขระที่กำหนดเป็นตัวเลขแบบ SQLite หรือไม่

การจับคู่โทเค็น

  • หลังจาก lexer แปลงสตรีมของอักขระเป็นสตรีมของโทเค็นแล้ว พาร์เซอร์จะใช้สิ่งนั้นเพื่อสร้างต้นไม้ไวยากรณ์
  • ใช้คำสั่ง match เพื่อจดจำประเภทของโทเค็น

การแสดงข้อผิดพลาด

  • มีการจัดการข้อผิดพลาดเพื่อแสดงข้อความผิดพลาดที่ชัดเจนให้ผู้ใช้

ความสามารถแบบเลือกได้

  • ใช้ชนิด Option ของ Rust เพื่อตรวจสอบว่ามีค่าหรือไม่ รวมถึงเช็กเงื่อนไขหรือกำหนดค่าเริ่มต้นได้
  • ใช้เมธอดอย่าง is_some_and, map, map_or เพื่อให้อ่านโค้ดได้ง่ายขึ้น

ตัววนซ้ำ

  • ใช้ iterator ของ Rust เพื่อกรองอักขระและประมวลผลให้ตรงกับกฎการพาร์สตัวเลขของ SQLite

1 ความคิดเห็น

 
GN⁺ 2024-11-09
ความคิดเห็นบน Hacker News
  • ประสบปัญหาในการใช้ Rust เพราะ borrow checker และความยากของการจัดการหน่วยความจำ แม้จะชอบองค์ประกอบของการเขียนโปรแกรมเชิงฟังก์ชัน (FP) ใน Rust แต่ก็ตัดสินใจมองหาภาษาอื่น และพบว่า OCaml น่าพอใจ

  • ดูเหมือนจะยังมีประสบการณ์กับ Rust และแนวคิดด้าน PL ไม่มากนัก คิดว่าการกำหนด AST ด้วย algebraic data types จะง่ายกว่า ส่วนแมโครแม้จะทำงานต่างกันไปในแต่ละภาษา แต่โดยหลักแล้วใช้เพื่อลดโค้ดซ้ำและลดงานเขียนซ้ำๆ

  • พาร์เซอร์ที่เขียนด้วย Haskell โดดเด่นมากในแง่ความเรียบง่ายและความอ่านง่าย อ่านได้แทบจะเหมือน BNF และแทบไม่มีขั้นตอนเชิงเทคนิคมาบดบัง ทำให้โฟกัสกับไวยากรณ์จริงได้

  • เคยเขียนพาร์เซอร์ด้วย Ragel, Go, Java, C++, และ C มาก่อน การเขียน JSON parser ด้วย C อาจง่ายกว่าโค้ด Rust ก็ได้ โครงสร้างพื้นฐานของพาร์เซอร์พัฒนาไปมาก จนถึงจุดที่สามารถสร้างพาร์เซอร์ด้วย eBNF ได้

  • เคยเขียนตัว disassembler และ emulator ของ eBPF ด้วย Rust และคิดว่า Rust เหมาะกับงาน parsing อย่างไรก็ตาม การใช้แมโครให้ความรู้สึกต่างจากการทำงานภายในตัวภาษาเอง

  • ชอบบรรยายของ Rob Pike เรื่อง lexical scanning ใน Go มาก เป็นแนวทางที่ให้ความรู้และสง่างาม

  • สามารถใช้ไลบรารี parser combinator เพื่อดีพลอยพาร์เซอร์โปรโตคอลประสิทธิภาพสูงในสภาพแวดล้อมแบบ embedded ได้ และยังสามารถใช้ไลบรารีเดียวกันนี้เขียน embedded protocol parser ได้ด้วย

  • ตอนเขียนพาร์เซอร์ AST ทั้งชุดใน Rust พบว่าการแสดงลำดับชั้นของชนิด AST แบบเฉพาะเจาะจงทำได้ยาก ต้องใช้เทคนิคด้านชนิดข้อมูลแปลกๆ และแมโคร

  • การพาร์สไวยากรณ์ของ sqlite เป็นงานที่ยาก sqlite เป็นแหล่งแรงบันดาลใจที่ดี แผนภาพ railroad มีประโยชน์มาก และตัวสร้างพาร์เซอร์ Lemon ก็ยังไม่ได้รับการยอมรับเท่าที่ควร

  • ภาษาที่มี algebraic data types เหมาะกับการพาร์สไวยากรณ์ของ sqlite และ Typescript ก็อาจเป็นตัวเลือกที่ดีเช่นกัน มีการเขียนบทแนะนำสั้นๆ เกี่ยวกับวิธีเขียนพาร์เซอร์ด้วย Rust