ภาษาการเขียนโปรแกรมคืออะไร? อะไรทำให้เราสามารถเขียนภาษาดังกล่าวได้


26

เอาล่ะฉันยังใหม่กับการเขียนโปรแกรมและฉันยอมรับว่านี่เป็นคำถามที่ค่อนข้างเป็นธรรม

ภาษาธรรมชาติที่เราพูดทุกวันมีอยู่เพราะผู้คนสามารถเข้าใจซึ่งกันและกัน คอมพิวเตอร์จะเข้าใจรหัสของฉันในภาษาใดภาษาหนึ่งได้อย่างไร

สมมติว่า Mr. A สร้างภาษาใหม่ เครื่องยอมรับได้อย่างไร? ผู้สร้างจะต้องสื่อสารกับเครื่องโดยใช้ภาษาเครื่องเพื่อสร้างภาษาใหม่หรือไม่ อะไรรับประกันได้ว่าเราสามารถเขียนภาษาในขณะที่ทำความเข้าใจกับเครื่องได้อย่างถูกต้อง?


1
อะไรทำให้เราสามารถเขียนภาษาดังกล่าวได้ - "สมอง: ฟิลเลอร์หัวแปลกใจใหม่!" - สไปค์ Milligan
Stephen C

6
ค่อนข้างกว้าง แต่เป็นคำถามที่ดีอย่างไรก็ตาม มีคนจำนวนมากที่ใช้ภาษาโดยไม่สงสัยว่าทำงานอย่างไร ดีที่คุณอยากรู้
riwalk

4
นี่เป็นคำถามอ้างอิงทั่วไปตอบโดยวิกิพีเดียอย่างง่ายดายและไม่สำคัญ
Aaronaught

คำตอบ:


39

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

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

การตอบคำถามในเชิงลึกมากกว่านี้จะเข้าสู่ทฤษฎีคอมไพเลอร์ซึ่งเป็นวิชาที่กว้างมาก หากคุณสนใจในหัวข้อคุณควรเริ่มต้นด้วยการอ่านบทความ Wikipedia สำหรับ "คอมไพเลอร์" และตรวจสอบลิงก์จากมันและหากคุณมีคำถามเฉพาะอย่าลังเลที่จะถามพวกเขาที่นี่


11
+1 - ฉันจะเพิ่มว่าเมื่อคุณเขียนภาษาใหม่คุณต้องเขียนคอมไพเลอร์หรือล่ามในภาษาอื่น คอมไพเลอร์หรือล่ามรุ่นที่ใหม่กว่านั้นสามารถเขียนในภาษาเวอร์ชันก่อนหน้าและคอมไพล์ด้วยคอมไพเลอร์รุ่นเก่า แอสเซมเบลอร์แรกถูกเขียนในรหัสเครื่อง คอมไพเลอร์ C ตัวแรกเขียนขึ้นในชุดประกอบ (น่าจะเป็นมากที่สุด) และอื่น ๆ
Scott Whitlock

1
ฉันจะเปลี่ยนคำจำกัดความของคอมไพเลอร์ พวกเขาไม่ได้ปล่อยรหัสเครื่องทั้งหมด โดยเฉพาะอย่างยิ่งในปัจจุบันที่มีคอมไพเลอร์จำนวนมากเปล่ง "รหัสกลาง" เช่น MSIL มีคอมไพเลอร์ที่ปล่อยจาวาสคริปต์!
Neil N

