Sự khác biệt giữa cú pháp và ngữ nghĩa trong ngôn ngữ lập trình là gì?


120

Sự khác biệt giữa cú phápngữ nghĩa trong các ngôn ngữ lập trình (như C, C ++) là gì?


2
Tôi muốn bỏ phiếu nhưng không có nỗ lực nghiên cứu nào là hiển nhiên.

Câu trả lời:


201

Cú pháp là về cấu trúc hoặc ngữ pháp của ngôn ngữ. Nó trả lời câu hỏi: làm thế nào để tôi xây dựng một câu hợp lệ? Tất cả các ngôn ngữ, ngay cả tiếng Anh và các ngôn ngữ khác của con người (hay còn gọi là "tự nhiên") đều có ngữ pháp, tức là các quy tắc xác định câu có được cấu tạo đúng hay không.

Dưới đây là một số quy tắc cú pháp ngôn ngữ C:

  • phân tách các câu lệnh bằng dấu chấm phẩy
  • đặt biểu thức điều kiện của câu lệnh IF bên trong dấu ngoặc đơn
  • nhóm nhiều câu lệnh thành một câu lệnh duy nhất bằng cách đặt trong dấu ngoặc nhọn
  • kiểu dữ liệu và biến phải được khai báo trước câu lệnh thực thi đầu tiên (tính năng này đã bị loại bỏ trong C99. C99 và sau này cho phép khai báo kiểu hỗn hợp.)

Ngữ nghĩa là về ý nghĩa của câu. Nó trả lời các câu hỏi: câu này có hợp lệ không? Nếu vậy, câu đó có nghĩa là gì? Ví dụ:

x++;                  // increment
foo(xyz, --b, &qrs);  // call foo

là các câu lệnh C hợp lệ về mặt cú pháp. Nhưng họ muốn nói gì? Liệu nó có hợp lệ khi cố gắng chuyển đổi các câu lệnh này thành một chuỗi hướng dẫn có thể thực thi được không? Những câu hỏi này là trọng tâm của ngữ nghĩa.

Hãy xem xét toán tử ++ trong câu lệnh đầu tiên. Trước hết, liệu nó có hợp lệ để thử điều này không?

  • Nếu x là kiểu dữ liệu float, câu lệnh này không có nghĩa (theo các quy tắc ngôn ngữ C) và do đó nó là một lỗi mặc dù câu lệnh này đúng về mặt cú pháp.
  • Nếu x là một con trỏ đến một số kiểu dữ liệu , ý nghĩa của câu lệnh là "thêm sizeof ( một số kiểu dữ liệu ) vào giá trị tại địa chỉ x và lưu trữ kết quả vào vị trí tại địa chỉ x".
  • Nếu x là một đại lượng vô hướng, ý nghĩa của câu lệnh là "thêm một vào giá trị tại địa chỉ x và lưu trữ kết quả vào vị trí tại địa chỉ x".

Cuối cùng, lưu ý rằng một số ngữ nghĩa không thể được xác định tại thời điểm biên dịch và do đó phải được đánh giá tại thời điểm chạy. Trong ví dụ về toán tử ++, nếu x đã ở giá trị lớn nhất cho kiểu dữ liệu của nó, điều gì sẽ xảy ra khi bạn cố gắng thêm 1 vào nó? Một ví dụ khác: điều gì sẽ xảy ra nếu chương trình của bạn cố gắng bỏ qua một con trỏ có giá trị là NULL?

Tóm lại, cú pháp là khái niệm chỉ liên quan đến bản thân câu đó có hợp lệ với ngữ pháp của ngôn ngữ hay không. Ngữ nghĩa là về việc liệu câu có ý nghĩa hợp lệ hay không.


ĐỒNG Ý. Nếu xở giá trị lớn nhất cho dữ liệu của nó và 1được thêm vào nó thì nó dẫn đến một số đầu ra kỳ lạ ( 0), đó có phải là lỗi ngữ nghĩa không?
haccks vào

Hãy xem xét đồng hồ đo đường trên một chiếc xe - nó có một loạt các bánh xe có liên quan với nhau với các chữ số từ 0 đến 9 được in trên mỗi chiếc. Bánh xe ngoài cùng bên phải quay nhanh nhất; khi nó kết thúc từ số 9 trở lại 0, bánh xe bên trái ngay lập tức của nó tiến lên một. Khi bánh xe này tiến từ 9 lên 0, bánh xe bên trái sẽ tiến lên, v.v.
Jeff N

