เหตุใดความยืดหยุ่นของ Forth จึงทำให้ไวยากรณ์ไม่เหมาะสม


10

ฉันเพิ่งทำภารกิจการเขียนภาษาโปรแกรมสแต็ก ก่อนที่ฉันจะเริ่มออกแบบภาษาของฉัน แต่ฉันคิดว่ามันเป็นความคิดที่ดีที่จะอ่านและทดลองใช้ภาษาที่มีอยู่เดิม

นี่นำฉันมาที่หัวข้อของโพสต์นี้ ฉันอ่านบทความวิกิพีเดียใน Forthซึ่งเป็นภาษาที่ใช้สแต็กซึ่งใช้การแสดงออกสไตล์ postfix ในบทความฉันเห็นข้อความต่อไปนี้:

ความยืดหยุ่นของ Forth ทำให้ไวยากรณ์ BNF คงที่ไม่เหมาะสมและไม่มีคอมไพเลอร์เสาหิน การขยายคอมไพเลอร์เพียงต้องการเขียนคำใหม่แทนที่จะแก้ไขไวยากรณ์และเปลี่ยนการใช้งานพื้นฐาน

จากความเข้าใจของฉันในศัพท์แสง Forth คำว่า "คำว่า" ดูเหมือนจะตรงกันกับ "subroutine" ด้วยสิ่งนี้ข้อความข้างต้นดูเหมือนแปลก ทำไมความสามารถในการสร้างฟังก์ชั่นใหม่ใน Forth จึงทำให้ไวยากรณ์เป็นทางการสำหรับ Forth ไม่เหมาะสม? ทำไมคุณต้องเขียนไวยากรณ์ใหม่สำหรับแต่ละรูทีนย่อยใหม่ที่คุณกำหนด การเขียนคำศัพท์ใหม่ในสภาพแวดล้อมประกอบด้วยการขยายคอมไพเลอร์อย่างไร ข้อความข้างต้นดูเหมือนจะคล้ายกับว่าไวยากรณ์อย่างเป็นทางการไม่เหมาะสมสำหรับ Python เพราะคุณสามารถกำหนดฟังก์ชั่นใหม่ได้

ในความเป็นจริงฉันตัดสินใจที่จะพยายามเขียนไวยากรณ์สไตล์ BNF สำหรับชุดย่อยง่ายๆของ Forth ด้านล่าง:

program        ::= stmt+
stmt           ::= func | expr
func           ::= ':' expr+ ';'
expr           ::= INTEGER | word
word           ::= ('+' | '-' | '*' | '/' )

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

โดยสรุปเหตุใด ablitiy ของ Forth จึงกำหนดคำศัพท์ใหม่ (รูทีนย่อย) ทำให้ไม่เหมาะสมสำหรับไวยากรณ์ที่เขียน


1
"ไม่เหมาะสม" เป็นคำที่แข็งแกร่งในบริบทนี้ คำที่ดีกว่าอาจเป็น "ไม่จำเป็น"
Robert Harvey

1
โอ้โอเค @RobertHarvery อย่างไรก็ตามหากเป็นเช่นนั้นข้อความที่ตัดตอนมาที่ฉันอ้างจะดูเหมือนจะใช้กับภาษาส่วนใหญ่ ในทางเทคนิคแล้วไวยากรณ์นั้นไม่จำเป็นแต่มันก็ดีที่จะมีหนึ่ง - โดยเฉพาะอย่างยิ่งเมื่อ parsers เขียนด้วยมือ
Christian Dean

แต่ในภาษาส่วนใหญ่ parser ไม่ใช่ไลบรารีรันไทม์อย่างง่ายที่สามารถเปลี่ยนได้โดยรหัสผู้ใช้ซึ่งส่งผลต่อวิธีแยกวิเคราะห์บรรทัดถัดไป
Jörg W Mittag

คำตอบ:


10

คำว่า "ปกติ" นั้นค่อนข้างจะเป็นเพียงแค่รูทีนย่อย

... แต่คุณสามารถเขียนคำที่ผู้ใช้กำหนดซึ่งจะเปลี่ยนวิธีการทำงานของคอมไพเลอร์ ตัวอย่างเช่นคำจำกัดความเริ่มต้นด้วยเครื่องหมายโคลอน (":") และลงท้ายด้วยเครื่องหมายอัฒภาค (";") แต่ถ้าคุณต้องการคุณสามารถ (ตัวอย่าง) เปลี่ยนแปลงสิ่งที่ลำไส้ใหญ่ทำและในกระบวนการเปลี่ยนวิธีคำจำกัดความของคำว่า "รวบรวม" จึงเปลี่ยนวิธีการทำงานของคอมไพเลอร์และเปลี่ยนไวยากรณ์ของภาษาที่ได้รับการยอมรับ

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


