(นานกว่าที่ตั้งใจไว้โปรดอดทนรอด้วย)
ภาษาส่วนใหญ่ประกอบด้วยสิ่งที่เรียกว่า "ไวยากรณ์": ภาษาประกอบด้วยคำหลักหลายคำที่กำหนดไว้อย่างดีและช่วงของนิพจน์ทั้งหมดที่คุณสามารถสร้างในภาษานั้นสร้างขึ้นจากไวยากรณ์นั้น
ตัวอย่างเช่นสมมติว่าคุณมี "ภาษา" เลขคณิตสี่ฟังก์ชันที่ใช้เฉพาะจำนวนเต็มหลักเดียวเป็นอินพุตและไม่สนใจลำดับของการดำเนินการโดยสิ้นเชิง (ฉันบอกคุณแล้วว่ามันเป็นภาษาง่ายๆ) ภาษานั้นสามารถกำหนดได้โดยไวยากรณ์:
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
จากกฎทั้งสามนี้คุณสามารถสร้างนิพจน์เลขคณิตอินพุตหลักเดียวจำนวนเท่าใดก็ได้ จากนั้นคุณสามารถเขียน parser สำหรับรูปแบบนี้ที่หยุดพักลงการป้อนข้อมูลที่ถูกต้องเป็นประเภทที่เป็นส่วนประกอบของ ( $expression
, $number
หรือ$operator
) และข้อตกลงที่มีผล ตัวอย่างเช่นนิพจน์3 + 4 * 5
สามารถแบ่งออกได้ดังนี้:
$expression = 3 + 4 * 5
= $expression $operator (4 * 5)
= $number $operator $expression
= $number $operator $expression $operator $expression
= $number $operator $number $operator $number
ตอนนี้เรามีไวยากรณ์ที่แยกวิเคราะห์อย่างสมบูรณ์ในภาษาที่เรากำหนดสำหรับนิพจน์ดั้งเดิม เมื่อเรามีนี้เราสามารถไปถึงและเขียนแยกวิเคราะห์เพื่อหาผลของการรวมกันทั้งหมดของ$number $operator $number
และถ่มน้ำลายออกผลเมื่อเรามีเพียงหนึ่ง$number
ซ้าย
โปรดทราบว่าไม่มี$expression
โครงสร้างเหลืออยู่ในเวอร์ชันที่แยกวิเคราะห์ขั้นสุดท้ายของนิพจน์ดั้งเดิมของเรา นั่นเป็นเพราะ$expression
สามารถลดลงเป็นการรวมกันของสิ่งอื่นในภาษาของเรา
PHP นั้นเหมือนกันมาก: โครงสร้างภาษาได้รับการยอมรับว่าเทียบเท่ากับ$number
หรือ$operator
. พวกเขาไม่สามารถลดลงในโครงสร้างภาษาอื่น ; แต่เป็นหน่วยฐานที่สร้างภาษาขึ้นมา ความแตกต่างที่สำคัญระหว่างฟังก์ชันและโครงสร้างภาษาคือสิ่งนี้ตัวแยกวิเคราะห์เกี่ยวข้องโดยตรงกับโครงสร้างภาษา ช่วยลดความซับซ้อนของฟังก์ชันลงในโครงสร้างภาษา
เหตุผลที่โครงสร้างภาษาอาจต้องใช้วงเล็บหรือไม่และเหตุผลบางอย่างมีค่าส่งคืนในขณะที่บางส่วนไม่ได้ขึ้นอยู่กับรายละเอียดทางเทคนิคเฉพาะของการใช้งานตัวแยกวิเคราะห์ PHP ฉันไม่ค่อยเชี่ยวชาญในการทำงานของโปรแกรมแยกวิเคราะห์ดังนั้นฉันจึงไม่สามารถตอบคำถามเหล่านี้โดยเฉพาะได้ แต่ลองนึกภาพภาษาที่สองที่ขึ้นต้นด้วยสิ่งนี้:
$expression := ($expression) | ...
อย่างมีประสิทธิภาพภาษานี้มีอิสระที่จะใช้นิพจน์ใด ๆ ที่พบและกำจัดวงเล็บโดยรอบ PHP (และที่นี่ฉันใช้การคาดเดาล้วนๆ) อาจใช้สิ่งที่คล้ายกันสำหรับโครงสร้างภาษา: print("Hello")
อาจลดลงprint "Hello"
ก่อนที่จะแยกวิเคราะห์หรือในทางกลับกัน (คำจำกัดความภาษาสามารถเพิ่มวงเล็บและกำจัดได้)
นี่คือต้นตอของสาเหตุที่คุณไม่สามารถกำหนดโครงสร้างภาษาใหม่ได้เช่นecho
หรือprint
: พวกมันถูกฮาร์ดโค้ดลงในตัววิเคราะห์อย่างมีประสิทธิภาพในขณะที่ฟังก์ชั่นถูกแมปกับชุดของโครงสร้างภาษาและตัวแยกวิเคราะห์ช่วยให้คุณสามารถเปลี่ยนการแมปที่คอมไพล์หรือรันไทม์เป็น แทนที่ชุดของโครงสร้างภาษาหรือนิพจน์ของคุณเอง
ในตอนท้ายของวันความแตกต่างภายในระหว่างโครงสร้างและนิพจน์คือสิ่งนี้: โครงสร้างภาษาจะเข้าใจและจัดการกับตัววิเคราะห์ ฟังก์ชั่นในตัวในขณะที่จัดเตรียมโดยภาษาจะถูกแมปและทำให้ง่ายขึ้นกับชุดของโครงสร้างภาษาก่อนที่จะแยกวิเคราะห์
ข้อมูลเพิ่มเติม:
แก้ไข: การอ่านคำตอบอื่น ๆ บางส่วนผู้คนให้คะแนนที่ดี ในหมู่พวกเขา:
- ภาษาในตัวเรียกได้เร็วกว่าฟังก์ชัน นี่เป็นความจริงหากเพียงเล็กน้อยเนื่องจากตัวแปล PHP ไม่จำเป็นต้องแมปฟังก์ชันนั้นกับฟังก์ชันที่สร้างขึ้นในภาษาของตนก่อนที่จะแยกวิเคราะห์ อย่างไรก็ตามสำหรับเครื่องจักรที่ทันสมัยความแตกต่างนั้นค่อนข้างเล็กน้อย
- ภาษาในตัวจะข้ามการตรวจสอบข้อผิดพลาด สิ่งนี้อาจเป็นจริงหรือไม่ก็ได้ขึ้นอยู่กับการใช้งานภายใน PHP สำหรับบิวด์อินแต่ละตัว แน่นอนว่าบ่อยกว่านั้นฟังก์ชันจะมีการตรวจสอบข้อผิดพลาดขั้นสูงและฟังก์ชันอื่น ๆ ที่ในตัวไม่มี
- ไม่สามารถใช้โครงสร้างภาษาเป็นการเรียกกลับของฟังก์ชันได้ นี่คือความจริงเพราะสร้างเป็นไม่ได้ฟังก์ชั่น พวกเขาเป็นหน่วยงานที่แยกจากกัน เมื่อคุณเขียนโค้ดในตัวคุณจะไม่ได้เข้ารหัสฟังก์ชันที่รับอาร์กิวเมนต์ - ไวยากรณ์ของบิวอินจะถูกจัดการโดยตรงโดยตัววิเคราะห์และได้รับการยอมรับว่าเป็นบิวอินแทนที่จะเป็นฟังก์ชัน (สิ่งนี้อาจเข้าใจง่ายกว่าถ้าคุณพิจารณาภาษาที่มีฟังก์ชันชั้นหนึ่ง: อย่างมีประสิทธิภาพคุณสามารถส่งผ่านฟังก์ชันไปรอบ ๆ เป็นวัตถุได้คุณไม่สามารถทำได้ด้วยบิวด์อิน