← กลับไปยังบทความทั้งหมด

Preprocessor คืออะไร? ทำความรู้จักกับโปรแกรมประมวลผลล่วงหน้า

Preprocessor คืออะไร? ทำความรู้จักกับโปรแกรมประมวลผลล่วงหน้า ในทางวิทยาการคอมพิวเตอร์ Preprocessor (หรือ Precompiler) คือโปรแกรมที่ทำหน้าที่ประมวลผลข้อมูลนำเข้า (Input) เพื่อสร้างผลลัพธ์ (Output) ซึ่งจะถูกนำไปใช้เป็น

สรุปใจความสำคัญ

  • Preprocessor คือโปรแกรมที่เตรียมข้อมูลนำเข้าให้อยู่ในรูปแบบที่เหมาะสมก่อนจะส่งต่อไปยังโปรแกรมอื่น เช่น คอมไพเลอร์
  • Lexical Preprocessor ทำงานในระดับข้อความ (Text) โดยเน้นการแทนที่ Token และการรวมไฟล์
  • Syntactic Preprocessor ทำงานในระดับโครงสร้างไวยากรณ์ (Syntax Tree) ช่วยให้สามารถสร้างภาษาเฉพาะทาง (DSL) ภายในภาษาหลักได้

ในทางวิทยาการคอมพิวเตอร์ Preprocessor (หรือ Precompiler) คือโปรแกรมที่ทำหน้าที่ประมวลผลข้อมูลนำเข้า (Input) เพื่อสร้างผลลัพธ์ (Output) ซึ่งจะถูกนำไปใช้เป็นข้อมูลนำเข้าสำหรับโปรแกรมอื่นต่อไป โดยทั่วไปแล้ว ผลลัพธ์ที่ได้จะถูกเรียกว่า "รูปแบบที่ผ่านการประมวลผลล่วงหน้า" (Preprocessed form) ซึ่งมักจะถูกส่งต่อไปยังโปรแกรมถัดไป เช่น คอมไพเลอร์ (Compiler)

ระดับและความซับซ้อนของการประมวลผลจะขึ้นอยู่กับประเภทของ Preprocessor บางตัวอาจทำหน้าที่เพียงแค่การแทนที่ข้อความง่ายๆ (Textual substitutions) และการขยายแมโคร (Macro expansions) ในขณะที่บางตัวมีความสามารถสูงเทียบเท่ากับภาษาโปรแกรมเต็มรูปแบบ

ประเภทของ Preprocessor

Preprocessor สามารถแบ่งออกเป็นประเภทหลักๆ ตามระดับของการทำงานได้ดังนี้:

1. Lexical Preprocessors (ตัวประมวลผลเชิงคำศัพท์)

เป็น Preprocessor ระดับต่ำที่สุด เนื่องจากต้องการเพียงการวิเคราะห์เชิงคำศัพท์ (Lexical analysis) โดยจะทำงานกับข้อความต้นฉบับก่อนที่จะมีการ Parse โดยการแทนที่ลำดับตัวอักษรที่ถูก Tokenize ตามกฎที่ผู้ใช้กำหนด

  • หน้าที่หลัก: การแทนที่แมโคร (Macro substitution), การรวมไฟล์ (Textual inclusion), และการคอมไพล์แบบมีเงื่อนไข (Conditional compilation)
  • ตัวอย่างที่ชัดเจน: C Preprocessor ซึ่งจะประมวลผลบรรทัดที่เริ่มต้นด้วยเครื่องหมาย # (Directives) โดยที่ C Preprocessor ไม่จำเป็นต้องเข้าใจไวยากรณ์ของภาษา C ในการทำงาน

ในบางภาษาโปรแกรมอาจใช้ฟีเจอร์ภายในแทนการใช้ Lexical Preprocessor เช่น การใช้ Inlining และ Templates แทนแมโคร หรือการใช้ Compile-time imports แทนการรวมไฟล์

2. Syntactic Preprocessors (ตัวประมวลผลเชิงไวยากรณ์)

ถูกนำมาใช้ครั้งแรกในตระกูลภาษา Lisp โดยมีหน้าที่ในการแปลง Syntax Trees ตามกฎที่ผู้ใช้กำหนด ซึ่งอาจเขียนด้วยภาษาเดียวกันกับโปรแกรม (Compile-time reflection) เช่นใน Lisp และ OCaml หรือใช้ภาษาภายนอก เช่น XSLT สำหรับ XML

Syntactic Preprocessors มักถูกนำมาใช้เพื่อ:

  • ปรับแต่งไวยากรณ์ (Customizing Syntax): เช่น ในภาษา Objective Caml ที่สามารถเขียนได้ทั้งแบบ "Normal syntax" และ "Revised syntax"
  • ขยายความสามารถของภาษา (Extending a Language): เช่น ในตระกูล Lisp ที่ใช้แมโครเพื่อเพิ่มความสามารถในการเขียนโปรแกรมแบบ Imperative หรือ Object-oriented ลงในแกนกลางที่เป็น Functional
  • สร้างภาษาเฉพาะทาง (Specializing a Language): การสร้าง Internal DSL (Domain-Specific Language) เช่น แมโคร LOOP ใน Common Lisp ที่สร้างภาษาขนาดเล็กสำหรับจัดการการวนซ้ำที่ซับซ้อน

General Purpose Preprocessor (ตัวประมวลผลล่วงหน้าอเนกประสงค์)

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

ตัวอย่างที่โดดเด่นที่สุดคือ M4 ซึ่งเป็นที่รู้จักอย่างกว้างขวางในระบบ Build system ข้ามแพลตฟอร์ม เช่น autoconf นอกจากนี้ C Preprocessor บางครั้งก็ถูกนำมาใช้ในงานที่ไม่เกี่ยวข้องกับภาษา C เช่น การประมวลผล JavaScript หรือการจัดการ Device Tree ภายใน Linux Kernel

คำถามที่พบบ่อย

C Preprocessor ทำงานอย่างไร?

C Preprocessor จะมองหาบรรทัดที่เริ่มต้นด้วยเครื่องหมาย # (Directives) และทำการแทนที่ข้อความหรือรวมไฟล์ตามคำสั่งนั้นๆ ก่อนที่โค้ดจะถูกส่งไปยังขั้นตอนการคอมไพล์จริง

ความแตกต่างระหว่าง Lexical และ Syntactic Preprocessor คืออะไร?

Lexical Preprocessor ทำงานกับข้อความดิบๆ (Raw text) โดยการแทนที่คำหรือข้อความ ส่วน Syntactic Preprocessor ทำงานกับโครงสร้างทางไวยากรณ์ (Syntax Tree) ซึ่งมีความซับซ้อนและทรงพลังมากกว่า

M4 คืออะไร?

M4 คือ General Purpose Preprocessor หรือตัวประมวลผลล่วงหน้าอเนกประสงค์ที่สามารถใช้จัดการข้อความได้หลากหลายรูปแบบ ไม่จำกัดเฉพาะภาษาโปรแกรมใดภาษาหนึ่ง