Có nghĩa là những gì mà ngữ cảnh không có nghĩa là ngữ nghĩa trong các thuật ngữ ngữ pháp không có ngữ cảnh.


55

Dựa vào số lượng tài liệu cố gắng giải thích ngữ pháp không ngữ cảnh (CFG) là gì, tôi thấy ngạc nhiên khi rất ít (trong mẫu của tôi, ít hơn 1 trên 20) đưa ra lời giải thích về lý do tại sao các ngữ pháp đó được gọi là "ngữ cảnh- miễn phí". Và, theo tôi, không ai thành công trong việc này.

Câu hỏi của tôi là, tại sao các ngữ pháp không ngữ cảnh được gọi là không ngữ cảnh? "Bối cảnh" là gì? Tôi có một trực giác rằng bối cảnh có thể là các cấu trúc ngôn ngữ khác xung quanh cấu trúc hiện đang được phân tích, nhưng dường như đó không phải là trường hợp. Bất cứ ai có thể cung cấp một lời giải thích chính xác?


4
tra cứu "hầu hết các phân tích vexing" cho C ++, điều này sẽ cho bạn biết lý do tại sao bối cảnh lại tiện dụng
ratchet freak

6
Tôi nghĩ rằng tôi đã biết ngữ pháp không ngữ cảnh là gì cho đến khi tôi chỉ đọc một số định nghĩa về Google. Bây giờ tôi ước tôi có một bản phác thảo và một bản trống mềm mại ... có lẽ tôi sẽ ra ngoài ... +1 cho một câu hỏi hay. Mong chờ một số câu trả lời dễ hiểu!
BrianH

Trực giác của bạn là những gì tôi hiểu, ngay cả khi định nghĩa chính thức của "các cấu trúc ngôn ngữ khác xung quanh cấu trúc hiện đang được phân tích" là phù hợp. Nhưng tôi không chắc chắn để đăng nó như là một câu trả lời.
Telastyn

1
Xem các wiki về ngữ pháp không ngữ cảnhphân cấp Chomsky . Trong thực tế, phân tích ngôn ngữ lập trình có một số ngữ cảnh, thường được xử lý "bên ngoài" phân tích cú pháp "không ngữ cảnh" (LR hoặc LL), ví dụ như bởi một số bảng biểu tượng, thuộc tính hoặc môi trường
Basile Starynkevitch

1
Tại đây, có một tài liệu tham khảo xkcd: xkcd.com/1090
CaptainCodeman

Câu trả lời:


60

Nó có nghĩa là tất cả các quy tắc sản xuất của nó có một thiết bị đầu cuối duy nhất ở phía bên trái của họ.

Ví dụ, ngữ pháp này nhận ra các chuỗi dấu ngoặc đơn phù hợp ("()", "() ()", "(()) ()", ...) không có ngữ cảnh:

S → SS
S → (S)
S → ()

Phía bên trái của mọi quy tắc bao gồm một thiết bị đầu cuối duy nhất (trong trường hợp này là luôn luôn S, nhưng có thể có nhiều hơn.)

Bây giờ hãy xem xét ngữ pháp khác này nhận ra các chuỗi có dạng {a ^ nb ^ nc ^ n: n> = 1} (ví dụ: "abc", "aabbcc", "aaabbbccc"):

S  → abc
S  → aSBc
cB → WB
WB → WX
WX → BX
BX → Bc
bB → bb

Nếu không phải Blà thiết bị đầu cuối đi trước ký tự đầu cuối / nghĩa đen c, bạn viết lại thuật ngữ đó thành WBnhưng nếu trước đó b, bạn mở rộng để bbthay thế. Đây có lẽ là điều mà độ nhạy ngữ cảnh của ngữ pháp nhạy cảm ngữ cảnh đang ám chỉ.