3
ฉันลังเลที่จะระบุว่าคอมไพเลอร์สร้างรหัสเครื่องตามคำจำกัดความแม้เมื่ออธิบายให้กับผู้เริ่มต้น นั่นเหมือนกับการพูดว่าฟังก์ชั่นคืนค่าจำนวนจริง ทั้งหมดของการก่อสร้างคอมไพเลอร์ถือเมื่อการผลิตรหัสที่ไม่ได้สำหรับคอมพิวเตอร์ที่สร้างขึ้นจริงจากซิลิกอน แต่กำหนดไว้เพียงนามธรรม (ไม่ว่าจะเป็น VM หรือภาษาระดับสูงมีเหตุผลของมันกล่าวว่ามาตรฐาน C กำหนดต์เครื่องนามธรรมและมี เป็นคอมไพเลอร์จาก LLVM IR ระดับต่ำมากถึง friggin 'JavaScript) ผู้เริ่มต้นจำเป็นต้องได้รับสิ่งนั้นยิ่งเร็วเท่าไร

2
การทำให้เข้าใจง่ายที่หนังสือคอมไพเลอร์ส่วนใหญ่ใช้คือคอมไพเลอร์ใช้กฎภาษาเพื่อแปลงจากภาษาต้นฉบับเป็นภาษาเป้าหมายเป็นเอาต์พุต (ไม่ใช่เรื่องแปลกที่จะคอมไพล์ไปที่ C เช่นโดยเฉพาะอย่างยิ่งสำหรับหลักสูตรเบื้องต้น)
JasonTrue

4
@delnan ยิ่งขึ้น - ทุกภาษาเป็นรหัสเครื่องสำหรับเครื่องนามธรรมของตัวเอง ไม่ว่าภาษาจะอยู่ในระดับใด
SK-logic

11

ในขณะที่คุณชี้ให้เห็นว่ามนุษย์สื่อสารผ่านภาษา "ธรรมชาติ" เช่นอังกฤษฝรั่งเศสเยอรมันระหว่างกัน พวกเขาถูกเรียกว่าเป็นธรรมชาติเพราะเราได้มาโดยธรรมชาติแทนที่จะสร้างสิ่งเหล่านั้นโดยเจตนา (ภาษาเป็นข้อยกเว้น)

ภาษาทางการเป็นภาษาที่คิดค้นขึ้นเพื่อวัตถุประสงค์บางอย่างหรืออื่น ๆ ยกตัวอย่างเช่นภาษาการเขียนโปรแกรมเช่น C เป็นภาษาทางการที่ประดิษฐ์ขึ้นเพื่อจุดประสงค์ของการเขียนโปรแกรมคอมพิวเตอร์

ทุกภาษาสามารถอธิบายได้โดยใช้ไวยากรณ์ ลำดับชั้นของไวยากรณ์ถูกอธิบายโดย Noam Chomsky ในปี 1956 ประกอบด้วยระดับดังต่อไปนี้:

Type-0 grammars (ไวยากรณ์ที่ไม่ จำกัด ) พวกเขาเป็นคนทั่วไปและเทียบเท่ากับทัวริงเครื่องจักร ดังนั้นปัญหาในการตัดสินใจว่าสตริงที่กำหนดนั้นเป็นส่วนหนึ่งของไวยากรณ์ที่ไม่ จำกัด หรือไม่นั้นไม่สามารถตัดสินใจได้

ไวยากรณ์ของ Type-1 (ไวตามบริบท) ภาษาธรรมชาติเกือบทั้งหมดเช่นภาษาอังกฤษนั้นคำนึงถึงบริบท ตัวอย่างของความไวต่อบริบทในภาษาอังกฤษคือวลีสองคำ: "เวลาผ่านไปเหมือนลูกศร" และ "ผลไม้บินได้เหมือนกล้วย" โดยทั่วไปแล้วมันเป็นเรื่องยากสำหรับคอมพิวเตอร์ที่จะเข้าใจภาษาที่ไวต่อบริบท

ไวยากรณ์ประเภท 2 (ปราศจากบริบท) ภาษาที่ไม่มีบริบทเป็นพื้นฐานทางทฤษฎีสำหรับไวยากรณ์ของภาษาโปรแกรมส่วนใหญ่

Type-3 grammars (ไวยากรณ์ปกติ) ครอบครัวของภาษาปกติสามารถรับได้จากการแสดงออกปกติ ภาษาทั่วไปมักใช้เพื่อกำหนดรูปแบบการค้นหาและโครงสร้างคำศัพท์ของภาษาโปรแกรม

ประเภทที่ 2 (ปราศจากบริบท) และไวยากรณ์ประเภทที่ 3 (ปกติ) ส่วนใหญ่มักจะใช้คอมพิวเตอร์เพราะตัวแยกวิเคราะห์สำหรับตัวแยกวิเคราะห์สามารถนำไปใช้ได้อย่างมีประสิทธิภาพ

BNF (รูปแบบปกติของ Backus หรือรูปแบบ Backus – Naur)เป็นเทคนิคสัญกรณ์สำหรับไวยากรณ์ที่ปราศจากบริบทมักใช้เพื่ออธิบายไวยากรณ์ของภาษาที่ใช้ในการคำนวณ

ตัวอย่างเช่นตัวระบุอาจถูกอธิบายว่า:

<identifier> ::= <letter> { <letter> | <digit> }

ซึ่งหมายความว่าจะต้องเริ่มต้นด้วยตัวอักษรและสามารถมีตัวอักษรหรือตัวเลขเพิ่มเติม

ก่อนหน้านี้จดหมายถูกกำหนดเป็น 'a' | 'b' | 'c' ฯลฯ และตัวเลขถูกกำหนดเป็น '0' ถึง '9' โดยใช้สัญกรณ์ชนิดเดียวกัน

คำสั่ง "สำหรับ" AC อาจถูกกำหนดเป็น:

 <for_statement> ::=
    'for' '(' <expression> ';' <expression> ';' <expression> ')' <statement> 

ตัววิเคราะห์คำศัพท์และตัวแยกวิเคราะห์ (ขั้นตอนแรกของคอมไพเลอร์หรือล่าม) จะถูกสร้างขึ้นเพื่อยอมรับไวยากรณ์เฉพาะที่อธิบายโดย BNF สำหรับภาษาเฉพาะ โดยทั่วไปแล้วการวิเคราะห์คำศัพท์จะใช้ในการแยกโทเค็นต่าง ๆ ของภาษา (เช่นคำหลักตัวระบุหรือตัวเลข) และตัวแยกวิเคราะห์จะใช้เพื่อหาว่าโทเค็นทำงานร่วมกันอย่างไรเช่นการสร้างคำสั่ง "สำหรับ" .


+1 บทความที่ยอดเยี่ยม แต่ฉันไม่แปลกใจที่นี่ไม่ได้รับการยอมรับว่าเป็นคำตอบ นี่คือสิ่งที่ฉันคิดว่า OP ขอ แต่ตามคำตอบที่พวกเขาเลือกดูเหมือนว่าพวกเขาต้องการระดับที่สูงกว่ามาก
Matthew Rodatus

5

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

ในระดับพื้นฐานที่สุดนี้ C # ไม่ใช่ทุกสิ่งที่แตกต่างจากภาษาอังกฤษ สิ่งที่ทำให้ C # เป็น "ภาษาโปรแกรม" คือเจตนาของมันและดังนั้นการออกแบบ มันถูกออกแบบมาให้ย่อยลงในคำสั่งระดับต่ำแต่ละรายการ ดังนั้นคำศัพท์ที่กำหนดไว้ล่วงหน้าจะถูก จำกัด ไวยากรณ์มีการบังคับใช้อย่างเข้มงวดและภาษาทั้งหมดได้รับการออกแบบมาเพื่อการบริโภคในวิธีที่กำหนดไว้ล่วงหน้าที่รู้จักกันดีโดย "ผู้ชม" ของมัน (คอมพิวเตอร์; คอมไพเลอร์ที่แม่นยำมากขึ้น ซอร์สโค้ดเป็น "ภาษากลาง" ของคำสั่งง่าย ๆ ที่สามารถแปลต่อไปในรหัสเครื่องโดย "รันไทม์") คุณไม่ได้เขียนร้อยแก้วหรือร้อยกรองใน C #; คุณบอกให้คอมพิวเตอร์ทำงานในลักษณะที่ชัดเจนที่สุดเท่าที่จะทำได้

สำหรับคอมพิวเตอร์จำเป็นต้องใช้เครื่องมือที่เรียกว่าคอมไพเลอร์ซึ่งจำเป็นต้องใช้สิ่งที่คุณเขียนในโค้ดและแปลงเป็นคำแนะนำที่คอมพิวเตอร์สามารถใช้ได้ วิทยาการคอมพิวเตอร์เช่นเดียวกับเทคโนโลยีส่วนใหญ่เป็นกระบวนการที่ซ้ำซ้อน "ซ้ำซ้อน" เมื่อคอมพิวเตอร์ถูกคิดค้นครั้งแรกพวกเขาถูกโปรแกรมโดยป้อนคำแนะนำแบบไบนารีด้วยตนเอง คำแนะนำเหล่านั้นกลายเป็นมาตรฐานสำหรับโปรเซสเซอร์แต่ละตัวในเลขฐานสิบหก "รหัสเครื่อง"; ความแตกต่างเป็นเพียงวิธีการจัดกลุ่มเลขฐานสองสำหรับแสดงต่อมนุษย์ จากนั้นในรหัสแอสเซมเบลอร์รายการคำสั่งและตัวระบุพื้นฐานบางอย่างเช่นชื่อรีจิสเตอร์จะถูกแทนที่ด้วยรหัสเลขฐานสิบหกเมื่อเขียนโปรแกรม ASM ยังสามารถแปลง 1: 1 เป็นรหัสเครื่องได้ การกระโดดควอนตัมคือการเขียนโปรแกรม "จำเป็น" รุ่นที่ 3 ซึ่งโดยทั่วไปจะใช้แนวคิดที่เป็นมนุษย์ที่เข้าใจได้ง่ายขึ้นเช่นตัวแปรและลอจิกแบบลอจิกและย่อยลงในคำแนะนำแบบเนทีฟโดยใช้รูปแบบตามคำหลักและไวยากรณ์ ภาษาแรก ๆ เช่น COBOL, FORTRAN, Pascal และ C ยังคงสามารถ "แปล" โดยมนุษย์เป็นภาษาเครื่องเฉพาะ (ปกติ 8086 ASM) จากนั้นเป็นการปฏิวัติการเขียนโปรแกรมเชิงวัตถุซึ่งโดยทั่วไปคือกฎไวยากรณ์เพิ่มเติมที่กำหนดรหัสว่าถูกห่อหุ้มด้วยแนวคิดใน "วัตถุ" ที่มีการผสมผสานระหว่างสถานะและตรรกะบางอย่าง โดยมนุษย์เป็นภาษาเครื่องโดยเฉพาะ (ปกติ 8086 ASM) จากนั้นเป็นการปฏิวัติการเขียนโปรแกรมเชิงวัตถุซึ่งโดยทั่วไปคือกฎไวยากรณ์เพิ่มเติมที่กำหนดรหัสว่าถูกห่อหุ้มด้วยแนวคิดใน "วัตถุ" ที่มีการรวมกันของสถานะและตรรกะบางอย่าง โดยมนุษย์เป็นภาษาเครื่องโดยเฉพาะ (ปกติ 8086 ASM) จากนั้นเป็นการปฏิวัติการเขียนโปรแกรมเชิงวัตถุซึ่งโดยทั่วไปคือกฎไวยากรณ์เพิ่มเติมที่กำหนดรหัสว่าถูกห่อหุ้มด้วยแนวคิดใน "วัตถุ" ที่มีการรวมกันของสถานะและตรรกะบางอย่าง

ทุกวันนี้เราเข้ากันได้ดีกับ "รุ่นที่ 4" ของภาษาซึ่งเป็นภาษาที่เขียนขึ้นเพื่อกำหนดการสื่อสารกับโปรแกรมอื่นแทนที่จะไปที่เครื่องโดยตรง มีการระบุอย่างกว้างขวางซึ่งรวมถึงภาษา "มาร์กอัป" เช่น XML / HTML, "สคริปต์" เช่น JavaScript และ SQL และภาษา "แซนด์บ็อกซ์" ส่วนใหญ่เช่น Java และ. NET Framework (ซึ่งรวบรวมเป็น IL ที่ถูกตีความเพิ่มเติมโดย รันไทม์ที่ย่อไปจากเครื่องและรายละเอียดเฉพาะของแพลตฟอร์ม) คุณสามารถพูดได้ว่ามันครอบคลุมขอบเขตของภาษาโปรแกรมที่ใช้งานได้ซึ่งขึ้นอยู่กับรันไทม์เพื่อให้นามธรรมไม่เพียง แต่รายละเอียดเฉพาะเครื่อง แต่รวมถึงรายละเอียดเฉพาะการทำงาน ภาษาในยุคที่ 4 เหล่านี้เป็นไปไม่ได้ที่มนุษย์จะสามารถแปลเป็นคำสั่งในเครื่องได้ และประเด็นก็คือว่ามันจะไม่พยายามอย่างคุ้มค่า จุดแข็งของภาษาเหล่านี้คือกระบวนการที่ใช้เลเยอร์เพื่อบอกคอมพิวเตอร์ว่าต้องทำอะไรในระดับต่ำ


ขอบคุณ ฉันมีเหลือบไปที่ประวัติศาสตร์ของการพัฒนาภาษาการเขียนโปรแกรม
Erica Xu

2
@KeithS: คุณอาจต้องการฟอร์แมตย่อหน้าสุดท้ายเพื่อให้อ่านได้ง่ายขึ้น
Ivan Vučica

4

มันเป็นคำถามที่ดี คำตอบที่เหมาะสมก่อให้เกิดครึ่งหนึ่งของสิ่งที่เรียกว่า "วิทยาศาสตร์คอมพิวเตอร์"

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

หากข้างต้นเป็นวิชาการเกินไปคุณสามารถเริ่มต้นด้วยPetzold "รหัส"แล้วกลับมาที่ความหมาย


1
คุณคาดหวังว่าผู้ที่อายุ 18 ปีจะอ่านทฤษฎีหนัก ๆ เพื่อตอบคำถามนี้?
งาน

2
@Job ตามคำถามก่อนหน้านี้ของเขาเขาได้รับ Scheme (และ SICP) ในมหาวิทยาลัย ควรปรับด้วยความหมายเล็กน้อยแล้ว อย่างไรก็ตามไม่มีคำตอบที่เหมาะสมสำหรับคำถามนี้โดยไม่มีทฤษฎีหนัก
SK-logic

+1 สำหรับการกล่าวถึง "รหัส" ควรอ่านหนังสือเล่มนั้นสำหรับนักเรียน CS ระดับเริ่มต้นทุกคน
Daniel Pryden

4

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

  1. ผู้ใช้เขียนโปรแกรมในภาษาระดับสูง (C) ซึ่ง CPU ไม่เข้าใจ แต่เป็นที่เข้าใจโดยตรงโดยโปรแกรมเมอร์ (เราหวังว่า!)

  2. คอมไพเลอร์แปลง C เป็นภาษา Assmebly ซึ่ง CPU ไม่เข้าใจโดยตรง แต่ง่ายต่อการแปลงเป็นอย่างอื่นนั่นคือ

  3. Assempler แปลง Assembly เป็นลำดับของรหัสไบนารี่ที่ CPU เข้าใจโดยตรง คอมไพเลอร์บางคนข้ามขั้นตอนข้างต้น (ขั้นตอนที่ 2) และสร้างไบนารีที่คอมไพล์โดยตรงจากซอร์สโค้ด

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

ในการสร้างภาษาใหม่คุณต้องออกแบบภาษาระดับสูงก่อนจากนั้นคุณต้องหาวิธีการแมปสัญลักษณ์ของภาษาใหม่ของคุณกับคำสั่งภาษาแอสเซมบลีที่ CPU ของคุณเข้าใจ


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