Những mô hình tính toán có thể được thể hiện thông qua ngữ pháp?


18

Đây là một sự cải tổ của các chương trình ngữ pháp? hỏi trước bởi Vag và với nhiều lời đề nghị từ các bình luận viên.

Bằng cách nào một ngữ pháp có thể được xem là chỉ định một mô hình tính toán? Ví dụ, nếu chúng ta sử dụng một ngữ pháp không ngữ cảnh đơn giản, chẳng hạn như

G ::= '1' -> '0' '+' '1'
      '1' -> '1' '+' '0'
      '2' -> '2' '+' '0'
      '2' -> '1' '+' '1'
      '2' -> '0' '+' '2'
      '3' -> '3' '+' '0'
      '3' -> '2' '+' '1'
      '3' -> '1' '+' '2'
      '3' -> '1' '+' '2'

Giả sử rằng trình phân tích cú pháp không phân biệt giữa các ký hiệu đầu cuối hiệu đại diện như tôi đã trình bày ở đây, thì có thể thực hiện số học đơn giản cho các số có tới 3.

Ví dụ: lấy chuỗi

"2 + 0 + 1"

Chạy trình phân tích cú pháp LR (1) trên chuỗi này sẽ cung cấp cho chúng ta cây cú pháp cụ thể sau đây trong đó kết quả tính toán được lưu trữ ở gốc của cây:

           '3'
         /  |  \
        /   |   \
      '2'  '+'  '1'
     / | \
    /  |  \
  '2' '+' '0' 

Vì vậy, nếu chúng ta lấy một ngữ pháp làm chương trìnhtrình tạo trình phân tích cú pháp để làm trình biên dịch , chúng ta có thể xem ngôn ngữ đặc tả ngữ pháp như một ngôn ngữ lập trình không?

Hơn nữa, chúng ta có thể xây dựng các chương trình Turing- Complete bằng cách chỉ định ngữ pháp tương tự như cách bạn có thể xây dựng các chương trình hoàn chỉnh với celullar automata hoặc phép tính lambda không?

Nói cách khác, người ta biết rằng trong ý nghĩa nhận biết một ngôn ngữ, các ngôn ngữ thông thường tương ứng với automata trạng thái hữu hạn , các ngôn ngữ không ngữ cảnh tương ứng với tự động đẩy xuốngcác ngôn ngữ nhạy cảm ngữ cảnh tương ứng với automata giới hạn tuyến tính . Tuy nhiên, nếu chúng ta xem ngữ pháp như các thiết bị tính toán (nghĩa là các chương trình theo nghĩa của ví dụ trên), thì làm thế nào để chúng ta phân loại sức mạnh tính toán của từng lớp ngữ pháp trong hệ thống phân cấp Chomsky?

Ngoài ra, làm thế nào về các lớp con ngữ pháp ít được biết đến như,

EDIT: Nhân tiện , đây là một câu hỏi của riêng tôi nhưng tôi không đề cập đến việc tôi không đưa ra biểu tượng bắt đầu cho ngữ pháp ví dụ và vẫy tay khi cần phân biệt giữa thiết bị đầu cuối và số không. Về mặt kỹ thuật hoặc truyền thống, tôi nghĩ rằng ngữ pháp có thể phải được viết ở dạng phức tạp hơn như thế này (trong đó S là ký hiệu bắt đầu và $ đại diện cho thiết bị đầu cuối cuối luồng):

G ::= S -> R0 '$'
      S -> R1 '$'
      S -> R2 '$'
      R0 -> '0'
      R0 -> R0 '+' '0'
      R1 -> '1'
      R1 -> R0 '+' '1'
      R1 -> '1' '+' R0
      R1 -> R0 '+' '1' '+' R0
      R2 -> '2'
      R2 -> R0 '+' '2'
      R2 -> '2' '+' R0
      R2 -> R0 '+' '2' '+' R0
      R2 -> R1 '+' '1'
      R2 -> R1 '+' '1' '+' R0

... không phải là nó thực sự thay đổi bất cứ điều gì, nhưng tôi nghĩ tôi nên đề cập đến nó.

EDIT: Một điều khác xuất hiện trong đầu tôi khi tôi đọc câu trả lời của gasche là mỗi nhánh trong cây trong ví dụ của tôi đại diện cho một tính toán phụ. Nếu bạn xem mỗi quy tắc sản xuất là một hàm trong đó LHS biểu thị kết quả và RHS đại diện cho các đối số của nó, thì cấu trúc của ngữ pháp xác định cách các hàm được tạo.