Một ngôn ngữ không ngữ cảnh có thể được nhận ra một máy tự động đẩy xuống . Trong khi một máy trạng thái hữu hạn sử dụng không có bộ lưu trữ phụ, tức là quyết định của nó chỉ dựa trên trạng thái hiện tại và đầu vào của nó, một máy tự động đẩy xuống cũng có một ngăn xếp theo ý của nó và có thể lén nhìn vào đầu ngăn xếp để đưa ra quyết định.

Để thấy rằng trong thực tế, bạn có thể phân tích các dấu ngoặc đơn lồng nhau bằng cách di chuyển từ trái sang phải và đẩy một dấu ngoặc trái sang một ngăn xếp mỗi khi bạn gặp một dấu ngoặc đơn và bật lên mỗi khi bạn gặp dấu ngoặc đơn bên phải. Nếu bạn không bao giờ kết thúc việc cố gắng bật ra từ một ngăn xếp trống và ngăn xếp trống ở cuối chuỗi, chuỗi đó là hợp lệ.

Đối với một ngôn ngữ nhạy cảm theo ngữ cảnh, một chiếc PDA không đủ. Bạn sẽ cần một máy tự động giới hạn tuyến tính giống như Máy Turing có băng không giới hạn (mặc dù lượng băng có sẵn tỷ lệ thuận với đầu vào). Lưu ý rằng điều đó mô tả các máy tính khá tốt - chúng tôi muốn nghĩ về chúng như Turing Machines nhưng trong thế giới thực, bạn không thể tự ý lấy thêm RAM giữa chương trình. Nếu bạn không rõ LBA mạnh hơn thế nào so với PDA, LBA có thể mô phỏng một PDA bằng cách sử dụng một phần băng của nó như một chồng, nhưng nó cũng có thể chọn sử dụng băng của nó theo những cách khác.

(Nếu bạn đang tự hỏi Máy trạng thái hữu hạn có thể nhận ra điều gì, thì câu trả lời là biểu thức chính quy. với những hoạt động như [abc], |, *, +, và ?. bạn có thể thấy rằng abbbzphù hợp với regex ab*zchỉ bằng cách giữ vị trí hiện tại của bạn trong chuỗi và regex, không có chồng yêu cầu.)


14
Giải thích rất hay. Mặc dù, băng của máy Turing không cần phải vô hạn, chỉ không giới hạn. Có thể có một nhà máy sản xuất băng ở hai đầu mà khi máy va vào nó, chỉ cần tạo ra nhiều băng hơn. Bằng cách đó, tại bất kỳ thời điểm nào, nó là hữu hạn.
Mike Dunlavey

2
@MikeDunlavey Cảm ơn bạn đã làm rõ, đã sửa nó.
Doval

10
Nhưng nhà máy sản xuất băng sẽ cần vật liệu làm băng vô hạn, hoặc vật liệu làm băng vô hạn, hoặc ... [tràn chồng]
flamingpenguin

8
@Mehrdad: Bạn có thể mô phỏng bất kỳ số lượng ngăn xếp nào bằng cách sử dụng hai ngăn xếp: giữ tất cả các ngăn xếp chồng lên nhau trên một ngăn xếp và khi bạn cần truy cập một số ngăn xếp tiếp theo, hãy tắt các ngăn xếp phía trên và đẩy chúng lên ngăn xếp thứ hai. Điều này chứng tỏ rằng n> 2 ngăn xếp không mạnh hơn 2 ngăn xếp. Bây giờ, liệu 2 ngăn xếp có mạnh hơn 1 ngăn xếp hay không, mà tôi không biết. Trực giác của tôi nói không, nhưng điều đó có thể phụ thuộc vào chính xác các nguyên thủy ngăn xếp là gì.
Jörg W Mittag

