Whitespace
Whitespace是一种深奥的编程语言。它由Edwin Brady和Chris Morris开发,于2003年4月1日发布。大部分的现代程式设计语言都不将空白字符视为语法的一部分。但Whitespace却只视空格(space)、制表符(tab)和换行(line feed)为语法元素,它的解释器会忽略其他所有字符。在没有特殊标记下,一段没有注释的Whitespace代码应该是完全不可见的[1]。
Whitespace是种基于堆栈的指令式编程语言。运行其程序的虚拟机具有一个堆栈(stack)和堆积(heap)作为数据结构。用户可自由将整数推进堆栈中(Whitespace目前并不支持浮点数或其他类型),亦可将堆积作为变量的暂存区。
这种语言有和Brainfuck一样的优点,能方便地撰写程序注释,写的注释只要不包含三种语法字符,解释器就会直接跳过。还有,借助这种语言,可以在满篇空白的代码中插入一篇文章,从而在看起来完全无关的文章中隐藏一段代码。对于一些需要保证安全性的工作来说,这种语言帮助很大,因为它可以防止别人把代码打印出来拿走。
语法
撰写Whitespace程序时,用户透过三种语法字符的排列去表达指令,进而操作虚拟机中的堆栈与堆积。这些指令皆分为三个部分:IMP、指令和参数。IMP决定接下来要使用的指令是哪一种类型,指令决定执行的具体工作,而部分指令需要额外的参数[1]。
IMP
IMP(Instruction Modification Parameter)是Whitespace语法中的一种特色,在每个指令前要先指定IMP,接着再选择IMP中的个别指令。
IMP | 意义 |
---|---|
[Space] | 堆栈操作 |
[Tab][Space] | 数学运算 |
[Tab][Tab] | 堆积存取 |
[LF] | 流程控制 |
[Tab][LF] | I/O |
数字
在Whitespace中,许多指令都需要在最后加上一个整数作为参数。整数由一串不限长度的字符表示,格式为:
- 第一个字符表示数字的正负,空白为“正”而制表符为“负”。
- 之后的字符以二进制表示数字,空白代表数码上的“0”,制表符则代表“1”。
- 数字结束时,须以换行标示。
堆栈操作
堆栈操作指令的IMP是[Space],因为是一种常用的指令,所以有最简短的IMP。 这里有四种操作方式。
指令 | 参数 | 意义 |
---|---|---|
[Space] | 数字 | 将某个数字放入堆栈 |
[Tab][Space] | 数字 | 将堆栈里的第n个元素复制到堆栈顶 |
[Tab][LF] | 数字 | 将堆栈里的第n个元素从堆栈里移除 |
[LF][Space] | - | 复制堆栈最上方的元素 |
[LF][Tab] | - | 交换两个堆栈最上层的元素 |
[LF][LF] | - | 屏弃堆栈最上层的元素 |
算术
算术指令的IMP是[Tab][Space],会取堆栈最上方的两个元素做运算,并以运算结果取代原本的元素。 先进入堆栈的元素将被视为运算符左方的操作数。
指令 | 参数 | 意义 |
---|---|---|
[Space][Space] | - | 加 |
[Space][Tab] | - | 减 |
[Space][LF] | - | 乘 |
[Tab][Space] | - | 整数除法 |
[Tab][Tab] | - | 模运算(取余数) |
堆积操作
堆积操作指令的IMP是[Tab][Tab],可以将物件存入堆栈中的特定地址,也可以获取堆栈中的特定地址的物件。 要存储一个物件至堆积里,先将地址放入堆栈,而后放入物件的值再执行存储指令。 要取出堆积里的一个物件,将地址放入堆栈而后执行取回指令,取回的值会被存放在堆栈的最上方。
指令 | 参数 | 意义 |
---|---|---|
[Space] | - | 存储 |
[Tab] | - | 取回 |
控制流程
控制流程指令的IMP是[LF]。子程序可以用标签(label)作标记,进行有条件或无条件的跳转,可用于实现条件判断或循环等复杂构造。标签是一个整数,由指令的参数栏输入,所有标签必须是独一无二的,不能重复。
这一类指令也包含了“结束”。所有程序都必须借由[LF][LF][LF]这条指令才能让解释器正确地退出程序。
指令 | 参数 | 意义 |
---|---|---|
[Space][Space] | 标签 | 标记程序中某一个流程 |
[Space][Tab] | 标签 | 标签调用子程序 |
[Space][LF] | 标签 | 从某标签无条件跳跃至另一标签 |
[Tab][Space] | 标签 | 如果堆栈顶为0则跳跃至某标签 |
[Tab][Tab] | 标签 | 如果堆栈顶为负数则跳跃至某标签 |
[Tab][LF] | - | 结束目前子程序并跳跃回调叫者 |
[LF][LF] | - | 退出程序 |
输入与输出
输入与输出指令的IMP是[Tab][LF],可以进行资料流的输入输出。
输入指令会取用堆栈最上方的数字作为地址,将输入的物件存入堆积。输出指令可输出堆栈最上端的数字,或输出堆栈最上端的数字所对应的ASCII字符
指令 | 参数 | 意义 |
---|---|---|
[Space][Space] | - | 输出堆栈最上方的字符 |
[Space][Tab] | - | 输出堆栈最上方的数字 |
[Tab][Space] | - | 读入一字符并写入堆栈顶的地址里 |
[Tab][Tab] | - | 读入一数字并写入堆栈顶的地址里 |
示例
这是一个能输出“Hello, world!”的简单示例程序,每个空白、制表符和换行字符被分别以“S”、“T”和“L”表示:
S S S T S S T S S S L T L S S S S S T T S S T S T L T L S S S S S T T S T T S S L T L S S S S S T T S T T S S L T L S S S S S T T S T T T T L T L S S S S S T S T T S S L T L S S S S S T S S S S S L T L S S S S S T T T S T T T L T L S S S S S T T S T T T T L T L S S S S S T T T S S T S L T L S S S S S T T S T T S S L T L S S S S S T T S S T S S L T L S S S S S T S S S S T L T L S S L L L
外部链接
参考资料
- ^ 1.0 1.1 Whitespace. Esolang. [2023-11-27]. (原始内容存档于2023-09-21) (英语).