Một kiểu dữ liệu giống như bánh xe của đồng hồ đo đường: nó chỉ có thể chứa đến một giá trị nhất định. Khi đạt đến giá trị lớn nhất, lần tăng tiếp theo làm cho bánh xe quay về số không. Đây có phải là lỗi ngữ nghĩa hay không phụ thuộc vào các quy tắc ngôn ngữ. Trong trường hợp này, bạn cần tham khảo lại tiêu chuẩn ngôn ngữ C. Tôi không biết chính xác tiêu chuẩn ngôn ngữ C nói gì, nhưng đây là một số tùy chọn. Tràn là: -không phải là lỗi; kết quả là không. -một lỗi; trình biên dịch PHẢI tạo ra một ngoại lệ tràn. -UNDEFINED; trình biên dịch có thể tự do làm bất cứ điều gì nó muốn.
Jeff N

2
Trong trường hợp bất kỳ ai quan tâm đến ví dụ cụ thể, tràn không dấu được định nghĩa là số học mô-đun (như vậy UINT_MAX + 1 == 0). Phần tràn đã ký là không xác định. Các trình biên dịch hiện đại thườngINT_MAX + 1 == INT_MIN, nhưng có những trường hợp bạn không thể tin tưởng vào điều này (ví dụ: for (i = 0; i <= N; ++i) { ... }đâu NINT_MAXvô hạn tùy thuộc vào tối ưu hóa; xem blog.llvm.org/2011/05/what-every-c-programmer-should-know). html ).
Daniel H

"lưu ý rằng một số ngữ nghĩa không thể được xác định tại thời điểm biên dịch và do đó phải được đánh giá tại thời điểm chạy" - Tôi thích cách điều này có sự song song với các ngôn ngữ tự nhiên. Bạn không thể biết ý nghĩa của một số cụm từ nếu không có ngữ cảnh. Ví dụ, trong câu "Anh ấy thích chuối", nghĩa của "anh ấy" tùy thuộc vào ngữ cảnh.
ymln

21

Cú pháp đề cập đến cấu trúc của một ngôn ngữ, truy tìm từ nguyên của nó để biết cách mọi thứ được kết hợp với nhau.
Ví dụ, bạn có thể yêu cầu mã được ghép lại với nhau bằng cách khai báo một kiểu, sau đó là tên và sau đó là dấu chấm phẩy, phải đúng về mặt cú pháp.

Type token;

Mặt khác, ngữ nghĩa là về nghĩa. Một trình biên dịch hoặc thông dịch viên có thể phàn nàn về lỗi cú pháp. Đồng nghiệp của bạn sẽ phàn nàn về ngữ nghĩa.


@Talespin_Kit nghĩa hơn là cấu trúc: logic là một sự trừu tượng hơn, ví dụ P => Q, v.v. hoặc !! P = P, nhưng khi bạn thêm ngữ nghĩa, mọi thứ có thể có sự tinh tế, nếu P là "hạnh phúc", thì !! P là "I 'm not un-happy "! =" Tôi rất vui "
doctorlove

5
+1 cho "Trình biên dịch hoặc thông dịch viên có thể phàn nàn về lỗi cú pháp. Đồng nghiệp của bạn sẽ phàn nàn về ngữ nghĩa".
GeekyJ

11

Wikipedia có câu trả lời. Đọc trang wikipages cú pháp (ngôn ngữ lập trình) & ngữ nghĩa (khoa học máy tính) .

Hoặc suy nghĩ về công việc của bất kỳ trình biên dịch hoặc thông dịch viên nào . Bước đầu tiên là phân tích từ vựng trong đó mã thông báo được tạo ra bằng cách chia chuỗi thành các từ vựng sau đó phân tích cú pháp , xây dựng một số cây cú pháp trừu tượng (là một đại diện của cú pháp). Các bước tiếp theo liên quan đến việc chuyển đổi hoặc đánh giá các AST (ngữ nghĩa) này.

Ngoài ra, hãy quan sát rằng nếu bạn xác định một biến thể của C trong đó mọi từ khóa được chuyển thành từ khóa tương đương với tiếng Pháp của nó ( iftrở thành si, dotrở thành faire, elsetrở thành , sinonv.v.), bạn chắc chắn sẽ thay đổi cú pháp ngôn ngữ của mình, nhưng bạn sẽ không thay đổi nhiều ngữ nghĩa: lập trình bằng tiếng Pháp-C đó sẽ không dễ dàng hơn!


8

Ngữ nghĩa là ý nghĩa của mã của bạn - những gì bạn có thể mô tả trong mã giả. Cú pháp là cấu trúc thực tế - mọi thứ từ tên biến đến dấu chấm phẩy.


Đó có phải là một cuộc trò chuyện giữa những người khác nhau? Hay nó chỉ là một bài viết? Tôi không hiểu. Ví dụ: "Không biết điều sau đây có nghĩa là gì. Không thể sai hơn".
doubleOrt

5