10
@ JörgWMittag: hai ngăn xếp tốt như một cuộn băng. Hand-wavily: sử dụng một ngăn xếp làm mặt trái của băng và ngăn xếp khác làm mặt phải, liên quan đến vị trí hiện tại của bạn. Vì vậy, 2-PDA là một máy Turing. Đối với người nguyên thủy, bạn chỉ cần có thể bật một giá trị từ một ngăn xếp và đẩy nó lên ngăn xếp khác, đó là cách bạn di chuyển dọc theo băng của mình.
Steve Jessop

20

Các câu trả lời khác khá dài, ngay cả khi chính xác và chính xác. Đây là phiên bản ngắn.

Nếu bạn có một chuỗi các ký tự (terminal và nonterminals) và bạn muốn thay thế một nonterminal trong chuỗi, một ngữ pháp không ngữ cảnh cho phép bạn làm điều đó bất kể các ký tự xung quanh nonterminal.

Hãy xem xét các quy tắc sau (chữ thường là thiết bị đầu cuối, chữ hoa là số không)

A -> a
AB -> a

Trong quy tắc đầu tiên, bạn có thể thay thế A bất kể những gì xuất hiện xung quanh nó (bối cảnh). Trong quy tắc thứ hai, bạn không thể thay thế Atrừ khi nó được tuân theo B. Trong khi cả hai nonterminals sẽ được thay thế trong trường hợp đó, điểm quan trọng là các nonterminals xung quanh Avấn đề. Người ta không thể thay thế BAbằng a, hoặc Bbằng a: chỉ Atheo sau bởi Bvì thứ tự, bối cảnh của các phần tử là quan trọng. Điều này có nghĩa là bối cảnh của một vấn đề khác thường trong quy tắc thứ hai, làm cho nó nhạy cảm với bối cảnh, trong khi quy tắc đầu tiên là không có ngữ cảnh.


Đây là một lời giải thích thực sự tốt, mặc dù tôi không đủ điều kiện để chứng minh cho tính chính xác hoặc tính đầy đủ của nó. Có phải tất cả là có nó?
rick

1
Ngữ pháp máy tính là một phần của hệ thống phân cấp Chomsky . Bài viết đó là một nơi tốt để bắt đầu. Ngoài ra, chủ đề này nên là một phần của bất kỳ chương trình tú tài nào trong khoa học máy tính. Ít nhất, các trường đại học nên dạy ngữ pháp thường xuyên và không có ngữ cảnh vì chúng bao gồm phần lớn các ngôn ngữ mà các lập trình viên chúng ta có thể gặp phải.

@Snowman: Rất sắc nét. Sẽ tốt hơn nếu bạn nói rằng "bạn không thể xuất phát atừ ABtrừ khi Ađược theo sau Bthay vì nói" bạn không thể thay thế A"có thể là không thể bởi vì thực sự bạn đang thay thế ABkhông phải không?
justin

@justin đúng. Tôi cập nhật câu trả lời của tôi để rõ ràng hơn về điều này.

@Snowman: Bạn có nghĩa là thay thế Ahoặc ABtrong quy tắc thứ hai (nhạy cảm theo ngữ cảnh)? Tôi nghĩ bạn vẫn đang cố gắng thay thế Anhư đã nói từ câu trả lời của mình.
justin

7

Để hiểu được sự khác biệt và các thuật ngữ tốt hơn, đó là một ý tưởng tốt để tương phản một ngôn ngữ bối cảnh tự do như một n b n với một bối cảnh nhạy cảm như một n b n c n . (Ký hiệu: a, b và c là các chữ ở đây và số mũ n có nghĩa là lặp lại n lần chữ , n > 0, nói.) Ví dụ, aabbchoặc aabbbcckhông có trong ngôn ngữ sau, trong khi đó aabbcclà.

