Làm thế nào là bình luận thường được phân tích cú pháp?


31

Làm thế nào là ý kiến ​​thường được đối xử trong ngôn ngữ lập trình và đánh dấu? Tôi đang viết một trình phân tích cú pháp cho một số ngôn ngữ đánh dấu tùy chỉnh và muốn tuân theo nguyên tắc ít gây ngạc nhiên nhất , vì vậy tôi đang cố gắng xác định quy ước chung.

Ví dụ: một bình luận có được nhúng trong mã thông báo 'can thiệp' vào mã thông báo hay không? Nói chung, là một cái gì đó như:

Sys/* comment */tem.out.println()

có hiệu lực?

Ngoài ra, nếu ngôn ngữ nhạy cảm với các dòng mới và nhận xét kéo dài dòng mới, dòng mới có nên được xem xét hay không?

stuff stuff /* this is comment
this is still comment */more stuff 

được đối xử như

stuff stuff more stuff

hoặc là

stuff stuff
more stuff

?

Tôi biết một vài ngôn ngữ cụ thể làm gì, tôi cũng không tìm kiếm ý kiến, nhưng tôi đang tìm kiếm hay không: có sự đồng thuận chung về những gì thường được mong đợi bởi một đánh dấu liên quan đến mã thông báo và dòng mới không?


Bối cảnh cụ thể của tôi là một đánh dấu giống như wiki.


Liệu dòng mới tồn tại bên trong của bình luận? Tại sao nó sẽ được đối xử khác biệt với bất kỳ nhân vật khác trong bình luận?

1
@Snowman có quan điểm đó, nhưng mặt khác, nếu mã thông báo 'x' có ý nghĩa đặc biệt nếu mã thông báo đầu tiên trên dòng và nó dường như là mã thông báo đầu tiên trên dòng cho cả người nhìn vào nguồn và cho trình phân tích cú pháp đọc từng dòng một. Có vẻ như một vấn đề nan giải nên tôi đã đặt câu hỏi.
Sled

4
Tôi cần phải làm điều này chính xác với thông số kỹ thuật một thời gian trước đây và thấy tài liệu của gcc là một tài nguyên tuyệt vời. Có một số trường hợp góc kỳ lạ bạn có thể không xem xét.
Karl Bielefeldt

Câu trả lời:


40

Thông thường các bình luận được quét (và loại bỏ) như một phần của quy trình mã thông báo, nhưng trước khi phân tích cú pháp. Một nhận xét hoạt động giống như một dấu tách mã thông báo ngay cả khi không có khoảng trắng xung quanh nó.

Như bạn chỉ ra, đặc tả C nói rõ rằng các bình luận được thay thế bằng một khoảng trắng. Tuy nhiên, đây chỉ là một đặc điểm kỹ thuật, vì trình phân tích cú pháp trong thế giới thực sẽ không thực sự thay thế bất cứ thứ gì, mà sẽ chỉ quét và loại bỏ một nhận xét giống như cách nó quét và loại bỏ các ký tự khoảng trắng. Nhưng nó giải thích một cách đơn giản rằng một nhận xét phân tách các mã thông báo giống như cách một không gian sẽ.

Nội dung của các bình luận bị bỏ qua, vì vậy các ngắt dòng bên trong các bình luận đa dòng không có tác dụng. Các ngôn ngữ nhạy cảm với ngắt dòng (Python và Visual Basic) thường không có nhận xét đa dòng, nhưng JavaScript là một ngoại lệ. Ví dụ:

return /*
       */ 17

Tương đương với

return 17

không phải

return
17

Nhận xét một dòng duy trì ngắt dòng, nghĩa là

return // single line comment
    17

tương đương với

return
17

không phải

return 17

Vì các bình luận được quét nhưng không được phân tích cú pháp, chúng có xu hướng không lồng nhau. Vì thế

 /*  /* nested comment */ */

là một lỗi cú pháp, vì bình luận được mở bởi đầu tiên /*và đóng bởi đầu tiên*/