Nói cách khác, bối cảnh của trình phân tích cú pháp cùng với cơ chế nhìn của nó giúp xác định không chỉ các hàm nào được áp dụng ('giống như đa hình tham số) mà còn nên kết hợp chúng như thế nào để tạo thành các hàm mới.

Ít nhất, tôi đoán bạn có thể nhìn nó theo cách này cho CFG rõ ràng, đối với các ngữ pháp khác, thể dục dụng cụ tinh thần là một chút quá nhiều đối với tôi ngay bây giờ.


3
Bạn đã quên đề cập đến Automaton Pushdown Automaton (Nested Words), một thiết bị đáng yêu và đầy hứa hẹn như vậy! Điều này rất quan trọng vì dường như là sự cải thiện tối thiểu so với biểu thức chính quy để có thể phân tích các chương trình được viết bằng các ngôn ngữ lập trình phổ biến. ( cis.upenn.edu/~alur/nw.html )
Vag

1
Cảm ơn, điều đó rất thú vị, tôi đã không tìm kiếm nó! Có một vài người khác tôi cũng bỏ qua như không có bối cảnh xác định, liền kề cây, được lập chỉ mục, v.v., tôi chỉ nghĩ rằng nó có thể là một chút nhiều cho một câu hỏi ... Nhưng có lẽ tôi sẽ thêm chúng
Rehno Lindeque

1
@imz Ý tôi là ngữ pháp vì chúng được định nghĩa chính thức trong hệ thống phân cấp chomsky (Nghĩa là bộ sản phẩm). Vì tôi đang khẳng định chính xác những gì bạn đang nói: ngữ pháp là chương trình, nó chỉ có nghĩa là lớp chương trình được biểu thị bằng ngữ pháp (đó là câu hỏi).
Rehno Lindeque

1
@imz Thành thật mà nói, tôi thực sự không quen thuộc với các ngữ pháp được lập chỉ mục, tôi chỉ thêm chúng dưới dạng suy nghĩ sau.
Rehno Lindeque

1
Tôi bắt đầu nghĩ rằng có lẽ nên gửi câu hỏi này lên diễn đàn LtU thay vì nhìn vào các cuộc thảo luận thú vị: P. Btw @imz, có lẽ tốt nhất nên đọc câu hỏi là "lớp ngữ pháp nào tương ứng với lớp chương trình nào theo nghĩa" chức năng "được mô tả bởi Jukka trong câu trả lời của Marc Hamman". Có lẽ tôi nên làm rõ hơn điều này mặc dù ...
Rehno Lindeque

Câu trả lời:


10

Có một sự tương ứng một-một giữa ngữ pháp Chomsky Type-0 và máy Turing.

Điều này được khai thác bằng ngôn ngữ lập trình Thue , cho phép bạn viết các chương trình hoàn thành Turing được chỉ định bởi một chuỗi ban đầu và một bộ quy tắc viết lại chuỗi (một ngữ pháp bán Thue , tương đương với ngữ pháp loại 0).

CẬP NHẬT:

Khác với các ngôn ngữ "Turing tar-pit" bí mật như Thue, các ngôn ngữ có mục đích chung khác nhau cho phép lập trình viên mở rộng cú pháp của riêng họ có thể được sử dụng để thực hiện tính toán Turing-Complete trong giai đoạn biên dịch phân tích cú pháp.

Các ngôn ngữ trong họ Lisp , đặc biệt là Common Lisp , có lẽ là ví dụ rõ ràng nhất, nhưng nói rộng ra, các ngôn ngữ có kiểm tra kiểu tĩnh không cần phải dừng lại, chẳng hạn như C ++ với các mẫu , ScalaQi .


Nhưng câu hỏi là về những thứ hoạt động theo cách khác: người ta nên đi đến kết quả không phải bằng cách viết lại một chuỗi ký hiệu ban đầu theo quy tắc, nhưng "kết quả" của tính toán được xác định bởi một ngữ pháp trong câu hỏi này là một chữ cái đầu tiên biểu tượng có thể tạo ra chuỗi "đầu vào" theo các quy tắc của ngữ pháp.
imz - Ivan Zakharyaschev

2
Nhưng, nếu tôi hiểu chính xác, hai điều về cơ bản là tương đương nhau: Nếu và chỉ khi, bắt đầu từ một ký hiệu ban đầu cố định, ngữ pháp có thể tạo ra chuỗi đầu vào, thì máy Turing sửa lỗi chấp nhận trên chuỗi đó. Nếu bạn muốn xem xét các tính toán trả về một kết quả khác ngoài chấp nhận / từ chối, nhưng vẫn trong một tập hợp hữu hạn, bạn phải thêm một đoạn chọn không đặc trưng của biểu tượng ban đầu (thực ra, đó chỉ là một quy tắc bổ sung). Để cho phép kết quả trong một tập hợp vô hạn, bạn có thể xác định một ngữ pháp tạo chuỗi iff . T M ( i n ) = o u tconcat(quote(in),out)TM(in)=out
Antonio Valerio Miceli-Barone

Tôi đồng ý rằng sự tương ứng giữa ngữ pháp Type0 và TM là câu trả lời hợp lệ cho câu hỏi (đặc biệt, nếu bị hạn chế tính toán có / không có chức năng). Gợi ý thêm để mô hình hóa một TM tùy ý với một ngữ pháp bằng cách giới thiệu một số quy ước làm thế nào để biểu diễn các cặp đầu vào-đầu ra dường như không phù hợp với mối quan tâm dự định của câu hỏi ban đầu: (được tiếp tục)
imz - Ivan Zakharyaschev

Tôi hiểu nó như một câu hỏi để khai thác chính xác các khung ngữ pháp hiện có và các trình phân tích cú pháp tương ứng để thực hiện các tính toán, nghĩa là hình thức dịch được cho phép giữa một hàm f và một ngữ pháp chỉ có thể là: một đầu vào tôi được phân tích cú pháp là S có nghĩa là f ( I) = S.
imz - Ivan Zakharyaschev

1
Nhìn bề ngoài, ngôn ngữ lập trình Thue dường như không rơi vào loại sử dụng khung ngữ pháp này: mặc dù nó có các quy tắc viết lại như ngữ pháp, việc tính toán kết quả từ đầu vào đi theo hướng của quy tắc, chứ không phải ngược lại hướng, như Rehno muốn. (Nhưng có lẽ đó chỉ là vấn đề thay đổi hướng mũi tên trong các sản phẩm: dịch một ngữ pháp "tính toán như một trình phân tích cú pháp" theo nghĩa của Q này thành Thue chỉ có thể thay đổi hướng của các quy tắc, sau đó là chương trình Thue sẽ đến các biểu tượng bắt đầu như kết quả thực sự, phải không? ..)
imz - Ivan Zakharyaschev

6

Câu trả lời của tôi không có ý định chính thức, chính xác và hoàn toàn trong chủ đề. Tôi nghĩ câu trả lời của Marc Hamman rất vững chắc, nhưng câu hỏi của bạn khiến tôi nghĩ về một chủ đề liên quan.

Ngữ pháp có thể được coi là trường hợp đặc biệt của các hệ thống suy diễn: đầu vào là một phán đoán và cây phân tích là một dẫn xuất của phán đoán hoặc bằng chứng cho thấy phán đoán đó là hợp lệ theo các quy tắc (ngữ pháp).

Theo nghĩa đó, câu hỏi của bạn có thể liên quan đến cách tiếp cận của một phần của cộng đồng tìm kiếm lập trình / chứng minh logic ( ví dụ tôi nghĩ về Dale Miller ), đó là tìm kiếm bằng chứng có nội dung tính toán, trái ngược với cổ điển hơn quan điểm lý thuyết loại / bằng chứng trong đó tính toán là chuẩn hóa bằng chứng .

Lưu ý: đọc lại câu trả lời của tôi, tôi nghĩ ý tưởng rằng "xây dựng cây phân tích là tìm kiếm bằng chứng" là một chút xa vời ở đây. Tìm kiếm bằng chứng thay vì chảy theo hướng khác: bắt đầu từ một phán đoán khá phức tạp và bằng cách sử dụng lặp lại các quy tắc suy luận làm việc trên cấu trúc của bằng chứng, người ta hy vọng đạt được các tiên đề đơn giản hơn mà không cần phải chứng minh thêm. Vì vậy, sẽ tự nhiên hơn khi thấy, về mặt ngữ pháp, các phán đoán phức tạp là không phải thiết bị đầu cuối, nguyên tử là thiết bị đầu cuối và tìm kiếm bằng chứng như một vấn đề tạo từ hoặc kiểm tra không trống rỗng.


Nhận xét rất thú vị mặc dù. Bộ não của tôi đã quá mệt mỏi để đưa ra một phản ứng tốt ngay bây giờ, tuy nhiên trong ví dụ của tôi, các nhánh của cây đại diện cho các tính toán phụ được kết hợp với nhau theo các quy tắc phân tích cú pháp ...
Rehno Lindeque

6

Hơn nữa, chúng ta có thể xây dựng các chương trình Turing-Complete bằng cách chỉ định ngữ pháp không?

Tôi không chắc liệu tôi có hiểu chính xác câu hỏi của bạn không, nhưng nếu bạn đang tìm kiếm một ngôn ngữ lập trình dựa trên một loại hệ thống viết lại chuỗi, có lẽ bạn sẽ được xen vào Refal , dựa trên chính thức thuật toán Markov (Turing- chủ nghĩa hình thức hoàn chỉnh cũng là một hệ thống viết lại chuỗi giống như ngữ pháp).


1
Tôi hiểu câu hỏi theo cách sau: Rehno quan tâm đến quá trình phân tích cú pháp khởi động (được xác định bởi một ngữ pháp) để được xem như là một tính toán của kết quả. Việc tính toán nên xây dựng kết quả từ các phần đi theo hướng ngược lại với quy tắc sản xuất của ngữ pháp. Các quy tắc viết lại của Refal (IIUC, tương tự như ngôn ngữ lập trình Thue đã đề cập ở trên) sẽ đi theo hướng khác (từ đầu vào đến kết quả).
imz - Ivan Zakharyaschev

Bây giờ tôi nghĩ về nó, ngữ pháp nhạy cảm ngữ cảnh có nhiều hơn một biểu tượng trên LHS của quy tắc sản xuất. Vì vậy, tôi nghĩ rằng không có sự khác biệt thực tế thực tế. Một trình phân tích cú pháp cho một ngôn ngữ nhạy cảm theo ngữ cảnh sẽ là một hệ thống viết lại chuỗi cho dù bạn nhìn nó như thế nào?
Rehno Lindeque

@imz cảm ơn bạn đã làm rõ câu hỏi của Rehno. @Rehno Cảnh Một trình phân tích cú pháp cho một ngôn ngữ nhạy cảm theo ngữ cảnh sẽ là một hệ thống viết lại chuỗi cho dù bạn nhìn nó như thế nào? Nhưng - nó có thể có ý nghĩa, vâng.
Artem Pelenitsyn

Nhưng các quy tắc viết lại của Refal có được xử lý không xác định không? (Hoặc đặt khác nhau: sẽ Refal thực hiện quay lui trong tìm kiếm đường dẫn viết lại hoạt động?) Nếu chúng ta muốn mô hình hóa phương pháp "phân tích như tính toán" này với các quy tắc viết lại theo hướng ngược lại, chúng ta cần các quy tắc không xác định; xem xét một ngữ pháp như S -> A a; S -> B b; A -> 0; B -> 0. Nếu chúng tôi lập trình điều này bằng cách đảo ngược các quy tắc, chúng tôi sẽ cần chọn các quy tắc khác nhau để xử lý 0trong thời gian chạy để đánh giá "0a" hoặc "0b" thành S.
imz - Ivan Zakharyaschev

6

(Chỉ là một số cân nhắc tầm thường. Có thể là một nhận xét, nhưng quá dài.)

Trong thực tế, những gì bạn mô tả có hiệu lực như một quan điểm rất tự nhiên về ngôn ngữ là gì (theo cách hiểu của con người về "ngôn ngữ", mục đích của nó) và cách một ngữ pháp định nghĩa một ngôn ngữ.

Một ngôn ngữ bao gồm (vô số) các hình thức cú pháp chính xác được diễn giải để đưa ra các giá trị ngữ nghĩa .

Nếu việc giải thích là có thể tính toán được, thì các hình thức cú pháp của một ngôn ngữ có thể được xem như các chương trình tính toán các giá trị ngữ nghĩa.

Nếu chúng ta giả sử rằng một ngôn ngữ được triển khai như một thiết bị hữu hạn, chúng ta có thể gọi đại diện hữu hạn này của ngôn ngữ là "ngữ pháp". Theo cách hiểu này, một ngữ pháp quan tâm đến cú pháp, mà còn về ngữ nghĩa, nghĩa là cách tính giá trị ngữ nghĩa của toàn bộ biểu thức từ các giá trị của các phần của nó (các phần nguyên tử và giá trị của chúng được lưu trữ trong một "từ vựng") .

Một số lý thuyết về ngôn ngữ tự nhiên có dạng như vậy (dạng phù hợp với các cân nhắc ở trên; nó đã được đề cập trong câu trả lời của @ gasche ở đây): một hệ thống suy luận tìm kiếm một dẫn xuất của đầu vào (kết hợp với tính toán của ngữ nghĩa giá trị, hoặc việc xây dựng thuật ngữ bằng chứng; xem thư từ Curry-Horward). Vì vậy, nếu chúng ta xem xét các hệ thống như thế và coi chúng là ngữ pháp, thì câu hỏi của bạn là tầm thường : các hệ thống này được nghĩ ra chính xác để thực hiện các tính toán theo cách bạn mô tả.

fGI f(I)=SISG )?

