Để một ngôn ngữ có thể lập trình được, có bắt buộc phải dựa trên ngữ pháp không ngữ cảnh không


23

Thực tế, đối với một ngôn ngữ cuối cùng có thể được biên dịch / chuyển đổi thành các hướng dẫn cấp hệ thống, có nhất thiết phải là một ngữ pháp không ngữ cảnh không?

ví dụ: Có phải tất cả các ngôn ngữ lập trình / kịch bản ngữ cảnh đều là ngữ pháp miễn phí? Java dựa trên CFG, nhưng thực tế có phải tất cả các ngôn ngữ lập trình đều dựa trên CFG không?

Nó không có vẻ bắt buộc, nhưng có những khoảng trống trong sự hiểu biết của tôi.

Một số bối cảnh cho câu hỏi: Tôi đã xem xét đặc tả ngôn ngữ Java, cũng cung cấp các quy tắc ngữ pháp . Điều này làm tôi suy nghĩ về câu hỏi này.


1
Nói chung tôi nghĩ rằng chỉ là bạn muốn vấn đề biên dịch có thể tính toán được và phân tích CFG là tốt và dễ dàng. Mặc dù tôi đã nghe một số tuyên bố rằng, ví dụ, việc nhận ra các chương trình perl hợp lệ trên thực tế là một vấn đề không thể tính toán được.
Janne H. Korhonen

2
thực ra tất cả những gì bạn thực sự cần là một cú pháp có thể quyết định được (mà tất cả các CFG đều có). Bạn cũng có thể tạo một ngôn ngữ lập trình mà cú pháp không thể xác định được, nhưng khi bạn đánh máy, trình biên dịch có thể không bao giờ dừng lại trong khi nó cố gắng quyết định xem đó có phải là cú pháp hợp lệ hay không. điều này không thực sự hữu ích
ratchet freak

@ratchet, bạn có giả sử cú pháp phải được liệt kê đệ quy không?
David Harris

4
@JanneKorhonen: Cụ thể, Perl không thể được phân tích cú pháp tĩnh , nghĩa là nó không thể được phân tích cú pháp mà không được thực thi; kể từ khi thực thi có thể không kết thúc, phân tích cú pháp Perl một cách tĩnh sẽ ngụ ý giải quyết vấn đề dừng.
Jon Purdy

@janne Ý tôi là, đăng tiền xử lý có thể kéo theo các vấn đề có thể hoặc không thể tính toán được, nói chung là trường hợp ngữ pháp cuối cùng mà chương trình được xác nhận chống lại không có ngữ cảnh. Để cụ thể hơn, hãy xử lý trước khi đăng, để xác định quy tắc phù hợp với chuỗi mã thông báo, chúng ta cần xem xét các mã thông báo khác xung quanh chuỗi. Tôi không biết nếu tôi có ý nghĩa, xin lỗi về điều đó. Tôi thực sự có một chút bối rối.
sandeepkunkunuru

Câu trả lời:


20

Hai lần không.

Đầu tiên, hầu hết các HPL không có ngữ cảnh. Mặc dù họ thường có cú pháp dựa trên CFG, họ cũng có những gì mọi người gọi là ngữ nghĩa tĩnh (cũng thường được bao gồm trong cú pháp thuật ngữ). Điều này có thể bao gồm tên và loại phải kiểm tra cho một chương trình chính xác. Ví dụ,

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

là một chương trình Java đúng về mặt cú pháp nhưng sẽ không biên dịch vì dkhông được xác định và akhông có kiểu phù hợp.

Thứ hai, bạn có thể phân tích các ngôn ngữ không có ngữ cảnh (rõ ràng đã được chứng minh bằng sự tồn tại của trình biên dịch). Chỉ có thể nói rằng CFG có thể được phân tích cú pháp một cách hiệu quả, trong khi nói chung, CSG không thể. Tuy nhiên, bạn có thể thêm một số tính năng không ngữ cảnh nhất định trong khi vẫn hiệu quả.

Trình biên dịch thường chạy theo các giai đoạn: mã thông báo đầu tiên (thông thường), sau đó phân tích cú pháp không ngữ cảnh, sau đó phân tích tên và loại (nhạy cảm theo ngữ cảnh, đôi khi còn khó hơn). Bạn có thể quan sát hành vi đó bằng loại thông báo lỗi bạn nhận được.


3
Đừng quên public class Program { public static void main(String[] args) { ... } }... Java sẽ không cho phép bạn thoát ra dễ dàng như vậy. :-)
Roy Tinker

Về mặt kỹ thuật, class A { ... }hoàn toàn đủ để javacbiên dịch những thứ bạn thực sự không thể thực hiện (vì thiếu điểm vào). Nhưng phải
Raphael

20

6
Tôi cảm thấy như đây sẽ là cú đấm của trò đùa Perl :)
Suresh Venkat

