Tôi đã luôn nghĩ rằng việc đề cập đến cú pháp của một ngôn ngữ cũng giống như đề cập đến ngữ nghĩa của một ngôn ngữ. Nhưng tôi đã được thông báo rằng rõ ràng đó không phải là trường hợp. Có gì khác biệt?
Tôi đã luôn nghĩ rằng việc đề cập đến cú pháp của một ngôn ngữ cũng giống như đề cập đến ngữ nghĩa của một ngôn ngữ. Nhưng tôi đã được thông báo rằng rõ ràng đó không phải là trường hợp. Có gì khác biệt?
Câu trả lời:
Ngữ nghĩa ~ Ý nghĩa
Cú pháp ~ Đại diện tượng trưng
Vì vậy, hai chương trình được viết bằng các ngôn ngữ khác nhau có thể làm cùng một thứ (ngữ nghĩa) nhưng các ký hiệu được sử dụng để viết chương trình sẽ khác nhau (cú pháp).
Trình biên dịch sẽ kiểm tra cú pháp của bạn cho bạn (lỗi thời gian biên dịch) và rút ra ngữ nghĩa từ các quy tắc ngôn ngữ (ánh xạ cú pháp theo hướng dẫn của máy nói), nhưng sẽ không tìm thấy tất cả các lỗi ngữ nghĩa (lỗi thời gian chạy, ví dụ: tính toán kết quả sai vì mã nói thêm 1 thay vì thêm 2).
x + y
không có +
toán tử thích hợp cho các toán hạng đó). Thêm 1 chứ không phải 2 là những gì tôi gọi là lỗi logic .
Thật ra không có hai cấp mà là ba:
i
và f
tạo ra if
)if
, (
, 42
, ==
, answer
và )
tạo ra một tuyên bố có điều kiện)ValidIdentifier
thiết bị đầu cuối, có thể được định nghĩa là một cái gì đó giống như ![AnyKeyword] [Identifier]
(Tôi đang sử dụng ký hiệu giống PEG ở đây). Bạn không cần một lexing pass riêng cho một ngôn ngữ như vậy. Xem, ví dụ, trình phân tích cú pháp C ++ dựa trên GLR.
Ngữ nghĩa mô tả các thực thể logic của ngôn ngữ lập trình và các tương tác của chúng. Cú pháp định nghĩa cách chúng được thể hiện trong các ký tự.
Ví dụ, khái niệm số học con trỏ là một phần của ngữ nghĩa của C; cách +
và các -
toán tử có thể được sử dụng để thể hiện các hoạt động con trỏ là một phần của cú pháp của nó.
Đôi khi, hai ngôn ngữ chia sẻ một phần ngữ nghĩa của chúng, nhưng cú pháp khác nhau rất nhiều (ví dụ: C # và VB.NET - cả hai đều sử dụng loại giá trị và loại tham chiếu, nhưng các ký tự bạn nhập để xác định chúng là khác nhau); trong các trường hợp khác, hai ngôn ngữ giống nhau về mặt cú pháp, nhưng ngữ nghĩa không khớp nhau (xem xét Java so với JavaScript, trong đó các điểm tương đồng thường gây nhầm lẫn cho người mới bắt đầu).
Cú pháp là cách bạn sắp xếp mã thông báo của ngôn ngữ. Ngữ nghĩa là ý nghĩa của những mã thông báo đó (thông thường, ý nghĩa của sự sắp xếp cụ thể của mã thông báo).
Bạn không chỉ định liệu bạn chỉ đề cập đến ngôn ngữ lập trình hay ngôn ngữ chung được sử dụng trong lập trình, vì vậy câu trả lời của tôi là về ngôn ngữ dữ liệu (như XML, RDF, hệ thống loại dữ liệu, v.v.):
Brian L. Meek trong bảy quy tắc vàng của mình để sản xuất các tiêu chuẩn độc lập với ngôn ngữ (1995) viết rằng "cú pháp của một ngôn ngữ có thể là ngữ nghĩa của ngôn ngữ khác" . Ông đề cập đến các từ "cú pháp" và "ngữ nghĩa" được sử dụng trong mô tả dữ liệu: vì vậy nếu bạn vấp phải những từ này trong một đặc điểm kỹ thuật của một số định dạng dữ liệu, bạn nên thay thế cả hai từ bằng "Potrzebie" để làm rõ rằng bạn phải giải quyết ý nghĩa cho chính mình.
Mối quan hệ giữa cú pháp và ngữ nghĩa, ít nhất là trong dữ liệu được chỉ định chính xác, có thể được mô tả tốt hơn bằng thuật ngữ "mã hóa" . Semantic được mã hóa theo cú pháp. Vì các bản ghi có thể được lồng nhau, cú pháp của một ngôn ngữ là ngữ nghĩa của ngôn ngữ khác. Nếu một người vượt ra ngoài phạm vi dữ liệu, việc lồng nhau này có thể gần như vô hạn, như được mô tả bởi Umberto Eco là "semiosis không giới hạn".
Để đưa ra một ví dụ:
Mọi người thường dừng lại ở một mức độ nào đó và coi nó là ngữ nghĩa, nhưng cuối cùng không có ngữ nghĩa cuối cùng trừ khi một số người giải thích dữ liệu trong tâm trí của anh ta. Ngay khi một người cố gắng diễn đạt ngữ nghĩa dưới dạng dữ liệu, nó sẽ trở thành cú pháp.
Nếu nó có thể được mô tả trong BNF (Backus-Naur Form) hoặc một cái gì đó tương tự, đó là cú pháp. Nếu không thể, thì không.
Mặt khác, ngữ nghĩa là về ý nghĩa của một chương trình (hoặc đoạn mã nguồn khác).
Và đôi khi ranh giới giữa hai người có thể bị mờ.
Một cách để hiểu sự khác biệt là xem xét các loại lỗi bạn gặp phải khi cú pháp hoặc ngữ nghĩa của chương trình không chính xác.
Lỗi cú pháp là lỗi mã nguồn không khớp với ngữ pháp ngôn ngữ, ví dụ, không có dấu chấm phẩy khi bắt buộc phải có dấu chấm phẩy.
Một lỗi ngữ nghĩa là không thể đáp ứng các yêu cầu ngôn ngữ khác (ví dụ, cái mà C gọi là "các ràng buộc"); một ví dụ có thể được viết x + y
ở đâu x
và y
thuộc loại không tương thích. Ngữ pháp ngôn ngữ cho bạn biết rằng một bổ sung trông giống như something + something
, nhưng nó không đủ mạnh để diễn đạt các yêu cầu về các loại toán hạng trái và phải.
(Các lỗi logic, chẳng hạn như sử dụng 1 trong đó 2 sẽ đúng, thường không thể phát hiện được bởi trình biên dịch - mặc dù trong một số trường hợp, trình biên dịch có thể cảnh báo về mã nghi vấn.)
Cú pháp là những gì các ký hiệu (từ vựng) nói. Ngữ nghĩa là những gì họ có nghĩa.
Xem xét:
C #: condition ? true_value : false_value
VB.NET: If(condition, true_value, false_value)
- Cú pháp khác nhau, cùng ngữ nghĩa.
C #: left_value / right_value
VB.NET: left_value / right_value
- Cùng một cú pháp, ngữ nghĩa khác nhau (đối với số nguyên).
Cú pháp là sự sắp xếp ngữ pháp của các từ trong một câu tức là trật tự từ.
(Tiếng Anh) ' cat dog boy ' và (lập trình) ' hi.5 ' không đúng về mặt cú pháp.
(Tiếng Anh) ' mèo ôm cậu bé ' và (lập trình) '* 3.2 * 5 *' có giá trị cú pháp.
Ngữ nghĩa tĩnh là liệu các câu lệnh hợp lệ về mặt cú pháp có bất kỳ ý nghĩa nào không.
(Tiếng Anh) ' Tôi lớn ' (lập trình) (python) ' 3 +' hi ' ' đúng về mặt cú pháp nhưng có lỗi ngữ nghĩa tĩnh.
Ngữ nghĩa là ý nghĩa liên quan đến chuỗi ký hiệu chính xác về mặt cú pháp không có lỗi ngữ nghĩa tĩnh tức là câu đúng về mặt cú pháp và ngữ nghĩa, nhưng ý nghĩa của nó có thể không phải là mục đích.
(Tiếng Anh) ' Máy bay có thể nguy hiểm ' có thể có hai ý nghĩa là bay máy bay có thể nguy hiểm hoặc máy bay đang bay có thể nguy hiểm.
(Lập trình) 'máy tính sẽ không tạo ra bất kỳ thông báo lỗi nào, nhưng nó sẽ không làm những gì bạn bảo nó làm; nó sẽ làm một cái gì đó khác. '
Nguồn : MIT 6,00.1
Cú pháp đề cập đến các quy tắc chính thức điều chỉnh việc xây dựng các câu lệnh hợp lệ trong một ngôn ngữ. Ngữ nghĩa đề cập đến tập hợp các quy tắc đưa ra ý nghĩa của một tuyên bố.
Lỗi do cú pháp xảy ra trong một chương trình khi sự hủy hoại của ngôn ngữ lập trình bị vi phạm hoặc sử dụng sai. Lỗi do ngữ nghĩa xảy ra trong một chương trình khi các câu lệnh không có ý nghĩa.
Trật tự từ là nguyên tắc cơ bản của cú pháp, những người cố gắng hiểu những gì được viết sử dụng các cú pháp cú pháp của trật tự từ để giúp đưa ra cấu trúc câu và ý nghĩa. Ngữ nghĩa là một cách giải thích riêng của cá nhân về ý nghĩa của một "câu" dựa trên kiến thức trước đó của họ. Do đó, một câu dường như không có ý nghĩa cú pháp, có thể có ý nghĩa khi sử dụng các tín hiệu ngữ nghĩa.
Cú pháp chỉ quan tâm đến những gì đúng về mặt ngôn ngữ và ngữ pháp. Ngữ nghĩa đòi hỏi tất cả những kiến thức trước đó, và vượt xa mọi thứ cụ thể về ngôn ngữ.
Câu "Đồ uống sữa cho trẻ em" không có nghĩa cú pháp, nhưng thông qua ngữ nghĩa, hầu hết mọi người sẽ hiểu nó có nghĩa là "Đồ uống cho trẻ em" vì kiến thức trước đây của chúng tôi cho chúng ta biết rằng em bé uống sữa, và do đó chúng ta có thể tìm thấy ý nghĩa từ từ khóa.
Cú pháp và ngữ nghĩa giống như chiến lược và chiến thuật hoặc trái và phải .
Chúng không thực sự là các khái niệm phổ quát độc lập, mà là một cặp từ liên quan mà khi bạn ở trong một bối cảnh cụ thể, chỉ ra các hướng ngược lại. Nhưng điều tương tự đó là chiến lược trên một quy mô là chiến thuật trên quy mô khác.
Vì vậy, nếu bạn đang viết mã bằng một ngôn ngữ, cú pháp là ngôn ngữ bạn đang sử dụng và hành vi mong muốn là ngữ nghĩa. Nhưng nếu bạn đang thực hiện, hoặc thảo luận, trình biên dịch cho ngôn ngữ đó, thì cú pháp là ngữ pháp và có lẽ loại hệ thống và ngữ nghĩa mọi thứ được xây dựng trên đó. Và như vậy.
Cú pháp là những gì máy tính hiểu, ngữ nghĩa là những gì con người hiểu.
Trình biên dịch / trình thông dịch không quan tâm đến thiết kế của bạn và trong bất kỳ mã nào được biên dịch theo cấp độ máy bạn sẽ khó có thể suy ra thiết kế. Các nhà phát triển quan tâm đến thiết kế bởi vì một thiết kế tốt là về việc giảm độ phức tạp bằng cách trừu tượng hóa các hành vi và tương tác phức tạp, và các loại vấn đề khác nhau cho vay theo các ngữ nghĩa khác nhau. Sự lựa chọn ngôn ngữ chủ yếu là về cách dễ dàng và hiệu quả các ngữ nghĩa bạn muốn sử dụng có thể được thể hiện trong cú pháp của nó.
Ví dụ rất ngắn với "plain c":
void main()
{
int a = 10;
int x = a - 1;
int y = - 1;
printf("x = %i", x);
printf("y = %i", y);
getch();
}
Trong ví dụ này, cú pháp của mã thông báo "-" là giống nhau, nhưng, nó có một ý nghĩa khác ("ngữ nghĩa), tùy thuộc vào nơi nó được sử dụng.
Trong phép gán "x", "-" có nghĩa là hoạt động "cơ số", Trong phép gán "y", "-" có nghĩa là hoạt động "dấu âm".
-
toán tử là cùng một mã thông báo , nhưng chúng khác nhau về mặt cú pháp , bởi vì chúng được sử dụng trong các bối cảnh khác nhau. 0 - 1
khớp với quy tắc cú pháp additive-expression: additive-expression - multiplicative-expression
, trong khi - 1
khớp với quy tắc cú pháp unary-expression: unary-operator cast-expression
(tham chiếu: tiêu chuẩn C99).
-
oeprators là cú pháp, không chỉ là ngữ nghĩa (mặc dù chúng cũng có ngữ nghĩa khác nhau). Cú pháp được xác định bởi ngữ pháp ngôn ngữ và hai toán tử được chỉ định trong các phần khác nhau của ngữ pháp. Xem dự thảo N1570 , mục 6.5.3 cho các toán tử đơn nguyên và 6.5.6 cho các toán tử cộng gộp . (BTW, nếu bạn đang sử dụng một ví dụ C, nó nên có lẽ là đúng; void main()
nên int main(void)
, và bạn đang thiếu #include <stdio.h>
và bất cứ điều gì tiêu đề tuyên bốgetch