เพื่อให้ภาษาสามารถตั้งโปรแกรมได้มันจำเป็นหรือไม่ที่จะต้องอิงตามบริบทของไวยากรณ์อิสระ


23

ในทางปฏิบัติแล้วสำหรับภาษาที่สามารถรวบรวม / แปลงเป็นคำสั่งในระดับระบบได้ในที่สุดจำเป็นหรือไม่ที่จะต้องเป็นไวยากรณ์ที่ไม่มีบริบท?

ตัวอย่าง: ไวยากรณ์ภาษาการเขียนโปรแกรม / สคริปต์ทั้งหมดไม่มีบริบทหรือไม่ Java ใช้ CFG แต่จริงๆแล้วมันเป็นกรณีที่ภาษาการเขียนโปรแกรมทั้งหมดใช้ CFG หรือไม่?

ดูเหมือนจะไม่ได้รับคำสั่ง แต่มีช่องว่างในความเข้าใจของฉัน

บางบริบทสำหรับคำถามที่ว่าฉันถูกมองที่สเปคภาษา Java ซึ่งนอกจากนี้ยังมีไวยากรณ์กฎ นี่ทำให้ฉันคิดถึงคำถามนี้


1
โดยทั่วไปฉันคิดว่าเป็นเพียงการที่คุณต้องการให้ปัญหาการคอมไพล์คำนวณได้และการแยก CFG นั้นดีและใช้งานง่าย แม้ว่าฉันเคยได้ยินบางคนอ้างว่าตัวอย่างเช่นการตระหนักถึงโปรแกรม Perl ที่ถูกต้องในความเป็นจริงเป็นปัญหาที่ไม่สามารถคำนวณได้
Janne H. Korhonen

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

@ ratchet คุณคิดว่าไวยากรณ์ต้องนับซ้ำซ้ำได้หรือไม่
David Harris

4
@JanneKorhonen: โดยเฉพาะ Perl ไม่สามารถแยกวิเคราะห์แบบคงที่นั่นคือมันไม่สามารถแยกวิเคราะห์โดยไม่ต้องดำเนินการ; เนื่องจากการดำเนินการดังกล่าวอาจไม่สิ้นสุดการแยก Perl แบบคงที่จะบ่งบอกถึงการแก้ปัญหาการหยุดชะงัก
Jon Purdy

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

คำตอบ:


20

ไม่สองครั้ง

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

class A {
  String a = "a";
  int b = a + d;
}

เป็นโปรแกรม Java ที่ถูกต้องทางไวยากรณ์ แต่จะไม่รวบรวมเพราะdไม่ได้กำหนดไว้และaไม่มีประเภทของข้อต่อ

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

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


3
อย่าลืมpublic class Program { public static void main(String[] args) { ... } }... Java จะไม่ทำให้คุณหลุดพ้นจากเรื่องง่าย :-)
Roy Tinker

ในทางเทคนิคแล้วclass A { ... }ก็เพียงพอแล้วสำหรับการjavacรวบรวมสิ่งที่คุณไม่สามารถดำเนินการได้จริง (เพราะขาดจุดเข้าใช้งาน) เช่นกัน แต่ใช่
กราฟิลส์

20

6
ฉันรู้สึกเช่นนี้ควรจะเป็นมุกของเรื่องตลก Perl :)
Suresh Venkat

5
Suresh: ฉันทำเรื่องตลกมาแล้วถึงแม้ว่ามันจะไม่ใช่เรื่องตลกที่ดีมากในบทความ "ในภาษาการเขียนโปรแกรมที่ไม่ยืดหยุ่น" ใน SIGBOVIK 2011 ( sigbovik.org/2011/proceedings.pdf - หน้า79- 82)
Rob Simmons

1
หมายเหตุ: ล่าม Perl ยังไม่เป็นที่ไม่ใช่กำหนดถ้านั่นคือความสะดวกสบายให้กับทุกคน :)
รอยทิงเกอร์

15

ฉันไม่เชื่อว่าไวยากรณ์ของ Python นั้นไม่มีบริบท ความต้องการที่บรรทัดในบล็อกของรหัสเดียวกันมีจำนวนเยื้องเท่ากันไม่ใช่การเรียงลำดับของสิ่งที่บริบทไวยากรณ์อิสระจัดการได้ดี

แม่นยำยิ่งขึ้นดูเหมือนว่าจะมี homomorphism จากภาษาของ Python block ของแบบฟอร์ม