5
Suresh: Tôi đã thực hiện trò đùa đó, mặc dù nó không trở thành một trò đùa rất hay, trong bài báo "Về ngôn ngữ lập trình không thể kiểm soát" trong SIGBOVIK 2011 ( sigbovik.org/2011/proceedings.pdf - trang 79- 82).
Rob Simmons

1
Lưu ý: trình thông dịch Perl chưa phải là không xác định, nếu đó là một sự thoải mái với bất cứ ai :)
Roy Tinker

15

Tôi không tin rằng ngữ pháp của Python là ngữ cảnh miễn phí. Yêu cầu rằng các dòng trong cùng một khối mã có cùng số lượng thụt lề không phải là thứ mà ngữ pháp tự do ngữ cảnh xử lý tốt.

Chính xác hơn, dường như có sự đồng hình từ ngôn ngữ của các khối Python có dạng

nếu điều kiện:
     dòng 1
     dòng 2
     dòng3
khác:
     dòng4

0n10n10n


4
Nghiêm túc bạn đúng, nhưng trong ngữ cảnh của các ngôn ngữ lập trình, chúng tôi cố gắng làm cho ngôn ngữ không có ngữ cảnh dẫn đến sau một bước tiền xử lý được gọi là mã thông báo . Tôi nghĩ rằng vết lõm được kiểm tra trước đó.
Diego de Estrada

7
Vâng, Python lexer (mã thông báo) có một đống độ sâu thụt; luồng mã thông báo có ký hiệu INDENT ở đầu mỗi khối và ký hiệu DEDENT ở cuối có thể được phân tích cú pháp theo cách không có ngữ cảnh (INDENT và DEDENT hoạt động giống như dấu ngoặc trong C). C có vấn đề "không thể biết nếu khai báo hay biểu thức": là foo * bar;khai báo foodưới dạng con trỏ tới barhoặc nhân với số foolần bar?
Tối đa

8
Ok, chắc chắn, nhưng sau đó bạn chỉ che giấu sự phức tạp tương tự trong từ vựng, thay vì làm cho nó trở thành một bộ chuyển đổi trạng thái hữu hạn như thường thấy.
David Eppstein

1
@DavidEppstein: Công bằng mà nói, sự phức tạp không phải là tuyệt vời bằng mọi cách.
Jon Purdy

1
Ngoài việc xử lý INDENT / DEDENT trong từ vựng, Python còn có ngữ pháp LL (1) rất đơn giản.
rmmh

13

Bodo Manthey và Martin Böhme cho thấy rằng mọi Trình biên dịch C ++ nhất thiết phải hoàn thành Turing, nghĩa là, nó có thể tính toán bất kỳ hàm đệ quy một phần nào trong thời gian biên dịch . Vì vậy, nó là tồi tệ hơn nhiều so với chỉ nhạy cảm bối cảnh.

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


Có, nhưng trình biên dịch không bao giờ chỉ là ngữ pháp không ngữ cảnh. Bạn nên thảo luận về ngữ pháp, không phải trình biên dịch.
Jeff Burdges

@Jeff: "Biên dịch thời gian" trong câu trả lời của tôi có nghĩa là "kiểm tra xem mã nguồn C + đã cho có chính xác không". Bằng một sửa đổi nhỏ về cấu trúc trong bài báo, theo đó bạn có thể giảm mọi ngôn ngữ có thể quyết định thành tập hợp tất cả các chương trình C ++ chính xác.
Markus Bläser

7

Tôi nghĩ rằng khai báo trước khi sử dụng các biến và tính đa hình chức năng của các ngôn ngữ OOP là các ví dụ khác về các đặc tả ngôn ngữ lập trình không thể được xử lý bởi các ngữ pháp tự do ngữ cảnh:

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);
...

Tôi đã thực hiện một tìm kiếm nhỏ trên Google và tôi đã tìm thấy bài viết này: " Ngữ pháp Boolean cho ngôn ngữ Boolean đơn giản " của A.Okhotin (2004); Theo ông, vấn đề thực sự là tìm một ngôn ngữ lập trình được mô tả hoàn toàn bằng một ngữ pháp chính thức:

Một ngôn ngữ lập trình thủ tục đồ chơi được xác định và ngữ pháp Boolean cho tập hợp các chương trình được hình thành tốt trong ngôn ngữ này được xây dựng. Đây rõ ràng là đặc điểm kỹ thuật đầu tiên của một ngôn ngữ lập trình hoàn toàn bằng một ngữ pháp chính thức.

Phần Giới thiệu của bài viết ngắn nhưng rất rõ ràng.


6

Tôi tin rằng ngữ pháp của C chỉ không có ngữ cảnh về mặt kỹ thuật trong đó các trình phân tích cú pháp luôn sử dụng các kỹ thuật phi ngữ cảnh để hỗ trợ thiết bị của Duff .

