介绍一个很干净的语言。





















Hello World

先看它的 Hello World 。































没看错。这个 Whitespace 语言的原语只有空格,制表符,还有换行。

语法

参考 Whitespace 语言官方教程 整理的 BNF 如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
Program ::= <Statement>{Statement}

Statement ::= <IMP>

IMP :: = <StackManipulation><SMCommand> | <Arithmetic><AriCommand> | <HeapAccess><HACommand> | <FlowControl><FCCommand> | <I/O><IOCommand>

StackManipulation ::= <Space>

SMCommand ::= <Push><Number> | <Duplicate> | <Swap> | <Discard>

Push ::= <Space>

Number ::= <Sign><Digit><End>

Sign ::= <Space> | <Tab>

Digit ::= <Space>{Digit}|<Tab>{Digit}

End ::= <LF>

Duplicate ::= <LF><Space>

Swap ::= <LF><Tab>

Discard ::= <LF><LF>

Duplicate ::= <LF><Space>

Arithmetic ::= <Tab><Space>

AriCommand ::= <Addition> | <Subtraction> | <Multiplication> | <IntegerDivision> | <Modulo>

Addition ::= <Space><Space>

Subtraction ::= <Space><Tab>

Multiplication ::= <Space><LF>

IntegerDivision ::= <Tab><Space>

Modulo ::= <Tab><Tab>

HeapAccess ::= <Tab><Tab>

HACommand ::= <Store><Retrieve>

Store ::= <Space>

Retrieve ::= <Tab>

FlowControl ::= <LF>

FCCommand ::= <Mark><Label> | <Call><Label> | <Jmp><Label> | <Jz><Label> | <Js><Label> | <SubroutineEnd> | <ProgramEnd>

Mark ::= <Space><Space>

Label ::= <LabelName><End>

LabelName ::= <Space>{LabelName}|<Tab>{LabelName}

Call ::= <Space><Tab>

Jmp ::= <Space><LF>

Jz ::= <Tab><Space>

Js ::= <Tab><Tab>

SubroutineEnd ::= <Tab><LF>

ProgrameEnd ::= <LF><LF>

I/O ::= <Tab><LF>

IOCommand ::= <OutputChar> | <OutputNumber> | <ReadChar> | <ReadNumber>

OutputChar ::= <Space><Space>

OutputNumber ::= <Space><Tab>

ReadChar ::= <Tab><Space>

ReadNumber ::= <Tab><Tab>

Space ::= " "

Tab ::= "\t"

LF ::= "\n"

不熟悉 BNF 可以直接看下面的图表。

IMP Command Meaning IMP Meaning
[Space] [Space][Number] Push the number onto the stack Stack Manipulation
[Space] [LF][Space] Duplicate the top item on the stack Stack Manipulation
[Space] [LF][Tab] Swap the top two items on the stack Stack Manipulation
[Space] [LF][LF] Discard the top item on the stack Stack Manipulation
[Tab][Space] [Space][Space] Addition Arithmetic
[Tab][Space] [Space][Tab] Subtraction Arithmetic
[Tab][Space] [Space][LF] Multiplication Arithmetic
[Tab][Space] [Tab][Space] Integer Division Arithmetic
[Tab][Space] [Tab][Tab] Modulo Arithmetic
[Tab][Tab] [Space] Store Heap access
[Tab][Tab] [Tab] Retrieve Heap access
[LF] [Space][Space] Mark a location in the program Flow Control
[LF] [Space][Tab] Call a subroutine Flow Control
[LF] [Space][LF] Jump unconditionally to a label Flow Control
[LF] [Tab][Space] Jump to a label if the top of the stack is zero Flow Control
[LF] [Tab][Tab] Jump to a label if the top of the stack is negative Flow Control
[LF] [Tab][LF] End a subroutineand transfer control back to the caller Flow Control
[LF] [LF][LF] End the program Flow Control
[Tab][LF] [Space][Space] Output the character at the top of the stack I/O
[Tab][LF] [Space][Tab] Output the number at the top of the stack I/O
[Tab][LF] [Tab][Space] Read a character and place it in the location given by the top of the stack I/O
[Tab][LF] [Tab][Tab] Read a number and place it in the location given by the top of the stack I/O

所以这是一个将特定序列的空白符转成指令的语言。

比如

1
[Tab][LF][Space][Space]

表示将栈顶数字以 ASCII 的形式输出。

解析 Hello World

空白符看起来比较不方便,将 Hello World 代码中空格替换为 [Space] ,制表符替换为 [Tab] ,换行替换为 [LF] 。

整理后如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[Space][Space][Space][Tab][Space][Space][Tab][Space][Space][Space][LF]
数字压栈 0100 1000 也就是数字 72 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 72 也就是 H

[Space][Space][Space][Tab][Tab][Space][Space][Tab][Space][Tab][LF]
数字压栈 00 0110 0101 也就是数字 101 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 101 也就是 e

[Space][Space][Space][Tab][Tab][Space][Tab][Tab][Space][Space][LF]
数字压栈 00 0110 1100 也就是数字 108 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 108 也就是 l

[Space][Space][Space][Tab][Tab][Space][Tab][Tab][Space][Space][LF]
数字压栈 00 0110 1100 也就是数字 108 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 108 也就是 l

[Space][Space][Space][Tab][Tab][Space][Tab][Tab][Tab][Tab][LF]
数字压栈 00 0110 1111 也就是数字 111 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 111 也就是 o

[Space][Space][Space][Tab][Space][Tab][Tab][Space][Space][LF]
数字压栈 0 0010 1100 也就是数字 44 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 44 也就是 ,

[Space][Space][Space][Tab][Space][Space][Space][Space][Space][LF]
数字压栈 0 0010 0000 也就是数字 32 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 32 也就是 空格

[Space][Space][Space][Tab][Tab][Tab][Space][Tab][Tab][Tab][LF]
数字压栈 00 0111 0111 也就是数字 119 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 119 也就是 w

[Space][Space][Space][Tab][Tab][Space][Tab][Tab][Tab][Tab][LF]
数字压栈 00 0110 1111 也就是数字 111 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 111 也就是 o

[Space][Space][Space][Tab][Tab][Tab][Space][Space][Tab][Space][LF]
数字压栈 00 0111 0010 也就是数字 114 输出字符 r
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 114 也就是 r

[Space][Space][Space][Tab][Tab][Space][Tab][Tab][Space][Space][LF]
数字压栈 00 0110 1100 也就是数字 108 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 108 也就是 l

[Space][Space][Space][Tab][Tab][Space][Space][Tab][Space][Space][LF]
数字压栈 00 0110 0100 也就是数字 100 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 100 也就是 d

[Space][Space][Space][Tab][Space][Space][Space][Space][Tab][LF]
数字压栈 0 0010 0001 也就是数字 33 压栈
[Tab][LF][Space][Space]
输出栈顶字符 ASCII 33 也就是 !

[LF][LF][LF]
程序结束符号

这个 Hello World 代码很简单,只是简单的入栈出栈,没有用到跳转等复杂的功能。

最后

这个语言最大的作用是……