ถ้าเงื่อนไข:
     บรรทัดที่ 1
     line2
     บรรทัดที่ 3
อื่น:
     เส้น 4

ไปยังภาษาที่ไม่มีบริบทโดยที่บล็อกแรกของศูนย์มาจากชุดของช่องว่างที่จุดเริ่มต้นของบรรทัดที่ 1 บล็อกที่สองมาถึงชุดของช่องว่างที่จุดเริ่มต้นของ line2 บล็อกที่สาม มาจากชุดของช่องว่างที่จุดเริ่มต้นของ line3 และบรรทัดที่เหลือด้วยอีกอย่างคือจะต้องบังคับให้ line1, line2 และ line3 เป็นของบล็อกเดียวกัน0n10n10n


4
อย่างเคร่งครัดคุณมีสิทธิ แต่ในบริบทของการเขียนโปรแกรมภาษาที่เราพยายามที่จะทำให้บริบทภาษาฟรีที่เกิดหลังจากขั้นตอนที่เรียกว่า preprocessing tokenization ฉันคิดว่ามีการตรวจสอบการเยื้องก่อนหน้านั้น
Diego de Estrada

7
ใช่ Python lexer (tokenizer) มีความลึกของการเยื้อง โทเค็นสตรีมมีสัญลักษณ์ INDENT ที่จุดเริ่มต้นของแต่ละบล็อกและสัญลักษณ์ DEDENT ที่ส่วนท้ายซึ่งสามารถแยกวิเคราะห์ในลักษณะที่ไม่มีบริบท (INDENT และ DEDENT ทำหน้าที่คล้ายกับเครื่องหมายปีกกาใน C) C มีปัญหา "ไม่สามารถบอกได้ว่าการประกาศหรือการแสดงออก" มีfoo * bar;การประกาศfooว่าเป็นตัวชี้ไปยังbarหรือการคูณของfooเวลาbarหรือไม่?
สูงสุด

8
ตกลงแน่นอน แต่คุณเพียงแค่ซ่อนความซับซ้อนเดียวกันในตัวเล็กซ์แทนที่จะทำให้มันเป็นตัวแปลงสัญญาณสถานะ จำกัด ตามที่พวกเขามักจะเป็น
David Eppstein

1
@DavidEppstein: การพูดอย่างยุติธรรมนั้นความซับซ้อนนั้นไม่ได้ยอดเยี่ยมเลย
Jon Purdy

1
นอกเหนือจากการจัดการ INDENT / DEDENT ใน lexer แล้ว Python ยังมีไวยากรณ์ LL (1) ที่ง่ายมาก
rmmh

13

Bodo Manthey และ Martin Böhmeแสดงให้เห็นว่าคอมไพเลอร์ C ++ ทุกตัวจำเป็นต้องใช้ทัวริงอย่างสมบูรณ์นั่นคือมันสามารถคำนวณฟังก์ชัน recursive บางส่วนได้ในเวลารวบรวม ดังนั้นมันจึงแย่กว่าบริบทที่ไว

http://wwwhome.math.utwente.nl/~mantheyb/journals/BotEATCS_BoehmeManthey_CompilingCPP.pdf


ใช่ แต่คอมไพเลอร์ไม่ได้เป็นเพียงแค่ไวยากรณ์ที่ไม่มีบริบท คุณควรหารือเกี่ยวกับไวยากรณ์เองไม่ใช่คอมไพเลอร์
Jeff Burdges

@Jeff: "เวลารวบรวม" ในคำตอบของฉันหมายถึง "การตรวจสอบว่ารหัส C + ที่กำหนดนั้นถูกต้อง" ด้วยการดัดแปลงเล็กน้อยของสิ่งก่อสร้างในกระดาษมันเป็นไปตามที่คุณสามารถลดทุกภาษา decidable เป็นชุดของโปรแกรม C ++ ที่ถูกต้องทั้งหมด
Markus Bläser

7

ฉันคิดว่าการประกาศก่อนการใช้ตัวแปรและฟังก์ชั่น polymorphismของภาษา OOP เป็นตัวอย่างอื่น ๆ ของข้อกำหนดภาษาการเขียนโปรแกรมที่ไม่สามารถจัดการได้ด้วยไวยากรณ์อิสระบริบท:

int myfun(int a) { ... }
int myfun(int a, int b) { ... }
int myfun(int a, int b, int c, ...) { ... }
...
int I_m_I_cfg = myfun(1,2);
...