Các ngôn ngữ dựa trên thụt lề không tự nhiên không có ngữ cảnh như David đã nói, nhưng chúng trở thành không có ngữ cảnh liên quan đến mã thông báo thụt lề được tham số hóa.

Haskell cho phép bạn thay đổi quyền ưu tiên của nhà điều hành với infix và infixl. Mô-đun pragma nghiêm ngặt của Perl được triển khai bằng các cài đặt từ vựng $ ^ H và% ^ H, làm cho nó không có ngữ cảnh, có lẽ các cài đặt khác cũng vậy.

Có các ngôn ngữ mở rộng vĩ mô như TeX trong đó phân tích cú pháp afaik không có ý nghĩa mà không thực hiện.

Có lẽ thậm chí có hai ngữ pháp không ngữ cảnh mà giao điểm của chúng không phải là không có ngữ cảnh nhưng vẫn mô tả một máy Turing.

Java và trình biên dịch có lẽ đều tự nhiên không có ngữ cảnh.


2
Không phải sự mơ hồ của việc (a)-blàm cho C nhạy cảm với ngữ cảnh? ( acó thể là biến hoặc typedef - một số ngôn ngữ khác không cho phép truyền các biểu thức trừ đơn nguyên vì lý do này)
Random832

Tôi xin lỗi vì nhận xét rất chậm trễ nhưng thiết bị của Duff không có sai lệch cú pháp. Niềng răng cân bằng chính xác. Tính năng C thường bị bỏ qua nhất trong các cuộc thảo luận về việc liệu C không có ngữ cảnh có phải là bộ tiền xử lý hay không. Tôi nghi ngờ rằng có bất kỳ cách giải thích nào, tuy nhiên không chính thức, về "không ngữ cảnh" cho phép sử dụng nó để mô tả một ngôn ngữ với bộ xử lý macro, thậm chí là một ngôn ngữ được xử lý tốt. Và tiền xử lý C là bất cứ điều gì nhưng hoạt động tốt.
rici

4

Không, và nhiều ngôn ngữ thực tế không có ngữ cảnh. Ví dụ, ngữ pháp C ++ thì không, bởi vì trong một số ngữ cảnh, độ phân giải ngữ pháp phụ thuộc vào việc gõ thông tin không có ngữ cảnh.


4

Đầu tiên hãy để tôi phân biệt giữa cú pháp của ngôn ngữ lập trình và ngôn ngữ đó.

Cú pháp của nhiều ngôn ngữ (ít nhất là dựa trên) Ngữ pháp tự do ngữ cảnh (CFG) bởi vì chúng được nghiên cứu kỹ và có các thuật toán có thể phân tích một cách hiệu quả CFG và trường hợp cạnh không thể giải quyết được bằng CFG

Tuy nhiên, nhiều ngôn ngữ trên thực tế không phải là Ngữ cảnh miễn phí (khi các biểu tượng khai báo trước khi sử dụng được sử dụng, ví dụ như trong java, C (++), D).

Sự thật thú vị: D có một đánh giá chức năng biên dịch thời gian biên dịch hoàn chỉnh Turing và mở rộng khuôn mẫu làm cho ngôn ngữ không thể Turing-decidable. Tuy nhiên, người tạo ra ngôn ngữ đã cố gắng hết sức để biến cú pháp thành CFG.


Phân tích tên và loại thường peform vốn dĩ không phải là tác vụ miễn phí theo ngữ cảnh.
Raphael

Lập trình meta mẫu trong C ++ là Turing hoàn tất.
Jeff Burdges

3

Theo như "Tất cả các ngôn ngữ lập trình / ngôn ngữ kịch bản có ngữ pháp miễn phí không?" một phần có liên quan, câu trả lời là một số xác định

Re: câu hỏi chính về "cho một ngôn ngữ cuối cùng có thể được biên dịch / chuyển đổi thành các hướng dẫn cấp độ hệ thống", tôi không biết tại sao nó nhất thiết phải là một CFG. Tuy nhiên, có thể có những lời giải thích tốt hơn sắp tới.


1
Kris, bạn có thể đưa ra một số ví dụ về các ngôn ngữ lập trình dựa trên ngữ pháp miễn phí không ngữ cảnh. Ý tôi là, hậu xử lý có thể kéo theo các vấn đề có thể hoặc không thể tính toán được, ngữ pháp cuối cùng mà chương trình được xác nhận chống lại.
sandeepkunkunuru

3

Một ngôn ngữ lập trình cần phải dựa trên một số loại hình thức ngữ pháp, trong đó CFG là một ví dụ. Mặc dù CFG là phổ biến nhất (và là điều thông thường được dạy trong các khóa học về trình biên dịch tại các trường đại học), có những hình thức khác như Ngữ pháp phân tích cú pháp, bạn có thể đọc thêm về đây (pdf) hoặc trên Wikipedia để đọc nhiều hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.