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

ขั้นตอนทั้งหมดเหล่านี้จะแปลงซอร์สโค้ดโดยแบ่งออกเป็นโทเค็น การสร้างแผนผังการแยกวิเคราะห์ และเพิ่มประสิทธิภาพซอร์สโค้ดตามเฟสต่างๆ
ระยะที่ 1: การวิเคราะห์คำศัพท์
การวิเคราะห์คำศัพท์เป็นระยะแรกที่คอมไพเลอร์สแกนซอร์สโค้ด กระบวนการนี้สามารถจากซ้ายไปขวา ทีละอักขระ และจัดกลุ่มอักขระเหล่านี้เป็นโทเค็น
ในที่นี้ สตรีมอักขระจากโปรแกรมต้นทางจะถูกจัดกลุ่มตามลำดับที่มีความหมายโดยการระบุโทเค็น โดยจะทำการป้อนตั๋วที่เกี่ยวข้องลงในตารางสัญลักษณ์และส่งโทเค็นนั้นไปยังเฟสถัดไป
หน้าที่หลักของเฟสนี้คือ:
- ระบุหน่วยคำศัพท์ในซอร์สโค้ด
- จำแนกหน่วยคำศัพท์ออกเป็นคลาสต่างๆ เช่น ค่าคงที่ คำสงวน และป้อนลงในตารางต่างๆ มันจะไม่สนใจความคิดเห็นในโปรแกรมต้นฉบับ
- ระบุโทเค็นที่ไม่ได้เป็นส่วนหนึ่งของภาษา
ตัวอย่าง:
x = y + 10
ราชสกุล
X | ระบุ |
= | ตัวดำเนินการมอบหมาย |
Y | ระบุ |
+ | ตัวดำเนินการเพิ่มเติม |
10 | จำนวน |
ขั้นตอนที่ 2: การวิเคราะห์ไวยากรณ์
การวิเคราะห์ไวยากรณ์เป็นเรื่องเกี่ยวกับการค้นหาโครงสร้างในโค้ด จะกำหนดว่าข้อความเป็นไปตามรูปแบบที่คาดหวังหรือไม่ จุดประสงค์หลักของระยะนี้คือเพื่อให้แน่ใจว่าซอร์สโค้ดที่เขียนโดยโปรแกรมเมอร์นั้นถูกต้องหรือไม่
การวิเคราะห์ไวยากรณ์จะขึ้นอยู่กับกฎที่อิงตามภาษาโปรแกรมเฉพาะโดยการสร้างแผนผังการแยกวิเคราะห์ด้วยความช่วยเหลือของโทเค็น นอกจากนี้ยังกำหนดโครงสร้างของภาษาต้นฉบับและไวยากรณ์หรือไวยากรณ์ของภาษาด้วย
นี่คือรายการงานที่ดำเนินการในระยะนี้:
- รับโทเค็นจากตัววิเคราะห์คำศัพท์
- ตรวจสอบว่านิพจน์มีความถูกต้องทางวากยสัมพันธ์หรือไม่
- รายงานข้อผิดพลาดทางไวยากรณ์ทั้งหมด
- สร้างโครงสร้างลำดับชั้นซึ่งเรียกว่าโครงสร้างการแยกวิเคราะห์
ตัวอย่าง
ตัวระบุ/หมายเลขใดๆ ถือเป็นนิพจน์
ถ้า x เป็นตัวระบุ และ y+10 เป็นนิพจน์ ดังนั้น x= y+10 จะเป็นคำสั่ง
พิจารณาการแยกวิเคราะห์ต้นไม้สำหรับตัวอย่างต่อไปนี้
(a+b)*c
ในต้นไม้พาร์ส
- โหนดภายใน: บันทึกด้วยไฟล์ตัวดำเนินการและไฟล์สองไฟล์สำหรับเด็ก
- Leaf: บันทึกที่มี 2 ช่องขึ้นไป หนึ่งอันสำหรับโทเค็นและข้อมูลอื่น ๆ เกี่ยวกับโทเค็น
- ตรวจสอบให้แน่ใจว่าองค์ประกอบของโปรแกรมเข้ากันได้อย่างมีความหมาย
- รวบรวมข้อมูลประเภทและตรวจสอบความเข้ากันได้ของประเภท
- ตรวจสอบว่าตัวดำเนินการได้รับอนุญาตจากภาษาต้นฉบับหรือไม่
ระยะที่ 3: การวิเคราะห์เชิงความหมาย
การวิเคราะห์เชิงความหมายจะตรวจสอบความสอดคล้องเชิงความหมายของโค้ด ใช้แผนผังไวยากรณ์ของเฟสก่อนหน้าพร้อมกับตารางสัญลักษณ์เพื่อตรวจสอบว่าซอร์สโค้ดที่กำหนดมีความสอดคล้องทางความหมาย นอกจากนี้ยังตรวจสอบว่าโค้ดสื่อความหมายที่เหมาะสมหรือไม่
Semantic Analyzer จะตรวจสอบความไม่ตรงกันของประเภท ตัวดำเนินการที่เข้ากันไม่ได้ ฟังก์ชันที่เรียกด้วยอาร์กิวเมนต์ที่ไม่เหมาะสม ตัวแปรที่ไม่ได้ประกาศ ฯลฯ
หน้าที่ของขั้นตอนการวิเคราะห์ความหมายคือ:
- ช่วยให้คุณจัดเก็บข้อมูลประเภทที่รวบรวมและบันทึกไว้ในตารางสัญลักษณ์หรือแผนผังไวยากรณ์
- ช่วยให้คุณสามารถดำเนินการตรวจสอบประเภทได้
- ในกรณีที่มีประเภทไม่ตรงกัน ซึ่งไม่มีกฎการแก้ไขประเภทที่แน่นอนที่ตอบสนองการดำเนินการที่ต้องการ จะแสดงข้อผิดพลาดด้านความหมาย
- รวบรวมข้อมูลประเภทและตรวจสอบความเข้ากันได้ของประเภท
- ตรวจสอบว่าภาษาต้นฉบับอนุญาตให้ใช้ตัวดำเนินการหรือไม่
ตัวอย่าง
float x = 20.2; float y = x*30;
ในโค้ดข้างต้น ตัววิเคราะห์ความหมายจะพิมพ์จำนวนเต็ม 30 ให้ลอย 30.0 ก่อนการคูณ
ขั้นตอนที่ 4: การสร้างรหัสระดับกลาง
เมื่อขั้นตอนการวิเคราะห์เชิงความหมายอยู่เหนือคอมไพลเลอร์แล้ว ให้สร้างโค้ดระดับกลางสำหรับเครื่องเป้าหมาย เป็นโปรแกรมสำหรับเครื่องนามธรรมบางเครื่อง
รหัสระดับกลางอยู่ระหว่างภาษาระดับสูงและระดับเครื่อง โค้ดระดับกลางนี้จำเป็นต้องสร้างขึ้นในลักษณะที่ทำให้ง่ายต่อการแปลเป็นโค้ดเครื่องเป้าหมาย
ฟังก์ชั่นในการสร้างรหัสระดับกลาง:
- ควรสร้างขึ้นจากการแสดงความหมายของซอร์สโปรแกรม
- เก็บค่าที่คำนวณระหว่างกระบวนการแปล
- ช่วยให้คุณแปลโค้ดระดับกลางเป็นภาษาเป้าหมาย
- ช่วยให้คุณรักษาลำดับความสำคัญของภาษาต้นฉบับได้
- มันถือจำนวนตัวดำเนินการของคำสั่งที่ถูกต้อง
ตัวอย่าง
ตัวอย่างเช่น
total = count + rate * 5
รหัสระดับกลางโดยใช้วิธีรหัสที่อยู่คือ:
t1 := int_to_float(5) t2 := rate * t1 t3 := count + t2 total := t3
ขั้นตอนที่ 5: การเพิ่มประสิทธิภาพโค้ด
ขั้นตอนต่อไปคือการเพิ่มประสิทธิภาพโค้ดหรือโค้ดระดับกลาง ระยะนี้จะลบบรรทัดโค้ดที่ไม่จำเป็นออก และจัดเรียงลำดับของคำสั่งเพื่อเร่งการทำงานของโปรแกรมโดยไม่เปลืองทรัพยากร เป้าหมายหลักของระยะนี้คือการปรับปรุงโค้ดระดับกลางเพื่อสร้างโค้ดที่ทำงานเร็วขึ้นและใช้พื้นที่น้อยลง
หน้าที่หลักของเฟสนี้คือ:
- ช่วยให้คุณสร้างการแลกเปลี่ยนระหว่างความเร็วในการประมวลผลและความเร็วในการคอมไพล์
- ปรับปรุงเวลาการทำงานของโปรแกรมเป้าหมาย
- สร้างโค้ดที่มีความคล่องตัวซึ่งยังคงอยู่ในการแสดงระดับกลาง
- การลบโค้ดที่ไม่สามารถเข้าถึงได้และกำจัดตัวแปรที่ไม่ได้ใช้
- การลบคำสั่งที่ไม่ได้รับการแก้ไขออกจากลูป
ตัวอย่าง:
ลองพิจารณาโค้ดต่อไปนี้
a = intofloat(10) b = c * a d = e + b f = d
สามารถกลายเป็น
b =c * 10.0 f = e+b
ขั้นตอนที่ 6: การสร้างโค้ด
การสร้างโค้ดเป็นขั้นตอนสุดท้ายและขั้นตอนสุดท้ายของคอมไพเลอร์ รับอินพุตจากขั้นตอนการเพิ่มประสิทธิภาพโค้ดและสร้างโค้ดเพจหรือโค้ดอ็อบเจ็กต์ตามผลลัพธ์ วัตถุประสงค์ของระยะนี้คือการจัดสรรพื้นที่เก็บข้อมูลและสร้างรหัสเครื่องที่ย้ายตำแหน่งได้
นอกจากนี้ยังจัดสรรตำแหน่งหน่วยความจำสำหรับตัวแปรด้วย คำแนะนำในโค้ดระดับกลางจะถูกแปลงเป็นคำสั่งเครื่อง ระยะนี้ครอบคลุมโค้ดเพิ่มประสิทธิภาพหรือโค้ดระดับกลางเป็นภาษาเป้าหมาย
ภาษาเป้าหมายคือรหัสเครื่อง ดังนั้น ตำแหน่งหน่วยความจำและรีจิสเตอร์ทั้งหมดจึงถูกเลือกและจัดสรรในระหว่างระยะนี้ด้วย รหัสที่สร้างโดยเฟสนี้จะถูกดำเนินการเพื่อรับอินพุตและสร้างเอาต์พุตที่คาดหวัง
ตัวอย่าง
ก = ข + 60.0
อาจจะแปลเป็นทะเบียนได้
MOVF a, R1 MULF #60.0, R2 ADDF R1, R2
การจัดการตารางสัญลักษณ์
ตารางสัญลักษณ์ประกอบด้วยบันทึกสำหรับตัวระบุแต่ละตัวพร้อมช่องสำหรับแอตทริบิวต์ของตัวระบุ ส่วนประกอบนี้ช่วยให้คอมไพเลอร์ค้นหาบันทึกตัวระบุและดึงข้อมูลได้อย่างรวดเร็วยิ่งขึ้น ตารางสัญลักษณ์ยังช่วยคุณในการจัดการขอบเขตอีกด้วย ตารางสัญลักษณ์และตัวจัดการข้อผิดพลาดโต้ตอบกับเฟสทั้งหมดและการอัปเดตตารางสัญลักษณ์ตามลำดับ
เกิดข้อผิดพลาดในการจัดการกิจวัตร
ในขั้นตอนการออกแบบคอมไพลเลอร์อาจเกิดข้อผิดพลาดในทุกขั้นตอนด้านล่าง:
- ตัววิเคราะห์คำศัพท์: โทเค็นสะกดผิด
- ตัววิเคราะห์ไวยากรณ์: ไม่มีวงเล็บ
- เครื่องกำเนิดโค้ดระดับกลาง: ตัวดำเนินการที่ไม่ตรงกันสำหรับตัวดำเนินการ
- เครื่องมือเพิ่มประสิทธิภาพโค้ด: เมื่อไม่สามารถเข้าถึงคำสั่งได้
- รหัส Generator: เมื่อหน่วยความจำเต็มหรือการลงทะเบียนที่เหมาะสมจะไม่ได้รับการจัดสรร
- ตารางสัญลักษณ์: ข้อผิดพลาดของตัวระบุที่ประกาศหลายรายการ
ข้อผิดพลาดที่พบบ่อยที่สุดคือลำดับอักขระที่ไม่ถูกต้องในการสแกน ลำดับโทเค็นที่ไม่ถูกต้องในประเภท ข้อผิดพลาดของขอบเขต และการแยกวิเคราะห์ในการวิเคราะห์เชิงความหมาย
ข้อผิดพลาดอาจเกิดขึ้นในขั้นตอนใดๆ ข้างต้น หลังจากพบข้อผิดพลาดแล้ว ขั้นตอนจะต้องจัดการกับข้อผิดพลาดเพื่อดำเนินกระบวนการคอมไพล์ต่อไป ข้อผิดพลาดเหล่านี้จำเป็นต้องรายงานไปยังตัวจัดการข้อผิดพลาดซึ่งจัดการข้อผิดพลาดเพื่อดำเนินการกระบวนการคอมไพล์ โดยทั่วไปข้อผิดพลาดจะถูกรายงานในรูปแบบของข้อความ
สรุป
- คอมไพเลอร์ทำงานในเฟสต่างๆ โดยแต่ละเฟสจะแปลงโปรแกรมต้นฉบับจากการแสดงผลแบบหนึ่งไปยังอีกแบบหนึ่ง
- หกขั้นตอนของ การออกแบบคอมไพเลอร์ 1) การวิเคราะห์คำศัพท์ 2) การวิเคราะห์ไวยากรณ์ 3) การวิเคราะห์ความหมาย 4) เครื่องสร้างโค้ดระดับกลาง 5) ตัวเพิ่มประสิทธิภาพโค้ด 6) โค้ด Generator
- การวิเคราะห์คำศัพท์เป็นระยะแรกที่คอมไพเลอร์สแกนซอร์สโค้ด
- การวิเคราะห์ไวยากรณ์เป็นเรื่องเกี่ยวกับการค้นพบโครงสร้างในข้อความ
- การวิเคราะห์เชิงความหมายจะตรวจสอบความสอดคล้องเชิงความหมายของโค้ด
- เมื่อขั้นตอนการวิเคราะห์เชิงความหมายอยู่เหนือคอมไพลเลอร์แล้ว ให้สร้างโค้ดระดับกลางสำหรับเครื่องเป้าหมาย
- ขั้นตอนการเพิ่มประสิทธิภาพโค้ดจะลบบรรทัดโค้ดที่ไม่จำเป็นและจัดเรียงลำดับของคำสั่ง
- ขั้นตอนการสร้างโค้ดได้รับอินพุตจากขั้นตอนการเพิ่มประสิทธิภาพโค้ดและสร้างโค้ดเพจหรือโค้ดอ็อบเจ็กต์ตามผลลัพธ์
- ตารางสัญลักษณ์ประกอบด้วยบันทึกสำหรับตัวระบุแต่ละตัวพร้อมช่องสำหรับแอตทริบิวต์ของตัวระบุ
- การจัดการข้อผิดพลาดตามปกติจะจัดการกับข้อผิดพลาดและรายงานในระหว่างหลายขั้นตอน