วันจันทร์ที่ 4 ตุลาคม พ.ศ. 2553

Compiler : ออกแบบ Grammar (ภาษา Java)

เริ่มจากออกแบบภาษาโปรแกรม (Grammar) ของเราก่อน โดยใช้เครื่องมือออกแบบภาษาที่เราเรียกว่า EBNF (ศัพท์บางคำที่เพื่อนๆไม่คุ้นเคย ผมต้องขออภัยที่จะไม่กล่าวถึงรายละเอียดของพวกมันมากนัก เพื่อทำให้บทความมีสัดส่วนของเนื้อและน้ำอย่างพอเหมาะ (ตามความเห็นส่วนตัว) เช่น EBNF ศัพท์คำนี้อยากให้เพื่อนๆลองนำมันไปค้นหาต่ออีกที โดยอาจพิมพ์ใน Google หรือเว็บค้นหาอื่นๆก็ได้ครับ ^^)

EBNF ประกอบด้วยสองลักษณะสองประการใหญ่ๆ คือ Non-terminal และ Terminal มักเขียนครอบด้วยเครื่องหมาย < > สำหรับ Non-terminal และเครื่องหมาย " " สำหรับ Terminal ครับ เช่น

<start> -> <type> <name> ";"
<type> -> "int" | "float"
<name> -> ตัดจาก Lexical

จาก Grammar ตัวอย่างข้างต้น เราเรียก <start> ว่าตัวเริ่มต้น หรือ Start Symbol เรียกเครื่องหมาย -> ว่าการผลิต ดังนั้น <start> ซึ่งเป็น Non-terminal จึงผลิตได้ <type> <name> ";" ส่วน <type> ผลิตได้ "int" หรือ "float" โดยเครื่องหมาย | นี้หมายถึง หรือ (เลือกเอาอย่างใดอย่างหนึ่ง) และสุดท้าย <name> ผลิตได้ ชื่อใดๆที่ถูกตั้งและตัดได้จากกระบวนการ Lexical นั่นเองครับ

สรุปได้ว่า Non-terminal สามารถผลิตได้ Non-terminal หรือ Terminal อีกเท่าใดก็ได้ ส่วน Terminal นั้นไม่สามารถผลิตต่อไปได้อีก

จากนี้คือ Grammar ที่ผมประดิษฐ์ขึ้นเลียนแบบการประกาศตัวแปรของภาษา C โดย Grammar นี้จะนำมาใช้เป็นตัวอย่างตลอดทั้งเนื้อหาที่เกี่ยวกับหัวข้อ "โปรแกรม Compiler" ซึ่งมีหน้าที่ประกาศตัวแปร แบ่งออกเป็นตัวแปร Global และ Local พร้อมกับบังคับให้สร้างฟังก์ชัน Main อย่างง่ายหนึ่งฟังก์ชันครับ

<start> -> <variableDeclaration> <mainFunction>

<variableDeclaration> -> <type> <name> <assignment> <variableDeclaration2> ";" <variableDeclaration> | empty

<variableDeclaration2> -> "," <name> <assignment> <variableDeclaration2> | empty

<type> -> "int" | "float"

<assignment> -> "=" <expression> | empty

<expression> -> <addSubExpression>

<addSubExpression> -> <mulDivExpression> <addSubExpression2>

<addSubExpression2> -> <addSubSymbol> <mulDivExpression> <addSubExpression2> | empty

<addSubSymbol> -> "+" | "-"

<mulDivExpression> -> <primary> <mulDivExpression2>

<mulDivExpression2> -> <mulDivSymbol> <primary> <mulDivExpression2> | empty

<mulDivSymbol> -> "*" | "/" | "%"

<primary> -> <name> | <literal> | "(" <expression> ")"

<name> -> ตัดจาก Lexical เช่น a, b, c

<literal> -> ตัดจาก Lexical เช่น 10, 10.0

<mainFunction> -> "void" "main" "(" ")" "{" <variableDeclaration> "}"

***หมายเหตุ
ศัพท์ empty นี้หมายถึงไม่เกิดการผลิตสำหรับ Non-terminal นั้นต่อไป

หลังจากเพื่อนๆได้ทำความเข้าใจกับ Grammar ข้างต้น (สงสัยให้แสดงความเห็นไว้นะครับ) เราจะใช้เครื่องมือที่เรียกว่า Net Beans IDE เป็นตัวช่วยเขียนภาษาจาวาสำหรับการสร้างโปรแกรม Compiler นี้ต่อไป

อ่านเนื้อหาที่เกี่ยวข้อง ก่อนหน้า หรือ ถัดไป

2 ความคิดเห็น:

  1. ไม่ระบุชื่อ14 มีนาคม 2554 เวลา 06:46

    ออกแบบแกรมม่ามันมีขั้นมากกว่านี้ ขอแตกรายละเอียดหน่อยสิค่ะ เช่น while_loop ,if_else ฯลฯ

    ตอบลบ
  2. ขอเป็นวิธีการออกแบบ grammar ฉบับผมก็แล้วกันนะครับเพื่อน (ฉบับมาตรฐานผมลืมเกือบหมดแล้ว) เดี๋ยวจัดให้ครับ ขอบคุณครับที่กรุณาอ่านบทความ ขอบคุณๆ

    ตอบลบ