IMO จะรวมอยู่ใน Java และ C # เป็นหลักเนื่องจากมีอยู่แล้วใน C ++ คำถามจริงคือทำไม C ++ เป็นแบบนั้น ตามการออกแบบและวิวัฒนาการของ C ++ (§16.3):
try
คำหลักซ้ำซ้อนอย่างสมบูรณ์และเพื่อให้มี{ }
วงเล็บยกเว้นในกรณีที่งบหลายถูกนำมาใช้จริงในการลองบล็อกหรือจัดการ ตัวอย่างเช่นมันจะไม่สำคัญที่จะอนุญาตให้:
int f()
{
return g() catch(xxii) { // not C++
error("G() goofed: xxii");
return 22;
};
}
อย่างไรก็ตามฉันพบว่ามันยากที่จะอธิบายว่ามีการแนะนำความซ้ำซ้อนเพื่อช่วยเจ้าหน้าที่ฝ่ายสนับสนุนจากผู้ใช้ที่สับสน
แก้ไข: สาเหตุที่ทำให้เกิดความสับสนฉันคิดว่ามีเพียงการดูคำยืนยันที่ไม่ถูกต้องในคำตอบของ @Tom Jeffery (และโดยเฉพาะอย่างยิ่งจำนวนคะแนนที่ได้รับ) เพื่อตระหนักว่าจะมีปัญหา การแยกวิเคราะห์นี้เป็นจริงไม่แตกต่างจากการจับคู่else
S กับif
s - ขาดการจัดฟันที่จะบังคับให้จัดกลุ่มอื่น ๆทุก คำสั่งจะตรงกับล่าสุดcatch
throw
สำหรับภาษาที่มีการใช้ภาษาที่ผิด ๆfinally
ข้อนั้นจะทำเช่นเดียวกัน จากมุมมองของ parser นี่แทบจะไม่แตกต่างจากสถานการณ์ปัจจุบันที่จะสังเกตเห็น - โดยเฉพาะอย่างยิ่งเมื่อ grammars ยืนอยู่ในขณะนี้ไม่มีอะไรที่จะจัดกลุ่มcatch
คำสั่งด้วยกัน - กลุ่มวงเล็บคำสั่งที่ควบคุมโดยcatch
ข้อไม่จับตัวเอง
จากมุมมองของการเขียนโปรแกรมแยกวิเคราะห์ความแตกต่างนั้นเล็กเกินกว่าจะสังเกตได้ ถ้าเราเริ่มต้นด้วยสิ่งนี้:
simple_statement: /* won't try to cover all of this */
;
statement: compound_statement
| simple_statement
;
statements:
| statements statement
;
compound_statement: '{' statements '}'
catch_arg: '(' argument ')'
จากนั้นความแตกต่างจะอยู่ระหว่าง:
try_clause: 'try' statement
และ:
try_clause: 'try' compound_statement
เช่นเดียวกันสำหรับข้อที่:
catch_clause: 'catch' catch_arg statement
เมื่อเทียบกับ
catch_clause: 'catch' catch_arg compound_statement
คำจำกัดความของบล็อก try / catch ที่สมบูรณ์นั้นไม่จำเป็นต้องเปลี่ยนแปลงเลย ไม่ว่าด้วยวิธีใดมันจะเป็นสิ่งที่ชอบ:
catch_clauses:
| catch_clauses catch_clause
;
try_block: try_clause catch_clauses [finally_clause]
;
[ที่นี่ฉันใช้[whatever]
เพื่อระบุสิ่งที่ไม่จำเป็นและฉันทิ้งไวยากรณ์สำหรับfinally_clause
เนื่องจากฉันไม่คิดว่ามันจะมีผลกับคำถาม]
แม้ว่าคุณจะไม่พยายามที่จะทำตามทุก Yacc เหมือนการกำหนดไวยากรณ์มีจุดสามารถสรุปได้อย่างเป็นธรรมได้อย่างง่ายดาย: ที่คำสั่งสุดท้าย (เริ่มต้นด้วยtry_block
) เป็นหนึ่งในที่catch
คำสั่งได้รับการจับคู่กับtry
คำสั่ง - และมันยังคงอยู่ตรงเหมือนกันไม่ว่าจะเป็นเครื่องมือจัดฟันที่จำเป็นหรือไม่
ย้ำ / สรุป: วงเล็บกลุ่มกันงบควบคุมโดยcatch
s แต่ทำไม่ได้กลุ่มcatch
s ตัวเอง เช่นการจัดฟันเหล่านั้นได้อย่างไม่มีผลต่อการตัดสินใจที่จะไปด้วยซึ่งcatch
try
สำหรับ parser / คอมไพเลอร์งานก็ง่ายเหมือนกัน (หรือยาก) ทั้งสองวิธี แม้จะมีสิ่งนี้คำตอบของ @ ทอม (และจำนวนคะแนนที่ได้รับจะเพิ่มขึ้น) แสดงให้เห็นถึงความจริงที่ว่าการเปลี่ยนแปลงเช่นนี้จะสร้างความสับสนให้กับผู้ใช้
for
ชิ้นส่วนควรตั้งชื่อสิ่งที่ต้องการinitial
,condition
และstep
เป็นinitial
ความต้องการไม่ได้กำหนดตัวแปรและstep
ไม่จำเป็นต้องเพิ่มขึ้น