มักจะแยกความคิดเห็นเป็นอย่างไร


31

ความคิดเห็นได้รับการปฏิบัติโดยทั่วไปในภาษาการเขียนโปรแกรมและมาร์กอัปอย่างไร ฉันกำลังเขียนโปรแกรมแยกวิเคราะห์สำหรับภาษามาร์กอัปที่กำหนดเองบางอย่างและต้องการทำตามหลักการของความประหลาดใจน้อยที่สุดดังนั้นฉันจึงพยายามกำหนดรูปแบบทั่วไป

ตัวอย่างเช่นความคิดเห็นที่ฝังอยู่ภายในโทเค็น 'รบกวน' กับโทเค็นหรือไม่? โดยทั่วไปแล้วเป็นสิ่งที่ชอบ:

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

ถูกต้อง?

นอกจากนี้หากภาษามีความอ่อนไหวต่อบรรทัดใหม่และความคิดเห็นที่ครอบคลุมบรรทัดใหม่ควรพิจารณาบรรทัดใหม่หรือไม่?

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

ถือว่าเป็น

stuff stuff more stuff

หรือ

stuff stuff
more stuff

?

ฉันรู้ว่ามีบางภาษาที่เฉพาะเจาะจงทำหรือฉันกำลังมองหาความคิดเห็น แต่กำลังมองหาหรือไม่: มีฉันทามติทั่วไปสิ่งที่คาดหวังโดยทั่วไปโดยเครื่องหมายขึ้นเกี่ยวกับโทเค็นและบรรทัดใหม่หรือไม่?


บริบทเฉพาะของฉันคือมาร์กอัปคล้ายวิกิ


บรรทัดใหม่มีอยู่ในความคิดเห็นหรือไม่? ทำไมมันถึงได้รับการปฏิบัติที่แตกต่างจากตัวละครอื่น ๆ ในความคิดเห็น?

1
@Snowman มีมุมมองนั้น แต่ในทางกลับกันถ้าโทเค็น 'x' มีความหมายพิเศษว่าเป็นโทเค็นแรกในบรรทัดและดูเหมือนจะเป็นโทเค็นแรกในบรรทัดสำหรับทั้งคนที่ดูแหล่งที่มาและ parser อ่านแบบบรรทัดต่อบรรทัด ดูเหมือนว่ากระอักกระอ่วนดังนั้นฉันถามคำถาม
เลื่อน

4
ฉันต้องทำสิ่งนี้ให้ตรงกับข้อมูลจำเพาะในขณะที่ผ่านมาและพบว่าเอกสารของ gccเป็นทรัพยากรที่ยอดเยี่ยม มีบางกรณีมุมแปลก ๆ ที่คุณอาจไม่ได้พิจารณา
Karl Bielefeldt

คำตอบ:


40

โดยทั่วไปความคิดเห็นจะถูกสแกน (และยกเลิก) เป็นส่วนหนึ่งของกระบวนการโทเค็น แต่ก่อนที่จะแยกวิเคราะห์ ความคิดเห็นทำงานเหมือนตัวแยกโทเค็นแม้จะไม่มีช่องว่างรอบ ๆ ก็ตาม

ในขณะที่คุณชี้ให้เห็นข้อมูลจำเพาะ C ระบุอย่างชัดเจนว่าความคิดเห็นจะถูกแทนที่ด้วยช่องว่างเดียว มันเป็นเพียงข้อกำหนด - lingo เนื่องจาก parser โลกแห่งความจริงจะไม่แทนที่อะไรจริง ๆ แต่จะสแกนและทิ้งความคิดเห็นแบบเดียวกับที่มันสแกนและทิ้งตัวละครในช่องว่าง แต่มันอธิบายด้วยวิธีง่าย ๆ ที่ความคิดเห็นจะแยกโทเค็นในลักษณะเดียวกับที่เว้นวรรค

เนื้อหาของความคิดเห็นจะถูกละเว้นดังนั้นการแยกบรรทัดภายในความคิดเห็นหลายบรรทัดจึงไม่มีผลกระทบ ภาษาที่มีความอ่อนไหวต่อตัวแบ่งบรรทัด (Python และ Visual Basic) มักจะไม่มีความคิดเห็นหลายบรรทัด แต่ JavaScript เป็นข้อยกเว้นหนึ่งข้อ ตัวอย่างเช่น:

return /*
       */ 17

มีค่าเท่ากับ

