ภาษาการเขียนโปรแกรมส่วนใหญ่ดูเหมือนจะได้รับการออกแบบให้ไม่อนุญาตให้หนึ่งประกาศตัวระบุที่ขึ้นต้นด้วยตัวเลข ฉันแค่อยากรู้อยากเห็นเหตุผล ฉันค้นหาเว็บแล้ว แต่ไม่พบคำอธิบายที่น่าพอใจ
ภาษาการเขียนโปรแกรมส่วนใหญ่ดูเหมือนจะได้รับการออกแบบให้ไม่อนุญาตให้หนึ่งประกาศตัวระบุที่ขึ้นต้นด้วยตัวเลข ฉันแค่อยากรู้อยากเห็นเหตุผล ฉันค้นหาเว็บแล้ว แต่ไม่พบคำอธิบายที่น่าพอใจ
คำตอบ:
ใน C / C ++ ตัวเลขที่ตามด้วยตัวอักษรจะถือว่าเป็นค่าคงที่ตัวเลขและสตริงที่ตามมาจะมีคุณสมบัติตามประเภทของค่าคงที่ ตัวอย่างเช่น (นี่คือ VC ++, ไม่แน่ใจว่ามาตรฐานเป็นอย่างไร):
a) มันง่ายกว่าสำหรับ lexer อย่างที่ Daniel บอก แต่ยัง b) มันสร้างความแตกต่างอย่างชัดเจนตั้งแต่ 0y อาจเป็นตัวแปร แต่ 0u จะไม่เป็นเช่นนั้น นอกจากนี้ยังมีการเพิ่มตัวระบุอื่น ๆ เช่น "i64" ในภายหลังช้ากว่า "l" หรือ "u" และพวกเขาต้องการเปิดตัวเลือกในการเพิ่มมากขึ้นหากจำเป็น
ความสะดวกสบายของผู้คนที่ใช้งาน lexer (ไม่จริงจังนั่นคือเกี่ยวกับมันภาษาต่าง ๆ มีเหตุผลอื่น ๆ แต่ท้ายที่สุดมันลงมาที่)
0flu
เป็นตัวอักษรและ0glu
เป็นตัวระบุในท้องถิ่น
int 0u = 5; unsigned int x = 0u;
อย่างไรก็ตามคุณเลือกที่จะนิยามการตีความของรหัสนี้ (น่าจะเป็น x == 0 หรือ x == 5) ผู้คนจะสับสน เพราะความกำกวม แม้ว่ามันจะไม่สำคัญที่จะใช้คอมไพเลอร์ด้วยวิธีนี้นักออกแบบที่ดีก็ไม่น่าจะทำได้
พิจารณา 2 กรณีต่อไปนี้:
สมมติว่าตัวบ่งชี้เริ่มต้นด้วยตัวเลข
ดังนั้นคำสั่งด้านล่างจะใช้ได้ (เนื่องจากตัวระบุสามารถมี 1 ตัวอักษรหรือมากกว่า):
int 3;
เมื่อฉันพยายามใช้ตัวแปรข้างต้นในโปรแกรมมันจะส่งผลให้คอมไพเลอร์คลุมเครือ:
int 3, a;
3 = 5;
A = 3;
ในคำสั่งa=3
บทบาทของ 3 คืออะไร (เป็นตัวแปรที่มีค่า 5 หรือเป็นตัวเลข 3)?
ตรงข้ามกับตัวอย่างด้านบนสมมติว่าภาษานั้นอนุญาตให้ตัวระบุที่ขึ้นต้นด้วยตัวเลขในขณะที่ยังคงไม่อนุญาตให้ใช้ตัวเลขเป็นตัวระบุ ซึ่งอาจทำให้เกิดปัญหาต่อไปนี้:
กฎภาษาที่เกี่ยวข้องกับตัวแปรที่ระบุว่าตัวแปรอาจประกอบด้วย 1 ตัวอักษรหรือมากกว่านั้นจะต้องถูกนิยามใหม่ให้เป็นกฎที่ซับซ้อนเช่น: ตัวแปรสามารถมีอักขระหนึ่งตัวขึ้นไปและจะต้องไม่ซ้ำกันหากไม่ได้ขึ้นต้นด้วยตัวเลขในขณะที่ มันไม่สามารถมีความยาวอักขระเดียวเมื่อเริ่มต้นด้วยตัวเลข (ฯลฯ .. )
คอมไพเลอร์จะต้องตรวจสอบและรายงานกรณีข้อผิดพลาดเมื่อใช้ตัวเลขทั้งหมด (เช่น 333) และคำต่อท้ายตัวอักษรที่ถูกต้อง (เช่น 34L) เป็นชื่อตัวแปร ในภาษาที่พิมพ์อย่างหลวม ๆ เช่น Python และ JS ที่คุณสามารถใช้ตัวแปรได้ทันทีโดยไม่ต้องประกาศมันอาจเป็นไปไม่ได้ที่จะตรวจสอบกรณีพิเศษที่เกี่ยวข้องกับตัวเลขทั้งหมดเช่นที่if (33==5)
นี่ 33 อาจเป็นตัวแปรที่ไม่ได้ประกาศผิดที่ผู้ใช้ประกาศ แต่คอมไพเลอร์จะไม่สามารถระบุสิ่งนี้และรายงานข้อผิดพลาด
การ จำกัด นี้จะป้องกันโปรแกรมเมอร์จากการใช้ตัวเลขเป็นชื่อตัวระบุ
int char = float
จะเกิดขึ้นได้อย่างไร?
int
เป็นคำหลักและไม่ใช่ตัวระบุได้อย่างไร ดีint
มีความสำคัญสูงกว่าเช่นเดียวกับตัวเลข numical จะมี
int 3,a; 3=5; a=3;
ในคำสั่ง a = 3, 3 ถูกตีความว่าเป็นตัวระบุหรือเป็นตัวเลขหรือไม่? สิ่งนี้ทำให้เกิดความกำกวม หวังว่ามันชัดเจน
ส่วนใหญ่ไม่มีส่วนเกี่ยวข้องกับการทำให้ผู้เขียนคอมไพเลอร์และประสิทธิภาพในการแยกวิเคราะห์ง่ายขึ้น แต่ส่วนมากเกี่ยวกับการออกแบบไวยากรณ์ที่ส่งเสริมการอ่านที่ชัดเจนและไม่คลุมเครือ
นักออกแบบภาษาที่มันคิดว่ามันจะดีที่จะสามารถที่จะเขียนตัวอักษรตัวเลขเช่นหมายเลข 1 เป็นเพียงธรรมดา1
มันจะค่อนข้างเป็นไปได้ในการออกแบบไวยากรณ์ภาษาที่ตัวอักษรตัวเลขถูกยกมาในทางใดทางหนึ่งเช่น tildas ดังนั้นตัวอักษรตัวเลขสำหรับหมายเลขหนึ่งถูกเข้ารหัสเป็น~ 1 ~และสิ่งที่ไม่ใช่คำหลักและไม่ได้อยู่ในเครื่องหมายคำพูดจะถือว่าเป็นชื่อตัวแปร .
ดังนั้นคุณสามารถรหัสงบเช่น:
1 = ~2~
two = 1 * ~2~
แต่ยัง:
2 = ~3~
six = 2 + 2
ไม่ว่าคุณจะเลือกใช้ไวยากรณ์ที่คลุมเครือและยากที่จะทำตามโค้ดใดก็ตาม
ภาษาซีและภาษาส่วนใหญ่ของ "วงเล็บปีกกา" ที่สืบทอดมาจากภาษาซียังคิดว่าเป็นความคิดที่ดีที่จะอนุญาตให้โปรแกรมเมอร์เขียนรหัสตัวอักษร Octal และเลขฐานสิบหกโดยตรงและเพื่อระบุประเภทของตัวอักษรหากนี่เป็นสิ่งสำคัญ ดังนั้น
010 // Octal 10 = 8;
0x10 // Hexadecimal 10 = 16;
5l // long integer with decimal value 5
2.0d // double float with value 2
ดังนั้นแม้ว่าคุณจะอนุญาตให้ชื่อตัวแปรเริ่มต้นด้วยตัวเลขตามด้วยการรวมกันของตัวเลขและตัวอักษรที่มีตัวอักษรอย่างน้อยหนึ่งตัวคุณจะต้องนำเสนอโปรแกรมเมอร์ที่มีปัญหาในการตัดสินใจว่ากลุ่มที่กำหนดเกิดขึ้นชื่อตัวแปรหรือตัวอักษรตัวเลขดังนั้น
2lll = 22 // OK
2ll = 2 // compiler error
ความคลุมเครือดังกล่าวจะไม่ช่วยให้ใครเขียนหรืออ่านโปรแกรม
สำหรับตัวอย่างที่เกี่ยวข้องกับโลกแห่งความจริงอย่างใกล้ชิดคุณสามารถดูภาษา PL / 1 ซึ่งนักออกแบบคิดว่าการใช้คำหลักเป็นชื่อตัวแปรเป็นแนวคิดที่ดีดังนั้น:
IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;
IF IF THEN ELSE = IF; ELSE THEN = ELSE;
DO WHILE (WHILE = DO); END = WHILE + DO; END;
เป็นรหัสที่ถูกต้องซึ่งรวบรวมและดำเนินการ
Fortran มีผลอย่างมากต่อการออกแบบภาษาในภายหลัง แต่เนิ่นๆ (ปัญหาเหล่านี้บางส่วนได้รับการแก้ไขแล้ว) Fortran แทบไม่มีกฎใด ๆ ที่ จำกัด ชื่อที่คุณสามารถให้แก่ตัวระบุได้ สิ่งนี้ทำให้ภาษาแยกวิเคราะห์ทั้งคอมไพเลอร์และโปรแกรมเมอร์ยากมาก นี่คือตัวอย่างคลาสสิก:
if if .eq. then then = else else else = endif endif
K I K K I I K I I K
ที่นี่ฉันได้ทำเครื่องหมาย "คำสำคัญภาษา" กับ K และตัวระบุ (ชื่อตัวแปร) I. เนื่องจากไม่มีการสะกดคำที่ต่างกันฉันคิดว่าคุณคงเข้าใจว่ามันสับสนได้อย่างไร แน่นอนว่านี่เป็นตัวอย่างที่ดีมากและไม่น่าจะมีใครเคยเขียนโค้ดแบบนี้มาก่อน บางครั้งคนทำ "รีไซเคิล" คำสำคัญภาษาเป็นชื่อตัวระบุ - และในหลาย ๆ กรณีพิมพ์ผิดง่ายอาจส่งผลในรหัสที่ spec ภาษากล่าวว่าควรจะแยกวิเคราะห์ด้วยวิธีนี้แม้ว่ามันจะไม่ได้ตั้งใจเลย สำหรับตัวอย่างที่รู้จักกันดีอื่นให้เปรียบเทียบสิ่งนี้:
do 10 i = 1,10
สำหรับสิ่งนี้:
do 10 i = 1.10
อันแรกคือวนรอบทำ - วนบล็อกของรหัส 10 ครั้ง ที่สอง แต่มีเครื่องหมายจุลภาคเปลี่ยนไปเป็นจุดทศนิยมจึงได้กำหนดค่าให้กับตัวแปรที่มีชื่อว่า1.10
do 10 i
นี่ก็หมายความว่าการเขียนตัวแยกวิเคราะห์ Fortran นั้นค่อนข้างยาก - คุณไม่แน่ใจว่าdo
จุดเริ่มต้นของบรรทัดนั้นเป็นคำสำคัญจริงๆจนกว่าคุณจะถึงจุดสิ้นสุดของบรรทัดและตรวจสอบว่าองค์ประกอบอื่น ๆ ของdo
ห่วงเป็นปัจจุบัน ตัวแยกวิเคราะห์โดยทั่วไปจะต้องพร้อมที่จะ "ย้อนกลับ" อีกครั้งแยกบรรทัดจากจุดเริ่มต้นที่จะมาถึง "ถูกต้อง" (แต่มักจะไม่ตั้งใจ) คำตอบของสิ่งที่อยู่ที่นั่นจริงๆ
หลังจากนั้นไม่กี่ปีที่ผ่านมานี้นักออกแบบภาษา (ส่วนใหญ่ของพวกเขาต่อไป) ไปหามากตรงข้าม - การ จำกัด การทุกอย่างเกือบเกี่ยวกับภาษามากที่สุดเท่าที่เป็นไปได้โดยไม่ต้องให้ผู้ใช้บ่นเกินไปมาก
ยกตัวอย่างเช่น BASIC ก่อนหน้านั้นโดยทั่วไปบอกว่าคุณไม่สามารถใช้คำสำคัญเป็นส่วนหนึ่งของตัวระบุได้ตัวอย่างเช่นfora=1
จะแยกวิเคราะห์เป็นfor a = 1
(เช่นจุดเริ่มต้นของfor
ลูปไม่ใช่การกำหนด) เห็นได้ชัดว่าสร้างการร้องเรียนมากพอที่จะใช้เวลาไม่นาน กฎเกี่ยวกับการเริ่มต้นตัวระบุที่มีตัวเลขไม่ได้สร้างการร้องเรียนจำนวนมากดังนั้นจึงยังคงมีการใช้ (อย่างน้อยก็ในภาษาส่วนใหญ่)
มีแนวโน้มว่าการประชุมนี้มีวิวัฒนาการมาจากการตัดสินใจออกแบบภาษาในยุคแรก ๆ เช่นเดียวกับคอมไพเลอร์เครื่องแรกรวมถึงการวิเคราะห์คำศัพท์ที่ต้องทำงานใน kWords ไม่กี่หน่วยความจำน้อยกว่าแคชข้อมูลโปรเซสเซอร์ระดับแรกบนอุปกรณ์มือถือปัจจุบัน ดังนั้นชื่อตัวแปรที่ได้รับอนุญาตจึงมี จำกัด มากและต้องแยกความแตกต่างจากค่าคงที่ตัวเลขในรหัส op น้อยมาก
ดังนั้นการประชุมจึงกลายเป็นสิ่งที่โปรแกรมเมอร์รุ่นต่อไปใช้
ไม่ใช่กฎที่จำเป็นในเชิงตรรกะสำหรับภาษาการเขียนโปรแกรม แต่เป็นเพียงหลักการที่ใช้โดยนักออกแบบภาษาจำนวนมาก
ฉันสามารถออกแบบภาษาที่แตกต่างอย่างสิ้นเชิงที่อนุญาตให้ตัวละครทั้งหมดสำหรับตัวระบุ สำหรับบรรทัดโค้ดทั้งหมดอักขระ 20 ตัวแรกจะอธิบายถึงชนิดข้อความสั่งและอักขระ 20 ตัวถัดไปจะกำหนดสัญลักษณ์แรกสำหรับข้อความสั่งนั้นและอักขระ 20 ตัวถัดไปจะถูกดำเนินการสำหรับคำสั่ง ภาษานี้จะถูกเรียกใช้งานบนตัวประมวลผลสแต็ก
01234567890123456789 01234567890123456789 01234567890123456789
decl symbol 12345
assign value 12345 12345
decl symbol 99999
assign value 99999 12345
push 12345
push 99999
add
print top
รหัสนี้สามารถแปลเป็น C ดังต่อไปนี้:
int i12345 = 12345;
int i99999 = 12345;
printf("%d", i12345+i9999);
นั่นคือทั้งหมดที่ มันไม่มีความหมายและกฎตัวระบุในหมายเลขก็ไม่มีประโยชน์ในด้านเหตุผล
นอกจาก "ความสะดวกสบายสำหรับผู้ใช้งานเล็ก" แล้วฉันคิดว่ามันก็คุ้มค่าที่จะพิจารณา "ความสะดวกสบายสำหรับผู้อ่าน"
เมื่ออ่านรหัสคุณจะต้องระบุอย่างรวดเร็วและซ้ำ ๆ ว่าคำใดเป็นตัวระบุและหมายเลขใด การมองหาตัวเลขที่จุดเริ่มต้นนั้นง่ายกว่าในการจับคู่รูปแบบภาพของเรา มันจะเป็นงานที่น่าเบื่อถ้าเราต้องตรวจสอบตัวละครทั้งหมดอย่างรอบคอบเพื่อให้แน่ใจ
คำตอบสำหรับคำถามนี้อยู่ในออโตมาตะหรือออโตมาต้า จำกัด ที่แม่นยำกว่าซึ่งกำหนดนิพจน์ทั่วไป กฎคือ ... คอมไพเลอร์ต้องการอัลกอริทึมหรือกฎที่แน่นอนในการตัดสินใจที่ตัวละครทุกตัวที่พวกเขาแยกวิเคราะห์ หากตัวบ่งชี้ได้รับอนุญาตให้เริ่มต้นด้วยตัวเลขแล้วคอมไพเลอร์จะอยู่ในการแก้ไข .. เกี่ยวกับลักษณะของโทเค็นมา ... มันจะเป็นตัวเลขหรือตัวระบุ ... และเป็นคอมไพเลอร์ลาดเท backtrack ไปยังตำแหน่งก่อนหน้า .. .so.. เพื่อให้ชัดเจนกับคอมไพเลอร์ว่าโทเค็นที่เข้ามานั้นเป็นตัวระบุหรือตัวเลข ... ข้อ จำกัด นี้มี ... coz ของ ... คอมไพเลอร์รู้เพียงแค่สแกนอักขระตัวแรกที่โทเค็นที่กำลังจะมาถึง เป็นตัวระบุหรือตัวเลข