2
คุณแน่ใจหรือไม่ว่าคุณสมบัติของ Forth นี้เปลี่ยนไวยากรณ์จริงๆและไม่ใช่แค่ความหมาย?
Doc Brown

@DocBrown: คนส่วนใหญ่ที่ใช้ Forth ชอบมันค่อนข้างมากดังนั้นพวกเขามักจะทำการเปลี่ยนแปลงเล็กน้อยที่สุดที่จำเป็นสำหรับงานที่ทำอยู่ ใครบางคนที่มีความทะเยอทะยาน (และคลั่งไคล้) พอที่จะเปลี่ยนรูปแบบได้อย่างสมบูรณ์ถ้าพวกเขาต้องการ - เช่นใช้สัญกรณ์ใส่มัดแทน Postfix ถ้าพวกเขาต้องการไม่ดีพอ
Jerry Coffin

@DocBrown ไวยากรณ์แบบไหนที่คุณสามารถเขียนได้ซึ่งจะช่วยให้ฉันสามารถเขียนล่าม C ใน Forth จากนั้นก็เปลี่ยนเป็น C ตรงกลางของโปรแกรมได้หรือไม่
user253751

@immibis: ดีคำถามของฉันคือ - ไม่อนุญาตให้บางสิ่งบางอย่างเช่นนี้หรือไม่ จากบทความที่เชื่อมโยงนั้นสิ่งนี้ไม่ชัดเจนสำหรับฉัน
Doc Brown

@DocBrown ใช่มันเป็นเช่นนั้น คุณสามารถเรียกใช้รหัสของคุณในเวลารวบรวมซึ่งหมายความว่าถ้าคุณต้องการที่จะใช้เวลาอย่างเต็มรูปแบบรวบรวม โดยทั่วไปคุณสามารถเรียกใช้ C คอมไพเลอร์ / ล่ามของคุณในช่วงกลางของ Forth คอมไพเลอร์ / ล่าม (ไม่ว่าคุณต้องการที่จะกลับไปที่ Forth หรือไม่นั้นขึ้นอยู่กับคุณ)
user253751

3

ใน Forth คุณสามารถเรียกใช้รหัสในเวลารวบรวม

โดยเฉพาะอย่างยิ่งคุณสามารถเรียกใช้รหัสที่ใช้คำจากอินพุต ตัวอย่างเช่นคุณสามารถเขียน C คอมไพเลอร์ใน Forth แล้วเรียกมันในเวลาคอมไพล์แล้วเขียนโปรแกรมที่เหลือใน C

โดยทั่วไปคุณสามารถกำหนดคำที่อ่านอาร์กิวเมนต์จากซอร์สโค้ด ตามเนื้อผ้าคุณจะอ่านคำต่าง ๆ เช่นเดียวกับที่คอมไพเลอร์ทำ แต่ก็ไม่จำเป็น

ยกตัวอย่างเช่น."คำ (ที่พิมพ์สตริง) "ไม่ได้อ่านจนพื้นที่ต่อไปก็อ่านจนต่อไป หากคุณพยายามวิเคราะห์โค้ด: PRINTHELLO ." Hello ; : func2 world!" ;โดยไม่ต้องใช้ตัวพิมพ์พิเศษ."คุณจะพบว่ารหัสไม่ถูกวิเคราะห์อย่างถูกต้อง

แน่นอนคุณสามารถเพิ่มเป็นกรณีพิเศษสำหรับ."ไวยากรณ์ของคุณ แต่ไวยากรณ์จะยังคงไม่ถูกต้องถ้าโปรแกรมเมอร์กำหนดคำที่ตัวเองชอบ."- : MY_PRINT POSTPONE ." ; IMMEDIATEตัวอย่างเช่นที่นี่เป็นหนึ่ง: คำนี้จะเทียบเท่ากับ."; ฉันสามารถเขียนMY_PRINT Hello ; world! "และไวยากรณ์ของคุณต้องสามารถแยกมัน ขอให้โชคดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.