return 17

ไม่

return
17

ความคิดเห็นบรรทัดเดียวรักษาตัวแบ่งบรรทัดคือ

return // single line comment
    17

เทียบเท่ากับ

return
17

ไม่

return 17

เนื่องจากมีการสแกนความคิดเห็น แต่ไม่สามารถแยกวิเคราะห์ได้จึงมีแนวโน้มที่จะไม่ซ้อน ดังนั้น

 /*  /* nested comment */ */

เป็นข้อผิดพลาดทางไวยากรณ์เนื่องจากความคิดเห็นถูกเปิดโดยคำสั่งแรก/*และปิดโดยคำสั่งแรก*/


3
ในภาษาส่วนใหญ่ความคิดเห็นในบรรทัด ( /* like this */) จะถือว่าเท่ากับช่องว่างเดียวและความคิดเห็นที่ยกเลิก EOL ( // like this) กับบรรทัดว่าง
9000

@JacquesB ดังนั้นฉันจึงคิดว่าการแสดงความคิดเห็นจะถูกแทนที่อย่างครบถ้วนจากแหล่งที่มาเป็นพื้นที่ว่างที่มีความกว้างเป็นศูนย์ซึ่งดูเหมือนจะเท่ากับสิ่งที่คุณแนะนำ
เลื่อน

1
@artb พื้นที่ธรรมดาควรใช้งานได้ดีและอยู่ในหน้ารหัส ASCII
John Dvorak

@JanDvorak ช่องว่างจะมีผลต่อลักษณะที่ปรากฏและขจัดความเข้าใจและใกล้ความหมายของ "ความคิดเห็นไม่ได้มีอยู่จริง" ผลลัพธ์การแสดงผลหลักจะเป็น HTML ดังนั้นในกรณีของฉัน ASCII จะไม่เป็นปัญหาเนื่องจากเบราว์เซอร์รองรับ Unicode ที่กล่าวว่าฉันเชื่อว่าคำสั่งมาตรฐาน C ที่ความคิดเห็นจะถูกแทนที่ด้วยช่องว่างเดียว
เลื่อน

1
บางภาษาสะดุดตาไม้ไม่ได้แสดงความคิดเห็นที่ซ้อนกันหลายคู่สาย: อัตราผลตอบแทน(define x #| this is #| a sub-comment |# the main comment |# 3) x 3
wchargin

9

ในการตอบคำถาม:

มีฉันทามติทั่วไปสิ่งที่คาดหวังโดยทั่วไปโดยมาร์คอัพ?

ฉันจะบอกว่าไม่มีใครคาดว่าความคิดเห็นที่ฝังอยู่ภายในโทเค็นจะถูกกฎหมาย

ตามกฎทั่วไปแล้วความคิดเห็นควรได้รับการปฏิบัติเช่นเดียวกับช่องว่าง สถานที่ใด ๆ ที่จะถูกต้องที่จะมีช่องว่างภายนอกควรได้รับอนุญาตให้มีความคิดเห็นฝังตัว ข้อยกเว้นเพียงอย่างเดียวจะเป็นสตริง:

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

มันจะค่อนข้างแปลกที่จะสนับสนุนความคิดเห็นภายในสายและจะทำให้พวกเขาน่าเบื่อ!


2
ไม่เคยคิดเกี่ยวกับสตริงนั่นเป็นกรณีที่ดี ความคิดปัจจุบันของฉันกำลังทำ regex อย่างง่ายระหว่างความคิดเห็นเริ่มต้นและสิ้นสุดและแทนที่ด้วยช่องว่างเดียว นั่นจะทำให้กรณีของคุณสะดุด
เลื่อน

3
+1 สำหรับบิตนั้นเกี่ยวกับการหลีกเลี่ยงสตริง ถึงแม้ว่าในตัวอย่างของคุณโดยทั่วไปฉันคาดว่ามันจะพิมพ์Hello /* world*/!แทนที่จะระงับตัวคั่นความคิดเห็น นอกจากนี้ยินดีต้อนรับสู่โปรแกรมเมอร์!
8bittree

1
ขอบคุณ 8bittree! และนั่นคือทั้งหมดที่ฉันหมายถึง ขันพอฉันยังต้องหลบหนี ** ในคำตอบของฉัน ....
คอนเนอร์คลาร์ก

2
@ArtB โดยทั่วไป "การแยกวิเคราะห์โดยการแทนที่" จะยุ่งยากมากตามท้องถนนด้วยเคสที่มีขอบและการมีปฏิสัมพันธ์กับคุณสมบัติอื่น ๆ และหลีกเลี่ยงได้ดีที่สุดตั้งแต่ต้น
ฮอบส์

7

ในภาษาที่ไม่มีช่องว่างให้ใช้อักขระที่ไม่สนใจ (เช่นช่องว่างหรือที่เป็นส่วนหนึ่งของความคิดเห็น) คั่นโทเค็น

ตัวอย่างเช่นSys temสองโทเค็นในขณะที่Systemเป็นหนึ่ง ประโยชน์ของนี้อาจจะชัดเจนมากขึ้นถ้าคุณเปรียบเทียบnew Foo()และnewFoo()หนึ่งซึ่งจะสร้างตัวอย่างของในขณะที่สายอื่นFoonewFoo

ความคิดเห็นสามารถเล่นบทบาทเช่นเดียวกับการทำงานของช่องว่างที่เช่นการทำงานเช่นเดียวกับnew/**/Foo() new Foo()แน่นอนว่าสิ่งนี้อาจซับซ้อนกว่านี้เช่นnew /**/ /**/ Foo()หรืออะไรก็ตาม

ในทางเทคนิคแล้วมันเป็นไปได้ที่จะอนุญาตให้แสดงความคิดเห็นภายในตัวระบุ แต่ฉันสงสัยว่ามันใช้งานได้จริงโดยเฉพาะ

ตอนนี้ภาษาที่มีความสำคัญในพื้นที่สีขาวคืออะไร?

Python มาในใจและมันมีคำตอบที่ง่ายมาก: ไม่มีความคิดเห็นที่ถูกบล็อก คุณเริ่มแสดงความคิดเห็นด้วย#และจากนั้น parser ทำงานเหมือนกับว่าส่วนที่เหลือของสายไม่ได้อยู่ แต่เป็นเพียงขึ้นบรรทัดใหม่แทน

ตรงกันข้ามกับที่หยกอนุญาตให้แสดงความคิดเห็นบล็อกที่บล็อกจะสิ้นสุดลงเมื่อคุณกลับไปที่ระดับเยื้องเดียวกัน ตัวอย่าง:

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

ดังนั้นในดินแดนนี้ฉันจะไม่บอกว่าคุณอาจจะบอกว่าสิ่งที่มักจะจัดการ สิ่งที่ดูเหมือนจะเป็นเรื่องธรรมดาคือความคิดเห็นมักลงท้ายด้วยจุดสิ้นสุดของบรรทัดซึ่งหมายความว่าความคิดเห็นทั้งหมดจะทำหน้าที่เหมือนกับบรรทัดใหม่ทุกประการ


อืมบรรทัดใหม่เป็นปัญหาจริงเนื่องจากเราใช้ไวยากรณ์ HTML \ XML สำหรับความคิดเห็นดังนั้นมันจะเป็นแบบหลายบรรทัด
เลื่อน

3
@ArtB หากคุณใช้ไวยากรณ์ HTML / XML คุณควรใช้พฤติกรรมของพวกเขา
8bittree

1
@ 8bittree ทำให้รู้สึกว่าควรจะคิดว่า ฉันจะทิ้งคำถามตามที่เป็นเพราะมันจะมีประโยชน์มากขึ้นด้วยวิธีนี้
เลื่อน

3

ในอดีตฉันเปลี่ยนความคิดเห็นเป็นโทเค็นเดี่ยวเป็นส่วนหนึ่งของการวิเคราะห์คำ เช่นเดียวกันสำหรับสตริง จากนั้นชีวิตก็ง่าย

ในกรณีเฉพาะของ parser สุดท้ายที่ฉันสร้างกฎ escape จะถูกส่งไปยังรูทีนการวิเคราะห์คำระดับสูงสุด กฎการหลบหนีใช้เพื่อจัดการโทเค็นเช่นโทเค็นความคิดเห็นแบบอินไลน์กับไวยากรณ์หลัก โดยทั่วไปโทเค็นเหล่านี้จะถูกทิ้ง

ผลที่ตามมาของการทำเช่นนี้คือตัวอย่างที่คุณโพสต์ด้วยความคิดเห็นตรงกลางของตัวระบุตัวระบุจะไม่ใช่ตัวระบุเดียว - นี่เป็นพฤติกรรมที่คาดหวังในทุกภาษา (จากหน่วยความจำ) ที่ฉันทำงานด้วย .

กรณีของความคิดเห็นภายในสตริงควรได้รับการจัดการโดยนัยโดยการวิเคราะห์คำ กฎในการจัดการสตริงไม่มีความสนใจในความคิดเห็นและความคิดเห็นดังกล่าวถือเป็นเนื้อหาของสตริง เช่นเดียวกับสตริง (หรือตัวอักษรที่ยกมา) ภายในความคิดเห็น - สตริงเป็นส่วนหนึ่งของความคิดเห็นซึ่งเป็นโทเค็นเดียวอย่างชัดเจน; กฎสำหรับการประมวลผลความคิดเห็นไม่มีความสนใจในสตริง

ฉันหวังว่าเหมาะสม / ช่วย


ดังนั้นหากคุณมีรหัสเช่นconsole.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")ที่มีเครื่องหมายคำพูดในความคิดเห็นและไวยากรณ์ความคิดเห็นในสตริง, lexer จะรู้วิธี tokenize อย่างถูกต้องได้อย่างไร คุณช่วยแก้ไขคำตอบของคุณโดยให้คำอธิบายทั่วไปของคดีเหล่านั้นได้หรือไม่?
chharvey

1

ขึ้นอยู่กับวัตถุประสงค์ในการแยกวิเคราะห์ของคุณ หากคุณเขียน parser เพื่อสร้างทรีการแยกวิเคราะห์สำหรับการคอมไพล์กว่าความคิดเห็นไม่มีค่าความหมายข้างๆอาจแยกโทเค็น (เช่น method / comment / (/ comment /)) ในกรณีนี้ถือว่าเป็นช่องว่าง

หาก parser ของคุณเป็นส่วนหนึ่งของ transpiler ที่แปลภาษาต้นฉบับหนึ่งเป็นภาษาต้นฉบับอื่นหรือถ้า parser ของคุณเป็นตัวประมวลผลล่วงหน้าที่ใช้หน่วยการคอมไพล์ในภาษาต้นฉบับแยกวิเคราะห์แก้ไขและเขียนเวอร์ชันที่แก้ไขกลับไปในภาษาต้นฉบับเดียวกัน เหมือนสิ่งอื่นใดที่มีความสำคัญมาก

นอกจากนี้หากคุณมีข้อมูลเมตาในความคิดเห็นและคุณใส่ใจเป็นพิเศษกับความคิดเห็นเช่นเมื่อสร้างเอกสาร API เช่น JavaDoc ความคิดเห็นนั้นสำคัญมากในทันที

ความคิดเห็นที่นี่มักจะแนบกับโทเค็นเอง หากคุณพบความคิดเห็นที่คุณแนบมันเป็นความคิดเห็นของโทเค็น เนื่องจากโทเค็นสามารถมีโทเค็นหลายรายการก่อนและหลังได้จึงมีวัตถุประสงค์อีกครั้งขึ้นอยู่กับวิธีจัดการกับความคิดเห็นเหล่านั้น

แนวคิดของการเพิ่มความคิดเห็นโทเค็นที่ไม่ใช่ความคิดเห็นที่มีความคิดเห็นคือการลบความคิดเห็นออกจากไวยากรณ์โดยสิ้นเชิง

เมื่อคุณมีการแยกวิเคราะห์ต้นไม้ AST บางอันจะเริ่มคลายความคิดเห็นที่แสดงถึงโทเค็นแต่ละอันด้วยองค์ประกอบ AST ของตัวเอง แต่จะถูกแนบไปกับองค์ประกอบ AST อื่นนอกเหนือจากความสัมพันธ์ปกติที่มีอยู่ ความคิดที่ดีคือการตรวจสอบเครื่องมือแยกวิเคราะห์ / AST ทั้งหมดสำหรับภาษาต้นฉบับที่มีอยู่ใน IDE แบบโอเพ่นซอร์ส

การใช้งานที่ดีอย่างหนึ่งคือโครงสร้างพื้นฐานคอมไพเลอร์ Eclipse สำหรับภาษา Java พวกเขาเก็บความคิดเห็นระหว่างโทเค็นและแสดงความคิดเห็นภายใน AST - เท่าที่ฉันจำได้ นอกจากนี้การใช้งานตัวแยกวิเคราะห์ / AST นี้จะรักษาการจัดรูปแบบไว้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.