大家好,我是程序员朝歌。
我发现我现在好像在空无一人的赛道里狂奔,自制编程语言的人,有,自制操作系统的人,也有,但是用自制编程语言写自制操作系统的,感觉好像是真没有,至少从各个平台上看,我发现除了我,没有人在搞用自制编程语言写自制操作系统的,我不知道为什么,可能这件事又难体力活又重吧。
本期讲的东西比较简单也比较有意思,不涉及技术,小白也能懂,本期的主题是如何设计一门编程语言,我在这里讲一下我的整个设计编程语言语法的过程。
第一步,就是写出自己编程语言最基础的设定,然后其他的东西再慢慢补完,例如,我想出来的第一个语法是关于变量声明的,这里就是我对于变量声明的设定:
声明一个常量:
a : 0
声明一个变量,感叹号是变量名的一部分,表明这是一个变量,意味着比较危险,需要注意:
b! : 1
定义一个可变类型的变量(变量的类型也能变,例如本是数字类型的变成了字符串类型的),问号表明这是一个可变类型的变量,意味着非常危险:
c? : 2
这样你看,变量声明就设计好了,很简单对不对,对于编程语法,基本上你想怎么设计就怎么设计,前提是你要用LR文法,不能用LL文法,用LL文法你就会很受限,就没办法像这样随心所欲地设计了。
我的第二个创意是将变量声明和函数声明统一,怎么统一呢,举个例子,先来看一个变量声明:
d : 1
e : (d+1)
d和e都是常量,声明完毕后,d的值是1,e的值是2,这个很好理解,但这里也说明一个事实,就是变量声明的右侧表达式会在声明时立即执行,这里e在声明时,会立即运行d+1,返回2,所以e是2,但是这里可不可以,在声明的时候,这个表达式不立即执行呢?所以我又发明了一个语法:
f() : (d+1)
我设定在常量名后面加一个括号,表示后面的表达式不是立即执行的,f()表示这个表达式本身,而不是这个表达式执行完毕之后返回的值,那么这个表达式什么时候执行呢?我设定调用f()的时候执行:
d : 1
f() : (d+1)
print(f())
此时,就会打印2,所以,f()就可以当作一个函数来看待,既然可以当作一个函数来看待,那么也就可以传参了:
f(a:0, b:0) : (a+b)
print(f(1, 2))
那么此时应该打印出3,这里a和b就是f的参数,还有默认值是0,所以很完美,但这就又有了一个问题,一个函数内不可能只有一个表达式,如果有很多表达式怎么办?
我设定用换行分隔或用逗号分隔,并且将最后一个执行的表达式的结果返回作为函数f的返回值:
f(a:0, b:0) : (c: a+b, d: a-b, c+d)
f(a:0, b:0) : (
c: a+b
d: a-b
c+d
)
print(f(1, 2))
这两个函数f是一样的,最后打印的结果都是2,这里简单口算一下就能算出来,那么这里又回有一个问题,如果我想提前结束这个函数怎么办?然后
我引入了return(),调用它就能提前结束函数:
f(a:0, b: 0) : (
c: a+b
d: a-b
return(c+d)
c-d
)
print(f(1, 2))
此时打印2,c-d就不执行不返回了,这里就可以看出我设计的函数与其他编程语言的函数有一个很大不同,它会将最后一个表达式执行的结果自动返回,其他编程语言一般是不用return就啥也不返回。因此,这里我又在想,三元表达式,是否能和if语句合并呢?于是,我就设计了这样的逻辑判断语句:
if(a, b, c)
什么意思呢,就是if是一个函数,如果a的值为true,那么返回b,否则返回c,很简洁,很直观,同时把逻辑判断语句用函数表示,也有利于降低学习成本和使用心智。
既然逻辑语句已经设计好了,那么循环语句是不是也是类似呢?于是我设计循环语句如下:
while(a, b)
其中,先执行一次表达式a,如果其值为true,那么就执行一次表达式b,然后再循环,直到表达式a的值是false,那么while就返回最后一次表达式b执行后的结果,那么这样就可以当作循环语句了。
所以,总结一下,设计编程语言有一个特点,就是你最开始设计了一个最基础的设定后,后面的语法设计就基本上固定了,顺势而为自然而然地就都设计出来了,如果你在中途强行改设定,就会感觉很违和,有一种格格不入的感觉。
最后呢,我极力推荐用lr 文法设计编程语言,虽然难,但是很强大,如果说图简单用了ll 文法,那可真的是要吃后悔药的,ll 文法的表达能力弱,设计语法的时候会让你很抓狂,尤其是这个编程语言后续还要支持自制操作系统,自制图形库什么的,一步错 步步错,后面就会越做越不想做,相信我,我趟过这个坑。
最后的最后,感谢大家的关注和支持,我们下期再见!