Cú pháp là cấu trúc hoặc hình thức của biểu thức, câu lệnh và đơn vị chương trình nhưng Ngữ nghĩa là ý nghĩa của các biểu thức, câu lệnh và đơn vị chương trình đó. Ngữ nghĩa theo sau trực tiếp từ cú pháp . Cú pháp đề cập đến cấu trúc / hình thức của mã mà một ngôn ngữ lập trình cụ thể chỉ định nhưng Ngữ nghĩa giải quyết ý nghĩa được gán cho các ký hiệu, ký tự và từ.


5
  • Bạn cần đúng cú pháp để biên dịch.
  • Bạn cần ngữ nghĩa chính xác để làm cho nó hoạt động.

1

Các cú pháp của một ngôn ngữ lập trình là hình thức biểu hiện, báo cáo, và các đơn vị chương trình của mình. Ngữ nghĩa của nó là ý nghĩa của các biểu thức, câu lệnh và đơn vị chương trình đó. Ví dụ: cú pháp của câu lệnh while trong Java là

while (boolean_expr) statement

Ngữ nghĩa của dạng câu lệnh này là khi giá trị hiện tại của biểu thức Boolean là true thì câu lệnh nhúng sẽ được thực thi. Sau đó, điều khiển hoàn toàn trở lại biểu thức Boolean để lặp lại quá trình. Nếu biểu thức Boolean sai, điều khiển sẽ chuyển đến câu lệnh theo sau cấu trúc while.


1

Cú pháp: Nó đề cập đến cấu trúc ngữ pháp của ngôn ngữ .. Nếu bạn đang viết ngôn ngữ c. Bạn phải rất quan tâm đến việc sử dụng các kiểu dữ liệu, mã thông báo [nó có thể là chữ hoặc ký hiệu như "printf ()". Nó có 3 toke, "printf, (,)"]. Theo cách tương tự, bạn phải rất cẩn thận, cách bạn sử dụng hàm, cú pháp hàm, khai báo hàm, định nghĩa, khởi tạo và gọi nó.

Trong khi ngữ nghĩa, nó liên quan đến logic hoặc khái niệm của câu hoặc câu lệnh. Nếu bạn nói hoặc viết một cái gì đó ngoài khái niệm hoặc logic, thì bạn đã sai về mặt ngữ nghĩa.


1

Hiểu cách trình biên dịch xem mã

Thông thường, phân tích cú pháp và ngữ nghĩa của mã được thực hiện trong phần 'giao diện người dùng' của trình biên dịch.

  • Cú pháp: Trình biên dịch tạo mã thông báo cho mỗi từ khóa và ký hiệu: mã thông báo chứa thông tin- loại từ khóa và vị trí của nó trong mã. Sử dụng các mã thông báo này, một AST (viết tắt của Cây cú pháp trừu tượng) được tạo và phân tích. Điều mà trình biên dịch thực sự kiểm tra ở đây là liệu mã có ý nghĩa từ vựng hay không, tức là 'chuỗi từ khóa' có tuân thủ các quy tắc ngôn ngữ không? Như đã đề xuất trong các câu trả lời trước, bạn có thể xem nó là ngữ pháp của ngôn ngữ (không phải ý nghĩa / ý nghĩa của mã). Lưu ý bên: Lỗi cú pháp được báo cáo trong giai đoạn này. (Trả về mã thông báo cùng loại lỗi cho hệ thống)

  • Ngữ nghĩa: Bây giờ, trình biên dịch sẽ kiểm tra xem các hoạt động mã của bạn có 'hợp lý' hay không. Ví dụ: Nếu ngôn ngữ hỗ trợ Type Inference, lỗi sematic sẽ được báo cáo nếu bạn đang cố gắng gán một chuỗi cho một float. HOẶC khai báo cùng một biến hai lần. Đây là những lỗi đúng về mặt ngữ pháp / cú pháp, nhưng không có ý nghĩa gì trong quá trình thao tác. Lưu ý bên: Để kiểm tra xem cùng một biến có được khai báo hai lần hay không, trình biên dịch quản lý một bảng ký hiệu

Vì vậy, đầu ra của 2 pha frontend này là một AST có chú thích (với các kiểu dữ liệu) và bảng ký hiệu.

Hiểu nó theo cách ít kỹ thuật hơn

Xem xét ngôn ngữ bình thường mà chúng ta sử dụng; tại đây, tiếng Anh:

ví dụ: He go to the school. - Ngữ pháp / cú pháp không chính xác, mặc dù anh ta muốn truyền đạt một ý nghĩa / ngữ nghĩa chính xác.

ví dụ: Anh ấy đi đến chỗ lạnh. - cold là một tính từ. Trong tiếng Anh, chúng ta có thể nói điều này không tuân thủ ngữ pháp, nhưng nó thực sự là ví dụ gần nhất cho ngữ nghĩa sai với cú pháp chính xác mà tôi có thể nghĩ ra.


Trình biên dịch Liên kết này có thể hữu ích để tìm hiểu thêm
Vedant Panchal
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.