caolang
v0.1.0
Published
草语言 — A meme-based Chinese programming language
Maintainers
Readme
草语言 (CaoLang) 🌿
一个基于梗的中文编程语言。写代码?不,我们叫它「整活」。
草语言是一门用中文互联网黑话作为关键字的编程语言。变量声明叫搞个,函数定义叫整活,返回值叫栓Q,循环叫卷,跳出循环叫润。
如果你觉得 JavaScript 的 undefined is not a function 不够有灵魂,试试草语言的 这谁啊,不认识。
整活 斐波那契(n)「
如果(n <= 1)「
栓Q n
」
栓Q 斐波那契(n - 1) + 斐波那契(n - 2)
」
搞个 i = 0
卷(i < 10)「
喊话(斐波那契(i))
i = i + 1
」安装 Installation
# 用 npm 安装
npm install -g caolang
# 或者直接 npx 一把梭
npx caolang run hello.cao从源码运行 Run from Source
git clone <repo-url>
cd caolang
npm install
npm run dev -- run examples/hello.cao用法 Usage
cao run <文件.cao> # 运行一个 .cao 文件
cao # 启动交互式控制台(REPL)
cao repl # 同上
cao tokenize <文件.cao> # 查看词法分析结果(给卷王看的)
cao parse <文件.cao> # 查看语法树(给更卷的卷王看的)
cao --help # 显示帮助
cao --version # 显示版本REPL 长这样:
草语言 (CaoLang) v0.1.0 — 交互式控制台
输入代码开始整活,输入 .exit 退出
草> 喊话("你好世界")
你好世界
草> 1 + 1
2
草> 搞个 x = 42
草> x * 2
84语言教程 Language Guide
变量:搞个
搞个 名字 = "张三"
搞个 年龄 = 25
搞个 是学生 = 确实
搞个 钱包 = 虚无 // 没钱,虚无函数:整活
整活 加法(a,b)「
栓Q a + b
」
喊话(加法(3,4)) // 输出: 7栓Q 就是 return。为什么叫栓Q?因为感谢这个函数给了我一个返回值,栓Q🙏
条件:如果 / 啊这
如果(年龄 >= 18)「
喊话("成年了,可以整活了")
」啊这「
喊话("啊这,还没成年")
」支持 else if 链:
如果(分数 >= 90)「
喊话("优秀")
」啊这 如果(分数 >= 60)「
喊话("及格")
」啊这「
喊话("寄")
」循环:卷
搞个 i = 0
卷(i < 10)「
喊话(i)
i = i + 1
」卷不动了?用 润 跳出循环。想跳过这次继续卷?用 继续卷。
搞个 i = 0
卷(确实)「
如果(i == 5)「润」 // 润了,不卷了
如果(i == 3)「
i = i + 1
继续卷 // 跳过这次,继续卷
」
喊话(i)
i = i + 1
」布尔值:确实 / 没有内味
搞个 真的 = 确实 // true
搞个 假的 = 没有内味 // false(对,就是这么长,惩罚你写烂逻辑)逻辑运算:
确实 并且 确实 // 确实
确实 或者 没有内味 // 确实
非 确实 // 没有内味为什么
没有内味这么长? 这是 feature 不是 bug。写太多布尔判断说明你代码有问题,长一点让你反思一下。
错误处理:真香 / 草
真香「
寄("出大事了兄弟!")
」草(那个错误)「
喊话("草!" + 那个错误)
」不想处理错误?纯摆烂模式——catch 不接参数:
真香「
寄("这个错误没人管")
」草「
摆烂 // 错误?什么错误?我不知道
」数组
搞个 水果 = ["苹果","香蕉","橘子"]
喊话(水果[0]) // 苹果
推入(水果,"西瓜") // push
搞个 最后 = 弹出(水果) // pop
喊话(长度(水果)) // 3闭包
整活 制造计数器()「
搞个 计数 = 0
整活 增加()「
计数 = 计数 + 1
栓Q 计数
」
栓Q 增加
」
搞个 计数器 = 制造计数器()
喊话(计数器()) // 1
喊话(计数器()) // 2
喊话(计数器()) // 3摆烂
有时候你就是不想写逻辑。摆烂 是草语言的 no-op / pass:
如果(今天是周一)「
摆烂 // 周一不想干活
」标点符号 Punctuation
草语言支持中文标点和 ASCII 标点,可以混用:
| 中文 | ASCII | 用途 |
|------|-------|------|
| 「」 或 『』 | {} | 代码块 |
| () | () | 分组 / 函数调用 |
| , | , | 分隔符 |
| ; | ; | 语句终止符(可选) |
分号完全可选。草语言不需要分号,因为生活已经够累了。
内置函数 Built-ins
| 函数 | 用途 | 示例 |
|------|------|------|
| 喊话(...) | 打印输出 | 喊话("你好") |
| 类型(值) | 返回类型名 | 类型(42) → "数字" |
| 长度(值) | 字符串/数组长度 | 长度("你好") → 2 |
| 数字化(字符串) | 字符串转数字 | 数字化("42") → 42 |
| 字符串化(值) | 任意值转字符串 | 字符串化(42) → "42" |
| 推入(数组,值) | 数组末尾添加 | 推入(arr,1) |
| 弹出(数组) | 数组末尾弹出 | 弹出(arr) |
| 切片(值,开始,结束) | 切片 | 切片("你好世界",0,2) → "你好" |
| 随机() | 随机数 [0, 1) | 随机() |
| 时间戳() | 当前毫秒时间戳 | 时间戳() |
梗味错误信息 Meme Error Messages
草语言的报错不说人话(但说的都是实话):
| 场景 | 报错 |
|------|------|
| 语法错误 | 啊?这写的什么玩意儿 |
| 变量未定义 | 这谁啊,不认识: xxx |
| 类型错误 | 类型不对啊兄弟,别乱搞 |
| 除以零 | 除以零?脑子瓦特了? |
| 栈溢出 | 卷太狠了,栈都溢出了 |
| 参数数量错误 | 参数数量不对,搞什么飞机 |
| 数组越界 | 越界了兄弟,别越线 |
| 字符串没闭合 | 字符串没写完就跑了,引号呢? |
🥚 彩蛋 Easter Eggs
社会信用系统 Social Credit System
cao run your-file.cao --social-credit如果一个函数里 栓Q(return)超过 5 次,编译器会警告你「太客气了」:
⚠️ 社会信用警告:函数「太客气了」里栓Q了8次,你也太客气了吧!996 模式
cao run your-file.cao --996如果你在晚上 9 点到早上 6 点之间跑代码,卷(while)循环每次迭代有 1% 概率猝死:
💀 猝死!你卷到猝死了!回去睡觉!
(996模式:深夜写代码有1%概率猝死)严厉模式 Strict Mode
在文件开头写 严厉,或者用 --strict 标志:
严厉
喊话("你好") // 用了ASCII括号,会被教育🔴 文化自信!请使用中文标点!
第3行:发现 '(',请使用()!
第3行:发现 ')',请使用()!全部彩蛋
cao run your-file.cao --全部彩蛋关键字速查表 Keyword Cheat Sheet
搞个 → let / var (搞一个变量)
整活 → function (开始整活)
栓Q → return (栓Q,谢谢)
喊话 → print (大声喊话)
如果 → if (如果的话...)
啊这 → else (啊这...)
卷 → while (开始卷)
润 → break (润了)
继续卷 → continue (继续卷!)
摆烂 → pass / no-op (摆烂了)
寄 → throw (寄了)
真香 → try (真香定律)
草 → catch (草!)
确实 → true (确实)
没有内味 → false (没有内味了)
虚无 → null (虚无)
并且 → and (并且)
或者 → or (或者)
非 → not (非)示例程序 Examples
examples/ 目录下有这些示例:
- hello.cao — 你好世界
- fibonacci.cao — 斐波那契数列(递归)
- fizzbuzz.cao — 经典 FizzBuzz(草Buzz)
- closures.cao — 闭包和计数器
- error-handling.cao — 真香/草 错误处理
- meme-showcase.cao — 完整特性展示
- social-credit.cao — 社会信用系统彩蛋演示
运行示例:
npm run dev -- run examples/meme-showcase.cao技术细节 Technical Details
- 实现语言: TypeScript
- 执行模型: Tree-walking 解释器
- 解析器: Pratt parser(自顶向下运算符优先级)
- 作用域: 词法作用域,支持闭包
- 类型系统: 动态类型(数字、字符串、布尔、虚无、数组、函数)
- 运行时依赖: 零(纯 TypeScript,无第三方依赖)
- Unicode: 正确处理 CJK 字符,支持中文标识符
- 标点: 中文标点在词法分析阶段归一化,解析器只看规范形式
空格无关的关键字识别
草语言使用贪心前缀匹配来识别关键字。你可以写 搞个东西 而不需要空格——词法分析器会自动拆分成 搞个(关键字) + 东西(标识符)。因为中文本来就不用空格。
开发 Development
npm install # 安装依赖
npm test # 跑测试(97个)
npm run dev # 用 tsx 直接跑
npm run build # 编译到 dist/
npm run lint # 类型检查License
MIT