(Trên thực tế, các trình biên dịch thực sự cho các ngôn ngữ lập trình trông giống như một hệ thống có cả cú pháp và ngữ nghĩa: chúng biến đổi hình thức cú pháp của chương trình thành một tệp thực thi, đó là ý nghĩa ngữ nghĩa của chương trình, chứ không chỉ đơn thuần là biểu tượng bắt đầu của ngữ pháp.)


4

Chỉ cần thêm:

Một chương trình logic thuần túy có đọc khai báo và đọc thủ tục. Báo cáo này thảo luận về ý tưởng rằng những điều này có thể được bổ sung bằng cách đọc ngữ pháp, trong đó các mệnh đề được coi là viết lại các quy tắc của một ngữ pháp. Mục tiêu là chỉ ra rằng quan điểm này tạo điều kiện chuyển giao chuyên môn từ lập trình logic sang nghiên cứu khác về ngôn ngữ lập trình và ngược lại. Một số ví dụ như một sự chuyển giao được thảo luận. Mặt khác, quan điểm ngữ pháp được trình bày biện minh cho một số phần mở rộng ad hoc để lập trình logic thuần túy và tạo điều kiện phát triển nền tảng lý thuyết cho các phần mở rộng đó.

Một cái nhìn ngữ pháp về lập trình logic của Pierre Deransart và Jan Maluszynski.