Người chấp nhận ngôn ngữ không ngữ cảnh a n b n có thể hợp đồng một cặp abbất kể những gì xung quanh nó (nghĩa là bất kể bối cảnh nào ab xuất hiện) và nó sẽ hoạt động chính xác, chỉ chấp nhận các chuỗi trong ngôn ngữ và từ chối mọi thứ khác, tức là ngữ pháp S -> aSb | ab. Lưu ý rằng không có thiết bị đầu cuối ở phía bên trái của (các) sản xuất . (Có hai quy tắc sản xuất, nhưng chúng tôi chỉ viết chúng một cách gọn gàng.) Người chấp nhận về cơ bản có thể đưa ra quyết định không ngữ cảnh cục bộ.

Ngược lại, bạn không thể làm một cái gì đó như thế cho ngôn ngữ context-sensitive một n b n c n , bởi vì đối với thứ hai bạn phải nhớ bằng cách nào đó bối cảnh mà bạn đang ở, tức là bao nhiêu co thắt của ab bạn làm gì để kết hợp chúng với co thắt của bc. Một ngữ pháp cho ngôn ngữ sau là

S -> abc | aBSc
Ba -> aB
Bb -> bb

Lưu ý rằng bạn có cả thiết bị đầu cuối và không đầu cuối ở bên trái trong hai quy tắc cuối cùng. Các thiết bị đầu cuối bên trái là bối cảnh trong đó các thiết bị đầu cuối có thể được mở rộng.


Bootnote liên quan đến thuật ngữ "hợp đồng" so với "mở rộng", v.v .: mặc dù các ngữ pháp chính thức là [chính thức, hah], cách mà chúng thực sự được thực hiện trong trình phân tích cú pháp thực sự là khử, tức là về cơ bản bạn liên hệ với mọi thứ với một thiết bị đầu cuối áp dụng các quy tắc "ngược lại", đó là lý do tại sao ngay cả ngữ pháp đầu tiên được đưa ra ở trên cũng không thực tế trong một chương trình (nó sẽ cung cấp cho bạn xung đột giảm ca nổi tiếng vì bạn không thể quyết định áp dụng quy tắc nào), nhưng hai quy tắc trên ngữ pháp đủ để minh họa sự khác biệt giữa bối cảnh không nhạy cảm và bối cảnh nhạy cảm. Vấn đề không rõ ràng trong ngữ pháp không ngữ cảnh khá phức tạp và không thực sự là chủ đề của câu hỏi này nên tôi sẽ không nói thêm ở đây, đặc biệt là vì Wikipedia có một bài viết khá hay về điều đó. Ngược lại, các bài viết của nó về ngôn ngữ không ngữ cảnh và đặc biệt là bài viết về ngôn ngữ nhạy cảm ngữ cảnh là! @ # $ @! # $ Đặc biệt nếu bạn chưa quen với chủ đề này ... Tôi đoán đó là nhiều hơn trong danh sách TODO của tôi.


5

Các câu trả lời trên cho một định nghĩa khá tốt về nó là gì. Hãy xem liệu tôi có thể đặt nó bằng từ ngữ của mình không, để bạn có 23 lời giải thích thay vì 20. Toàn bộ mục đích của một ngữ pháp, bất kỳ ngữ pháp nào, là tìm hiểu xem một câu cụ thể có phải là một câu trong ngôn ngữ đã cho không. Tuy nhiên, những gì chúng tôi thực sự sử dụng ngữ pháp và phân tích cú pháp là để tìm ra ý nghĩa của câu. Nó giống như sơ đồ cũ của một câu bạn có thể hoặc không thể học lại trong lớp tiếng Anh ở trường. Một câu được tạo thành từ một phần chủ ngữ và một phần vị ngữ, một phần chủ đề có một danh từ và có thể một số tính từ, một phần vị ngữ có một động từ và có lẽ là một danh từ đối tượng, với một số tính từ, v.v.

Nếu có một ngữ pháp cho tiếng Anh (và tôi không nghĩ là có, không phải theo nghĩa khoa học máy tính) thì nó sẽ có các quy tắc của hình thức sau đây, được gọi là sản phẩm.

Sentence -> SubjectPart PredicatePart
SubjectPart -> Adjective Noun

