Clem เป็นภาษาการเขียนโปรแกรมแบบกองซ้อนที่มีฟังก์ชั่นชั้นหนึ่ง จุดประสงค์ของคุณคือการเขียนล่ามสำหรับภาษา Clem มันถูกต้องควรจะดำเนินการตัวอย่างทั้งหมดรวมอยู่ในการดำเนินการอ้างอิงที่มีอยู่ที่นี่
- ตามปกติจะใช้ช่องโหว่มาตรฐาน
- รายการที่น้อยที่สุดด้วยการนับไบต์ชนะ
ภาษาเคล็ม
Clem เป็นภาษาโปรแกรมสแต็กที่มีฟังก์ชั่นชั้นหนึ่ง วิธีที่ดีที่สุดในการเรียนรู้ Clem คือการใช้clem
ล่ามโดยไม่มีข้อโต้แย้ง มันจะเริ่มต้นในโหมดโต้ตอบช่วยให้คุณสามารถเล่นกับคำสั่งที่มีอยู่ ในการรันโปรแกรมตัวอย่างให้พิมพ์clem example.clm
โดยที่ example คือชื่อของโปรแกรม บทแนะนำสั้น ๆ นี้ควรจะเพียงพอสำหรับคุณในการเริ่มต้น
มีฟังก์ชั่นหลักสองประเภท ฟังก์ชั่นอะตอมมิกและฟังก์ชั่นสารประกอบ ฟังก์ชั่นผสมคือรายการที่ประกอบด้วยฟังก์ชั่นอื่น ๆ และฟังก์ชั่นอะตอมมิก โปรดทราบว่าฟังก์ชั่นผสมไม่สามารถมีตัวเอง
ฟังก์ชั่นของอะตอม
ชนิดแรกของฟังก์ชั่นของอะตอมเป็นคงที่ คงเป็นเพียงค่าจำนวนเต็ม ตัวอย่างเช่น -10 เมื่อล่ามพบค่าคงที่มันจะดันไปที่สแต็ก เรียกใช้clem
ตอนนี้ พิมพ์-10
ที่พรอมต์ คุณควรเห็น
> -10
001: (-10)
>
ค่า001
อธิบายถึงตำแหน่งของฟังก์ชันในสแต็กและ(-10)
เป็นค่าคงที่ที่คุณเพิ่งป้อน ตอนนี้ป้อน+11
ที่พรอมต์ คุณควรเห็น
> +11
002: (-10)
001: (11)
>
ขอให้สังเกตว่า(-10)
ได้ย้ายไปยังตำแหน่งที่สองในกองซ้อนและ(11)
ตอนนี้ครองตำแหน่งแรก นี่คือธรรมชาติของสแต็ก! คุณจะสังเกตเห็นว่า-
เป็นคำสั่งลดลง เมื่อใดก็ตาม-
หรือ+
นำหน้าหมายเลขพวกเขาจะแสดงสัญลักษณ์ของตัวเลขนั้นและไม่ใช่คำสั่งที่เกี่ยวข้อง ทุกฟังก์ชั่นของอะตอมอื่น ๆ ที่มีคำสั่ง มีทั้งหมด 14:
@ Rotate the top three functions on the stack
# Pop the function on top of the stack and push it twice
$ Swap the top two functions on top of the stack
% Pop the function on top of the stack and throw it away
/ Pop a compound function. Split off the first function, push what's left,
then push the first function.
. Pop two functions, concatenate them and push the result
+ Pop a function. If its a constant then increment it. Push it
- Pop a function. If its a constant then decrement it. Push it
< Get a character from STDIN and push it to the stack. Pushes -1 on EOF.
> Pop a function and print its ASCII character if its a constant
c Pop a function and print its value if its a constant
w Pop a function from the stack. Peek at the top of the stack. While it is
a non-zero constant, execute the function.
การพิมพ์คำสั่งที่พรอมต์จะดำเนินการตามคำสั่ง พิมพ์#
ที่พรอมต์ (คำสั่งซ้ำ) คุณควรเห็น
> #
003: (-10)
002: (11)
001: (11)
>
ขอให้สังเกตว่า (11) ถูกทำซ้ำ ตอนนี้ให้พิมพ์%
ที่พรอมต์ (คำสั่งปล่อย) คุณควรเห็น
> %
002: (-10)
001: (11)
>
ในการส่งคำสั่งไปยังสแต็กเพียงแค่ล้อมรอบมันในวงเล็บ พิมพ์(-)
ที่พรอมต์ สิ่งนี้จะดันโอเปอเรเตอร์การลดลงไปยังสแต็ก คุณควรเห็น
> (-)
003: (-10)
002: (11)
001: (-)
>
ฟังก์ชั่นแบบผสม
คุณอาจใส่หลายฟังก์ชั่นของอะตอมมิกไว้ในวงเล็บเพื่อสร้างฟังก์ชั่นผสม เมื่อคุณเข้าสู่ฟังก์ชั่นรวมที่พรอมต์มันจะถูกผลักไปที่กองซ้อน พิมพ์($+$)
ที่พรอมต์ คุณควรเห็น
> ($+$)
004: (-10)
003: (11)
002: (-)
001: ($ + $)
>
ในทางเทคนิคทุกอย่างในสแต็กเป็นฟังก์ชั่นแบบผสม อย่างไรก็ตามฟังก์ชั่นสารประกอบบางอย่างในสแต็กประกอบด้วยฟังก์ชั่นอะตอมมิกเดียว (ในกรณีนี้เราจะพิจารณาว่าเป็นฟังก์ชั่นอะตอมมิกเพื่อความสะดวก) เมื่อจัดการกับฟังก์ชั่นผสมบนสแต็ค.
คำสั่ง (การต่อข้อมูล) จะมีประโยชน์บ่อยครั้ง พิมพ์.
ทันที คุณควรเห็น
> .
003: (-10)
002: (11)
001: (- $ + $)
>
ขอให้สังเกตว่าฟังก์ชั่นที่หนึ่งและที่สองในสแต็กถูกต่อกันและฟังก์ชั่นที่สองในสแต็คมาก่อนในรายการผลลัพธ์ ในการดำเนินการฟังก์ชั่นที่อยู่ในสแต็ก (ไม่ว่าจะเป็นอะตอมหรือสารประกอบ) เราจะต้องออกw
คำสั่ง (ในขณะที่) w
คำสั่งจะปรากฏฟังก์ชั่นครั้งแรกในกองและดำเนินการซ้ำ ๆ ตราบใดที่ฟังก์ชั่นที่สองในสแต็คเป็นที่ไม่ใช่ศูนย์อย่างต่อเนื่อง w
พยายามที่จะคาดการณ์สิ่งที่จะเกิดขึ้นถ้าเราพิมพ์ w
ตอนนี้พิมพ์ คุณควรเห็น
> w
002: (1)
001: (0)
>
นั่นคือสิ่งที่คุณคาดหวัง มีการเพิ่มตัวเลขสองตัวที่อยู่ด้านบนสุดของสแต็กและผลรวมจะยังคงอยู่ ลองอีกครั้ง ครั้งแรกที่เราจะลดลงเป็นศูนย์และผลักดัน 10 %10
โดยการพิมพ์ คุณควรเห็น
> %10
002: (1)
001: (10)
>
ตอนนี้เราจะพิมพ์ฟังก์ชั่นทั้งหมดในนัดเดียว แต่เราจะเพิ่มส่วนพิเศษ%
ตอนท้ายเพื่อกำจัดศูนย์ พิมพ์(-$+$)w%
ที่พรอมต์ คุณควรเห็น
> (-$+$)w%
001: (11)
>
(โปรดทราบว่าอัลกอริทึมนี้ใช้งานได้หากค่าคงที่แรกบนสแต็กเป็นค่าบวก)
เงื่อนไข
ปัจจุบันมีเงื่อนไข พวกเขาส่วนใหญ่น้ำตาล syntactic แต่จะมีประโยชน์มาก เมื่อล่ามพบสตริงสตริงนั้นจะผลักอักขระแต่ละตัวจากสุดท้ายไปยังอันดับแรกลงบนสแต็ก พิมพ์%
เพื่อปล่อย 11 จากตัวอย่างก่อนหน้า ตอนนี้พิมพ์0 10 "Hi!"
พรอมต์ 0
จะแทรกเทอร์มิโมฆะและ10
จะแทรกตัวละครใหม่เส้น คุณควรเห็น
> 0 10 "Hi!"
005: (0)
004: (10)
003: (33)
002: (105)
001: (72)
>
พิมพ์(>)w
เพื่อพิมพ์อักขระจากสแต็กจนกว่าเราจะพบกับ NULL terminator คุณควรเห็น
> (>)w
Hi!
001: (0)
>
สรุปผลการวิจัย
หวังว่ามันจะเพียงพอที่จะให้คุณเริ่มต้นกับล่าม การออกแบบภาษาควรตรงไปตรงมา แจ้งให้เราทราบหากมีสิ่งใดที่ไม่ชัดเจนอย่างยิ่ง :) มีบางสิ่งที่ถูกทิ้งไว้โดยเจตนาที่คลุมเครือ: ค่าต้องลงนามและอย่างน้อย 16 บิตสแต็กจะต้องมีขนาดใหญ่พอที่จะเรียกใช้โปรแกรมอ้างอิงทั้งหมดเป็นต้น ออกมาที่นี่เพราะสเปคภาษาเป่าเต็มรูปแบบจะมีขนาดใหญ่โพสต์ห้าม (และฉันยังไม่ได้เขียนหนึ่ง: P) เมื่อมีข้อสงสัยเลียนแบบการดำเนินการอ้างอิง