3
Trong hầu hết các ngôn ngữ, các nhận xét nội tuyến ( /* like this */) được coi là bằng một khoảng trắng duy nhất và một nhận xét kết thúc EOL ( // like this) cho một dòng trống.
9000

@JacquesB vì vậy tôi nghĩ rằng việc coi các bình luận được thay thế toàn bộ từ nguồn dưới dạng không gian có độ rộng bằng 0 , dường như tương đương với những gì bạn đang đề xuất.
Sled

1
@artb một không gian bình thường sẽ hoạt động tốt và nằm trong trang mã ASCII.
John Dvorak

@JanDvorak một không gian sẽ có hiệu lực xuất hiện và loại bỏ sự hiểu biết và gần với ngữ nghĩa của "một nhận xét không thực sự ở đó". Đầu ra kết xuất chính sẽ là HTML, vì vậy trong trường hợp của tôi, ASCII không phải là vấn đề vì các trình duyệt hỗ trợ Unicode. Điều đó nói rằng, tôi tin rằng các tiêu chuẩn C ủy nhiệm rằng các bình luận được thay thế bằng một không gian duy nhất.
Sled

1
Một số ngôn ngữ, đáng chú ý là Vợt, có các nhận xét nhiều dòng lồng nhau: (define x #| this is #| a sub-comment |# the main comment |# 3) xsản lượng 3.
wchargein

9

Để trả lời câu hỏi:

Có một sự đồng thuận chung những gì thường được mong đợi bởi một đánh dấu lên?

Tôi sẽ nói không ai mong muốn một bình luận được nhúng bên trong mã thông báo là hợp pháp.

Theo nguyên tắc chung, các bình luận nên được đối xử giống như khoảng trắng. Bất kỳ nơi nào có thể hợp lệ để có khoảng trắng bên ngoài cũng nên được phép có một nhận xét được nhúng. Ngoại lệ duy nhất sẽ là các chuỗi:

trace("Hello /*world*/") // should print Hello /*world*/

Sẽ là khá kỳ quặc khi hỗ trợ các bình luận bên trong chuỗi, và sẽ khiến việc thoát chúng trở nên tẻ nhạt!


2
Không bao giờ nghĩ về chuỗi, đó là một trường hợp cạnh tốt. Suy nghĩ hiện tại của tôi là thực hiện regex đơn giản giữa bắt đầu và kết thúc bình luận và thay thế nó bằng một không gian duy nhất. Điều đó sẽ tăng gấp ba trường hợp của bạn.
Sled

3
+1 cho bit đó về thoát chuỗi. Mặc dù, trong ví dụ của bạn, tôi thường mong đợi nó được in Hello /* world*/!hơn là triệt tiêu các dấu phân cách nhận xét. Ngoài ra, chào mừng các lập trình viên!
8bittree

1
Cảm ơn 8bittree! Và đó hoàn toàn là những gì tôi muốn nói. Thật thú vị, tôi cũng cần phải thoát khỏi ** trong câu trả lời của mình ....
Connor Clark

2
@ArtB nói chung, "phân tích cú pháp thay thế" rất khó khăn với các trường hợp cạnh và tương tác với các tính năng khác, và tốt nhất nên tránh ngay từ đầu.
hobbs

7

Trong các ngôn ngữ không phân biệt khoảng trắng, các ký tự bị bỏ qua (ví dụ: khoảng trắng hoặc các ký tự là một phần của nhận xét) phân định mã thông báo.

Vì vậy, ví dụ Sys temlà hai mã thông báo, trong khi Systemlà một. Sự hữu ích của điều này có thể rõ ràng hơn nếu bạn so sánhnew Foo()newFoo()một trong số đó sẽ xây dựng một thể hiện Footrong khi các cuộc gọi khác newFoo.

Nhận xét có thể đóng vai trò tương tự như một khoảng trắng, ví dụ: new/**/Foo() hoạt động tương tự như new Foo(). Tất nhiên điều này có thể phức tạp hơn, vdnew /**/ /**/ Foo() hoặc không có gì.

Về mặt kỹ thuật, có thể cho phép nhận xét trong các định danh, nhưng tôi nghi ngờ nó đặc biệt thiết thực.

Bây giờ, những gì của ngôn ngữ nhạy cảm không gian trắng?

Python đến với tâm trí và nó có một câu trả lời rất đơn giản: không có bình luận khối. Bạn bắt đầu một bình luận với# và sau đó trình phân tích cú pháp hoạt động chính xác như thể phần còn lại của dòng không tồn tại mà chỉ là một dòng mới thay thế.

Ngược lại, ngọc cho phép nhận xét khối , trong đó khối kết thúc khi bạn quay lại mức thụt đầu dòng tương tự. Thí dụ:

body
  //-
    As much text as you want
    can go here.
  p this is no longer part of the comment

Vì vậy, trong vương quốc này, tôi sẽ không nói bạn có thể nói mọi thứ thường được xử lý như thế nào . Điều có vẻ là một điểm chung, là một bình luận luôn kết thúc bằng một dòng cuối, có nghĩa là tất cả các bình luận hoạt động giống hệt như các dòng mới.


Hmm, dòng mới là vấn đề thực sự vì chúng tôi đang sử dụng cú pháp HTML \ XML cho các nhận xét nên nó sẽ là đa dòng.
Sled

3
@ArtB Nếu bạn đang sử dụng cú pháp HTML / XML, có thể chỉ đơn giản là sử dụng hành vi của họ.
8bittree

1
@ 8bittree có ý nghĩa, nên đã nghĩ về điều đó. Tôi sẽ để lại câu hỏi vì nó sẽ hữu ích hơn theo cách này.
Sled

3

Trước đây, tôi đã biến các bình luận thành một mã thông báo duy nhất như là một phần của phân tích từ vựng. Các chuỗi cũng vậy. Từ đó, cuộc sống thật dễ dàng.

Trong trường hợp cụ thể của trình phân tích cú pháp cuối cùng mà tôi đã xây dựng, một quy tắc thoát được chuyển đến thói quen phân tích cú pháp cấp cao nhất. Quy tắc thoát được sử dụng để xử lý các mã thông báo như mã thông báo nhận xét nội tuyến với ngữ pháp cốt lõi. Nói chung, các mã thông báo này đã bị loại bỏ.

Hậu quả của việc thực hiện theo cách này là ví dụ bạn đã đăng với một nhận xét ở giữa một định danh, định danh sẽ không phải là một định danh duy nhất - đây là hành vi được mong đợi trong tất cả các ngôn ngữ (từ bộ nhớ) mà tôi đã làm việc với .

Trường hợp của một nhận xét trong một chuỗi nên được xử lý ngầm bằng phân tích từ vựng. Các quy tắc để xử lý một chuỗi không có hứng thú với các bình luận và như vậy bình luận được coi là nội dung của chuỗi. Điều tương tự cũng áp dụng cho một chuỗi (hoặc được trích dẫn bằng chữ) trong một nhận xét - chuỗi là một phần của một nhận xét, rõ ràng là một mã thông báo duy nhất; các quy tắc để xử lý một bình luận không có hứng thú với các chuỗi.

Tôi hy vọng điều đó có ý nghĩa / giúp đỡ.


Vì vậy, nếu bạn có mã như console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible"), trong đó có dấu ngoặc kép trong một cú pháp nhận xét và nhận xét trong một chuỗi, làm thế nào để nhà từ vựng biết để mã hóa chính xác? Bạn có thể vui lòng chỉnh sửa câu trả lời của bạn, cung cấp một mô tả chung về những trường hợp đó?
chharvey

1

Nó phụ thuộc vào mục đích mà trình phân tích cú pháp của bạn có. Nếu bạn viết một trình phân tích cú pháp để xây dựng một cây phân tích cú pháp để biên dịch hơn một bình luận không có giá trị ngữ nghĩa bên cạnh các mã thông báo có khả năng phân tách (ví dụ: phương thức / bình luận / (/ bình luận /)). Trong trường hợp này, nó được đối xử như không gian.

Nếu trình phân tích cú pháp của bạn là một phần của trình dịch mã dịch một ngôn ngữ nguồn sang ngôn ngữ nguồn khác hoặc nếu trình phân tích cú pháp của bạn là bộ xử lý trước, hãy lấy một đơn vị biên dịch bằng ngôn ngữ nguồn, phân tích cú pháp, sửa đổi nó và viết lại phiên bản đã sửa đổi trong cùng ngôn ngữ nguồn như bất cứ điều gì khác trở nên rất quan trọng.

Ngoài ra, nếu bạn có thông tin meta trong các bình luận và bạn đặc biệt quan tâm đến các bình luận như khi tạo tài liệu API như JavaDoc, thì các bình luận đều rất quan trọng.

Ở đây các bình luận thường được gắn vào chính các mã thông báo. Nếu bạn tìm thấy một bình luận, bạn đính kèm nó là một bình luận của một mã thông báo. Vì mã thông báo có thể có nhiều mã thông báo trước và sau, nên mục đích lại tùy thuộc vào cách xử lý các nhận xét đó.

Ý tưởng chú thích các mã thông báo không bình luận có bình luận là loại bỏ hoàn toàn các bình luận khỏi ngữ pháp.

Khi bạn có cây phân tích, một số AST bắt đầu giải nén các nhận xét đại diện cho mỗi mã thông báo bằng AST-Element của riêng nó nhưng được gắn vào một Element-Element khác bên cạnh mối quan hệ chứa thông thường. Một ý tưởng tốt là kiểm tra tất cả các triển khai trình phân tích cú pháp / AST cho các ngôn ngữ nguồn có sẵn trong IDE nguồn mở.

Một triển khai rất tốt là cơ sở hạ tầng trình biên dịch Eclipse cho ngôn ngữ Java. Họ lưu giữ các bình luận trong quá trình token hóa và đại diện cho các bình luận trong AST - theo như tôi nhớ. Ngoài ra, trình phân tích cú pháp / AST này bảo tồn định dạng.

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.