Vân vân...

Sau đó, bạn có thể viết một chương trình và đưa cho nó bất kỳ câu nào, và chương trình có thể sử dụng ngữ pháp để tìm ra phần nào của câu mỗi từ và mối quan hệ giữa chúng với nhau.

Nếu trong mỗi sản xuất, chỉ có một điều ở phía bên trái, thì điều đó có nghĩa là bất cứ khi nào bạn nhìn thấy phía bên phải trong câu, bạn được phép thay thế ở phía bên trái. Chẳng hạn, bất cứ khi nào bạn thấy danh từ tính từ, bạn có thể nói "Đó là một Chủ đề" mà không cần chú ý đến bất cứ điều gì bên ngoài cụm từ đó.

Tuy nhiên, tiếng Anh (ngay cả mô tả đơn giản về tiếng Anh tôi đã nêu ở trên) rất nhạy cảm với ngữ cảnh. "Danh từ tính từ" không phải lúc nào cũng là một Chủ đề, nó có thể là một Danh từ trong một Dự đoán. Nó phụ thuộc vào ngữ cảnh. Hãy mở rộng ngữ pháp giả tiếng Anh của chúng tôi một chút:

Sentence -> SubjectPart PredicatePart
SubjectPart -> Adjective Noun
PredicatePart -> VerbPhrase ObjectNounPhrase
VerbPhrase ObjectNounPhrase -> VerbPhrase Adjective Noun

Bạn chỉ có thể biến "danh từ tính từ" thành ObjectNounPhrase nếu nó xuất hiện ngay sau VerbPhrase.

Về cơ bản, nếu bạn có một sản phẩm và bạn có thể áp dụng nó bất cứ lúc nào bạn muốn, bất kể điều gì xung quanh nó, nó không có ngữ cảnh.

Bạn luôn có thể biết nếu một ngữ pháp là ngữ cảnh miễn phí dễ dàng. Chỉ cần kiểm tra nếu có nhiều hơn một biểu tượng ở bên trái của mũi tên.

Bất kỳ ngôn ngữ có thể được mô tả bởi nhiều hơn một ngữ pháp. Nếu một số ngữ pháp cho một ngôn ngữ là không có ngữ cảnh, thì ngôn ngữ đó là ngữ cảnh miễn phí. Nó có thể được chứng minh cho một số ngôn ngữ rằng không có ngữ pháp không ngữ cảnh có thể. Tôi cho rằng có thể có một ngữ pháp không ngữ cảnh cho tập hợp giả tiếng Anh đơn giản mà tôi đang mô tả ở trên.

Về lý do tại sao nó quan trọng, nó đòi hỏi một loại chương trình đơn giản hơn để phân tích ngữ pháp không ngữ cảnh. Như đã lưu ý trong các câu trả lời khác, nó không đòi hỏi toàn bộ sức mạnh của máy Turing để phân tích ngữ pháp không ngữ cảnh. Một trình phân tích cú pháp lookahead LR (1) (là một loại máy đẩy xuống) cho một ngữ pháp không ngữ cảnh cụ thể có thể phân tích bất kỳ câu nào trong ngữ pháp đó theo thời gian và không gian tuyến tính theo độ dài của câu. Nếu câu trong ngôn ngữ, trình phân tích cú pháp sẽ tạo ra một cây cấu trúc xác định ý nghĩa của từng biểu tượng trong câu (hoặc ít nhất là phần nào nó đóng trong cấu trúc). Nếu câu không có trong ngữ pháp, trình phân tích cú pháp sẽ chú ý và dừng lại ở ký hiệu đầu tiên không thể đối chiếu với ngữ pháp và các ký hiệu trước (trên "lỗi" đầu tiên).