Rõ ràng, Prolog nảy sinh từ ngữ pháp thuộc tính, vì vậy quan điểm này là thứ bắt đầu lập trình logic.
Revierpost

1

Điều gì về những thứ như số Peano:

S    -> int
int  -> zero
int  -> succ
zero -> "0"
succ -> "#" int

nó sẽ nhận ra bất kỳ chuỗi (số) nào của mẫu này:

0   // zero
#0  // one
##0 // two

và nó sẽ trả về một cấu trúc lồng nhau, với độ sâu là số.

Nhưng nó bắt đầu trở nên phức tạp khi người ta muốn thực hiện chỉ cần nói thêm:

S    -> int
int  -> sum
int  -> zero
int  -> succ
zero -> "0"
succ -> "#" int
sum  -> int "+" int

Nó có ý nghĩa hoàn hảo ở chỗ nó sẽ chỉ nhận ra các int hình thành tốt như thế này:

#####0 + ####0

Nhưng ngữ pháp này giới thiệu một phân chia trong cây phân tích bất cứ khi nào có một tổng, vì vậy thay vì có một cây một nhánh đẹp, trực tiếp ánh xạ tới một số, chúng ta có cấu trúc của biểu thức, vẫn còn một vài tính toán từ hiệu quả giá trị. Vì vậy, không có tính toán được thực hiện, chỉ công nhận. Rắc rối có thể không phải là ngữ pháp mà là trình phân tích cú pháp. Thay vào đó, người ta có thể sử dụng một cái gì đó khác, idk ... Một điểm khác xuất hiện trong tâm trí là sự đầy đủ của hình thức ngữ pháp để diễn đạt tính toán. Khi bạn xem một tiên đề của Peano (theo ký hiệu giống Haskell):

1) Nat = Zero
2) Nat = Succ Nat
3) Sum ( Succ X ) ( Y ) = Succ ( X + Y )
4) Sum Zero X = X

Quy tắc thứ ba nêu rõ một sự chuyển đổi. Bất cứ ai cũng có thể tưởng tượng để mang cùng một ý nghĩa trong một quy tắc ngữ pháp không ngữ cảnh. Và nếu vậy thì thế nào!?

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.