Cirru 语法说明

最近状态不佳代码写不出来, 补一下 Cirru 的文档吧
前一篇 Cirru 的一年回顾好像有不少人看, 但整个项目似乎关注的人不多
我大概梳理一下, 如果有兴趣希望有人能帮我探索 Cirru http://cirru.org

Cirru 是基于 Lisp 的 S 表达式衍生出来的一套缩进语法
大致就是把括号语法当中跟缩进语义重合的部分给简化掉了
稍微明确一点的例子, (+ 1 2 (+ 3 4 (+ 5 6))) 到了 Cirru 里变成了

+ 1 2
  + 3 4
    + 5 6

或者上边的例子不用缩进, 实际上写出来是:

+ 1 2 (+ 3 4 (+ 5 6))

就像是每一行开头结尾的括号都不用了, 假装会被自动加上
但是为了考虑几个奇怪的写法, 实际上会有两个特殊语法

+ 1 2 $ + 3 4 $ + 5 6

其中 $ 意思就是后面的内容全部算在一个括号里, 括号管理起来麻烦嘛
然后还有这样的写法, 括号后面还有单个的值 (+ 1 (+ 2 3) 4 5), 写成这样

+ 1
  + 2 3
  , 4 5

其中的逗号 , 意思是这一行的内容是紧跟在原来的内容后面, 是不打括号的
关于缩进还有个极端的情况, (let ((a 1) (b 2)) (+ a b)) 写成

let
    a 1
    b 2
  + a b

也就是多层缩进会生成的多个括号, 用来表示 Lisp 特殊的意思
另外还有一个地方容易有误区, 就是使用引号, 跟一般的语言是不一样的

print |a
print "|a"
print "|a" "|b"
print "|a b"

Cirru 语法里第一行和第二行是一样的, 因为引号本身不是用来标记字符串的
引号只是用来对付像是第三行第四行这种想写的字段中有特殊字符的内容
其实 |a 在 JavaScript 中完全就是 "a", 前面的 | 只是特殊记号而已
在 CirruScript 当中是 :a 在 Sepal.clj 中是 |a, 你也可以定义别的符号

这确实是非常奇怪的语法, 造成这个情况的原因是, Cirru 原本是为图形化编辑设计的
我之前尝试过不少次想做个好用的图形化编辑器, 但效果不理想

后来觉得用文本的语法来做反而现实一点, 反而能在 GitHub 上先用起来
https://github.com/trending?l=Cirru
图形当中, 每个叶节点都是一快文本, 引号就没必要了, 只有文本需要引号
$, 的缩进和展开, 在图形上直接就是, 在文本里反而麻烦

所以 Cirru 本来想的是把 S 表达式用树状的图形界面做出来的
编程语言解析出来的树很像是分形的结构

明确一点可以参考 Let’s Build A Simple Interpreter 里的图片来理解



文本形态的 Cirru 语法怎么解析, 可以尝试这里 JavaScript 写的例子
http://repo.cirru.org/parser/

如果熟悉 AST 或者解释器, 会知道这是编程语言实现过程中很基础的玩具
事实上最近我也弄出了个微博专门整理关于这方面的资料
http://weibo.com/webassembly
有了 AST, 高级语言生成 AST, 底层代码又从 AST 生成, 所以很重要
这某种程度也算是 IR: Intermediate Representation(中间表示)
现在我已经用 CirruScript 和 Sepal.clj 来生成 JavaScript 和 Clojure 了
下一步希望用来生成 WebAssembly, 而且已经尝试了一下
势单力薄不知能走多远, 有兴趣的同学可以关注下, 也欢迎到微博私信我

补充一下免得误解, Cirru 对应的是语法树, AST 是指的抽象语法树
AST 会带更多信息, ES6 AST 比语法树复杂一点点, Clojure AST 非常复杂
Lisp 系语言有时说代码表示 AST, 但也许没把内部实现说明确, 说不准的
关于 AST 还可以看下这里 https://www.zhihu.com/question/20346372

阅读 2.3k

推荐阅读
题叶
用户专栏

ClojureScript 爱好者.

494 人关注
248 篇文章
专栏主页
目录