ฉันค้นหาโดยใช้ Google เล็กน้อยและพบบทความนี้: " A Boolean Grammar for Simple Boolean Language "โดย A.Okhotin (2004); ตามเขาปัญหาที่แท้จริงคือการหาภาษาโปรแกรมที่สมบูรณ์อธิบายโดยไวยากรณ์อย่างเป็นทางการ:

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

ส่วนบทนำของบทความนั้นสั้น แต่ชัดเจนมาก


6

ฉันเชื่อว่าไวยากรณ์ของ C นั้นปราศจากบริบททางเทคนิคในตัวแยกวิเคราะห์ที่ใช้เทคนิคที่ไม่ใช่บริบทเพื่อสนับสนุนอุปกรณ์ของ Duffเสมอ

ภาษาที่ใช้การเยื้องไม่ใช่บริบทที่เป็นธรรมชาติอย่างที่เดวิดพูด แต่พวกมันกลายเป็นบริบทที่ปราศจากสัมพัทธ์กับโทเค็นการเยื้องพารามิเตอร์

Haskell ให้คุณเปลี่ยนลำดับความสำคัญของโอเปอเรเตอร์ด้วย infix และ infixl โมดูล pragma ที่เข้มงวดของ Perl นั้นถูกนำไปใช้งานโดยใช้การตั้งค่าคำศัพท์ $ ^ H และ% ^ H ซึ่งทำให้ไม่เป็นไปตามบริบท

มีภาษาตัวขยายแมโครอย่าง TeX ซึ่งการแยกวิเคราะห์ afaik ไม่สมเหตุสมผลหากไม่ดำเนินการ

อาจมีแม้แต่ไวยากรณ์สองบริบทที่ไม่มีจุดตัดไม่ใช่บริบท แต่ยังอธิบายถึงเครื่องทัวริง

Java และแอสเซมเบลอร์อาจไม่มีบริบทตามธรรมชาติ


2
ความคลุมเครือของการ(a)-bทำให้ C เป็นบริบทหรือไม่ ( aอาจเป็นตัวแปรหรือ typedef - ภาษาอื่นบางภาษาไม่อนุญาตให้ใช้การแสดงออกแบบไม่นับลบด้วยเหตุนี้)
สุ่ม 832

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

4

ไม่และภาษาที่ใช้งานได้หลาย ๆ อย่างนั้นไม่มีบริบท ตัวอย่างเช่นไวยากรณ์ C ++ ไม่ได้เพราะในการแก้ปัญหาไวยากรณ์บริบทบางอย่างขึ้นอยู่กับข้อมูลการพิมพ์ที่ไม่ได้เป็นบริบท


4

ก่อนอื่นให้ฉันสร้างความแตกต่างระหว่างไวยากรณ์ของภาษาโปรแกรมและภาษาของตัวเอง

ไวยากรณ์ของหลายภาษาคือ (อย่างน้อยตาม) Context Free Grammar (CFG) เพราะสิ่งเหล่านี้ได้รับการศึกษามาอย่างดีและมีอัลกอริธึมที่สามารถแยก CFG และกรณีที่ไม่สามารถแก้ไขได้โดย CFG เป็นพิเศษ

อย่างไรก็ตามมีหลายภาษาในความเป็นจริงไม่ใช่ Context-Free (เมื่อใช้สัญลักษณ์ที่ประกาศก่อนใช้งานเช่นใน java, C (++), D)

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


การวิเคราะห์ชื่อและประเภทโดยทั่วไปจะแสดงงานอิสระที่ไม่ใช่บริบทโดยเนื้อแท้
Raphael

แม่แบบการเขียนโปรแกรมเมตาใน C ++ นั้นเสร็จสมบูรณ์แล้ว
Jeff Burdges

3

ตราบใดที่ "ไวยากรณ์ภาษาการเขียนโปรแกรม / สคริปต์ฟรีทั้งหมดหรือไม่" ส่วนที่เกี่ยวข้องคำตอบคือไม่แน่นอน

Re: คำถามหลักของ "สำหรับภาษาที่สามารถรวบรวม / แปลงเป็นคำสั่งในระดับระบบได้" ฉันไม่รู้ว่าทำไมมันจำเป็นต้องเป็น CFG อย่างไรก็ตามอาจมีคำอธิบายที่ดีกว่าออกมา


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

3

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

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