ขั้นตอนของคอมไพเลอร์พร้อมตัวอย่าง: กระบวนการและขั้นตอนการคอมไพล์

การออกแบบคอมไพเลอร์มีขั้นตอนอะไรบ้าง?

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

  1. การวิเคราะห์คำศัพท์
  2. การวิเคราะห์ไวยากรณ์
  3. การวิเคราะห์เชิงความหมาย
  4. เครื่องสร้างโค้ดระดับกลาง
  5. เครื่องมือเพิ่มประสิทธิภาพโค้ด
  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
  • การวิเคราะห์คำศัพท์เป็นระยะแรกที่คอมไพเลอร์สแกนซอร์สโค้ด
  • การวิเคราะห์ไวยากรณ์เป็นเรื่องเกี่ยวกับการค้นพบโครงสร้างในข้อความ
  • การวิเคราะห์เชิงความหมายจะตรวจสอบความสอดคล้องเชิงความหมายของโค้ด
  • เมื่อขั้นตอนการวิเคราะห์เชิงความหมายอยู่เหนือคอมไพลเลอร์แล้ว ให้สร้างโค้ดระดับกลางสำหรับเครื่องเป้าหมาย
  • ขั้นตอนการเพิ่มประสิทธิภาพโค้ดจะลบบรรทัดโค้ดที่ไม่จำเป็นและจัดเรียงลำดับของคำสั่ง
  • ขั้นตอนการสร้างโค้ดได้รับอินพุตจากขั้นตอนการเพิ่มประสิทธิภาพโค้ดและสร้างโค้ดเพจหรือโค้ดอ็อบเจ็กต์ตามผลลัพธ์
  • ตารางสัญลักษณ์ประกอบด้วยบันทึกสำหรับตัวระบุแต่ละตัวพร้อมช่องสำหรับแอตทริบิวต์ของตัวระบุ
  • การจัดการข้อผิดพลาดตามปกติจะจัดการกับข้อผิดพลาดและรายงานในระหว่างหลายขั้นตอน