Điều tuyệt vời hơn nữa là có những chương trình mà bạn có thể đưa ra một mô tả về ngữ pháp và một danh sách các hướng dẫn về những việc cần làm với mỗi phần (theo nghĩa là gắn "ý nghĩa" cho mỗi sản phẩm) và chương trình sẽ viết trình phân tích cú pháp cho bạn. Chương trình sẽ phân tích cú pháp câu, tìm cấu trúc và chạy hướng dẫn của bạn trên từng phần của cấu trúc. Loại chương trình này được gọi là trình phân tích cú pháp hoặc trình biên dịch-trình biên dịch.

Loại phân tích ngôn ngữ này được phát minh để phân tích tự động ngôn ngữ tự nhiên (như tiếng Anh) nhưng hóa ra điều này hữu ích nhất để phân tích ngôn ngữ máy tính. Một nhà thiết kế ngôn ngữ có thể viết một ngữ pháp nắm bắt ngôn ngữ mới của anh ta, sau đó chạy nó thông qua trình tạo trình phân tích cú pháp để có được một chương trình phân tích ngôn ngữ của anh ta, và dịch, phiên dịch, biên dịch, thực thi, v.v. nếu anh ta muốn.

Trong thực tế, trong hầu hết các trường hợp, bạn không thể thực sự làm điều này. Chẳng hạn, dấu ngoặc đơn cân bằng là một ngôn ngữ không có ngữ cảnh, nhưng một ngôn ngữ bắt buộc phải khai báo tất cả các biến trước khi bạn sử dụng chúng là phân biệt ngữ cảnh. Trình phân tích cú pháp là một phần của trình biên dịch, nhưng cần có logic bổ sung để thực thi các yêu cầu khác này. Những gì bạn phải làm là viết một ngữ pháp nắm bắt càng nhiều ngôn ngữ của bạn càng tốt, chạy nó thông qua một trình tạo trình phân tích cú pháp, sau đó viết mã thực thi phần còn lại của các yêu cầu (trình xử lý bảng biểu tượng, v.v.).

Chúng tôi thường không sử dụng các ngữ pháp nhạy cảm theo ngữ cảnh vì chúng được hỗ trợ kém hơn nhiều. Tôi không biết liệu có tương đương với trình tạo trình phân tích cú pháp LR (k) cho các ngôn ngữ nhạy cảm theo ngữ cảnh hay không. Đúng, một máy Turing (hoặc máy bị ràng buộc tuyến tính) có thể phân tích cú pháp, nhưng tôi không biết liệu có một thuật toán chung để biến ngữ pháp nhạy cảm ngữ cảnh thành một chương trình cho máy Turing hay không, theo nghĩa là một LR (1 ) máy phát điện làm bảng phân tích cú pháp cho máy đẩy xuống. Tôi đoán là các bảng làm nền tảng cho trình phân tích cú pháp sẽ lớn hơn theo cấp số nhân. Trong mọi trường hợp, sinh viên CS (như bản thân tôi, hồi trước) thường được dạy các ngữ pháp không ngữ cảnh và trình tạo trình phân tích cú pháp LR (1) như YACC.


-1

Ngữ pháp không ngữ cảnh không xem xét bất kỳ bối cảnh nào cho quy tắc sản xuất. Bối cảnh là thiết bị đầu cuối hoặc không thiết bị đầu cuối.

Vì vậy: Các ngữ pháp không có ngữ cảnh chỉ có một đầu cuối duy nhất ở bên trái của quy tắc sản xuất.


3
Điều này thêm gì vào câu trả lời hiện có? Ngoài ra, một quy tắc sản xuất có hai hoặc nhiều thiết bị đầu cuối ở phía bên trái cũng không phải là bối cảnh miễn phí.

Tôi nghĩ rằng các câu trả lời đã cho là quá dài. Nếu ai đó thêm TL; DR, tôi sẽ xóa cái này.
Martin Thoma

Đẹp! Bạn có nói rằng "bối cảnh" là các ký tự phụ đủ điều kiện khi mỗi quy tắc sản xuất có thể được áp dụng không?
rick
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.