ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

文言编程语言(wenyan-lang)入门与实战指南:语法、CLI 编译与古书 SVG 渲染

2026/9/20 8:52:54 拓冰建站 浏览量
文言编程语言(wenyan-lang)入门与实战指南:语法、CLI 编译与古书 SVG 渲染 文言编程语言wenyan-lang入门与实战指南语法、CLI 编译与古书 SVG 渲染【免费下载链接】wenyan文言文編程語言 A programming language for the ancient Chinese.项目地址: https://gitcode.com/gh_mirrors/we/wenyanwenyan-lang文言是一门以古汉语语法为蓝本的自然语言编程语言编译器可把文言代码转译为 JavaScript、Python 与 Ruby。本文以仓库 README.zh-Hans.md 为骨架结合 src/cli.ts、src/parser.ts、src/render.ts 等源码系统讲解语言语法、命令行工具、导入机制与古书样式渲染器读完即可动手编写、编译并渲染属于自己的文言程序。项目概览用文言写代码是什么体验wenyan-lang 试图让程序语言回归文言这一延续数千年的书写传统。项目序言中作者自述其志然以文言編程者似所未有。此誠非文脈之所以傳文心之所以保意在补文言编程之空白让代码亦可文氣淋灕。从工程角度看它有如下核心特征引自 README.zh-Hans.md符合古汉语语法的自然语言处理程序代码读起来像一篇短文而非符号堆砌多目标编译可编译为 JavaScript、Python 或 Ruby三个转译器统一注册在 src/transpilers/index.ts图灵完备仓库内置了用文言编写的通用图灵机程序 examples/turing.wy 作为佐证在线 IDE仓库 site/ide.html 与 static/index.html 提供了浏览器内即时编辑体验丰富的示例埃拉托斯特尼筛法、快速排序、曼德博集合、汉诺塔等算法均有文言实现集中存放于 examples/ 目录。快速上手Hello World 与标点无关特性仓库中的 examples/helloworld.wy 内容如下吾有一言。曰「「問天地好在。」」。書之。README 中给出了更完整的循环版本示例。文言代码吾有一數。曰三。名之曰「甲」。 為是「甲」遍。 吾有一言。曰「「問天地好在。」」。書之。 云云。它等价于以下 JavaScriptvar n 3; for (var i 0; i n; i) { console.log(問天地好在。); }运行输出問天地好在。 問天地好在。 問天地好在。标点与换行完全可选正如古汉语中文字连绵不断wenyan 的标点符号与换行都是可选的上面的代码与下面这一行完全等价吾有一數曰三名之曰「甲」為是「甲」遍吾有一言曰「「問天地好在」」書之云云这一设计在词法分析层面得到了体现src/parser.ts 的wy2tokens将。、\n\r\t视为可忽略符号IGNORE_SYMBOLS真正的语法单位由「」引号、数字关键字与文言关键字边界决定而非依赖标点。想继续深入examples/ 目录提供了 40 余个可直接运行的程序涵盖排序quicksort.wy、mergesort.wy、selectionsort.wy、数论euclidean.wy、modinv.wy、crt.wy、图形学mandelbrot.wy、draw_heart.wy以及经典算法hanoi.wy、eightqueens.wy、turing.wy等。安装与环境准备安装命令行编译器通过 npm 全局安装编译器npm install -g wenyan/cli安装后即可直接运行仓库内置示例例如wenyan examples/helloworld.wy -o helloworld.js该命令读取文言源文件、编译为 JavaScript 并写入helloworld.js详见下文 CLI 章节。若直接执行wenyan examples/helloworld.wy而不带参数则会编译并在终端中直接运行输出問天地好在。。在线 IDE不想安装任何东西时可使用仓库内的浏览器版 IDE 页面 site/ide.html生产构建对应 static/index.html左侧编写文言代码、右侧即时查看编译结果与输出编辑器插件社区为常用编辑器提供了语法支持由 antfu 提供的适用于 VSCode 的插件由 voldikss 提供的适用于 Vim 的插件由 absop 提供的适用于 Sublime Text 的插件。wenyan 命令行工具全参数详解README 建议用wenyan -h获取帮助。结合 src/cli.ts 中commander的定义当前 CLI 支持如下完整参数参数含义默认值 / 说明-v, --version输出版本号读取自 src/version.ts-l, --lang lang目标语言js可选js、py、rb-c, --compile只输出编译后代码不执行需配合-o指定输出文件-e, --eval code直接求值一段文言代码追加在源文件内容之后一并编译-i, --interactive进入交互式 REPL仅支持目标语言js-o, --output [file]输出到文件未给路径时会自动推导见下-r, --render输出古书样式 SVG 渲染见渲染器章节--roman [method]标识符罗马化可选pinyin、baxter、unicode--roman裸用等价于--roman pinyin--strict开启静态类型检查默认关闭--allowHttp允许通过 HTTP 导入模块默认关闭安全考虑--dir path追加导入搜索目录多个目录用逗号分隔--no-outputHanzi关闭输出结果汉字化默认开启数字/布尔输出会转为汉字--log file将编译日志写入文件支持/dev/stdout、/dev/stderr--title title覆盖渲染标题默认取输出文件名或源文件名-h, --help显示帮助无参数直接运行也会打印帮助与 ASCII Logo输出文件的自动推导由 src/cli.ts 的preprocess可见当-o后未跟具体路径时编译器会以源文件名去掉扩展名为基础自动生成--compile时推导为${base}.${lang}如helloworld.js--render时推导为${base}.svg默认执行时推导为${base}.log。执行模式的限制值得注意直接执行不带--compile与交互式 REPL 仅支持目标语言jssrc/execute.ts 的isLangSupportedForEval会显式抛错Python / Ruby 目标必须配合--compile生成代码文件后另行运行。同时直接执行时数字与布尔输出默认会被汉字化outputHanziWrapper见 src/execute.ts例如打印5会输出五可用--no-outputHanzi关闭。语法速查表从变量到注释README 提供了一份详尽的文言 ↔ JavaScript对照语法表以下完整收录并补充说明。变量wenyanJavaScript吾有一數。曰三。名之曰「甲」。var a 3;有數五十。名之曰「大衍」。var dayan 50;昔之「甲」者。今「大衍」是也。a dayan;吾有一言。曰「「噫吁戲」」。名之曰「乙」。var b alas!;吾有一爻。曰陰。名之曰「丙」。var c false;吾有一列。名之曰「丁」。var d [];吾有三數。曰一。曰三。曰五。名之曰「甲」曰「乙」曰「丙」。var a1,b3,c5;数字由汉字书写一、三、五…其解析由 src/converts/hanzi2num.ts 负责词法阶段先把汉字数字串转换为数值字符串hanzi2numstr再进入 AST 构建。流程控制wenyanJavaScript若三大於二者。乃得「「想當然耳」」也。if (32){ return of course; }若三不大於五者。乃得「「想當然耳」」。若非。乃得「「怪哉」」也。if(35){return of course}else{return no way}為是百遍。⋯⋯ 云云。for (var i 0; i 100; i){ ... }恆為是。⋯⋯ 云云。while (true) { ... }凡「天地」中之「人」。⋯⋯ 云云。for (var human of world){ ... }乃止。break;运算wenyanJavaScript加一以二。12加一於二。21加一以二。乘其以三。(12)*3除十以三。所餘幾何。10%3減七百五十六以四百三十三。名之曰「甲」。var a 756-433;夫「甲」「乙」中有陽乎。a \|\| b夫「甲」「乙」中無陰乎。a b注意「以」与「於」区分操作数顺序加一以二为12加一於二为21这正对应古汉语的语序习惯。容器数组下标从一开始而非零。wenyanJavaScript吾有一列。名之曰「甲」。充「甲」以四。以二。var a []; a.push(4, 2);銜「甲」以「乙」。以「丙」a.concat(b).concat(c);夫「甲」之一。a[0]夫「甲」之其餘。a.slice(1);夫「玫瑰」之「「名」」。rose[name]夫「寶劍」之長。sword.length;对象wenyanJavaScript吾有一物。名之曰「甲」。var a {};吾有一物。名之曰「甲」。其物如是。物之「「乙」」者。數曰三。物之「「丙」」者。言曰「「丁」」。是謂「甲」之物也。var a {b:3, c:d}函数wenyanJavaScript吾有一術。名之曰「吸星大法」。是術曰。⋯⋯是謂「吸星大法」之術也。function f(){...}吾有一術。名之曰「六脈神劍」。欲行是術。必先得六數。曰「甲」。曰「乙」。曰「丙」。曰「丁」。曰「戊」。曰「己」乃行是術曰。⋯⋯是謂「六脈神劍」之術也。function f(a,b,c,d,e,f){...}吾有一術。名之曰「翻倍」。欲行是術。必先得一數。曰「甲」。乃行是術曰。乘「甲」以二。名之曰「乙」。乃得「乙」。是謂「翻倍」之術也。function double(a){var b a * 2; return b;}施「翻倍」於「大衍」。double(dayan);吾有一術。名之曰「甲」。欲行是術。必先得一數曰「乙」。二言。曰「丙」。曰「丁」function a(float b, string c, string d)夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。名之曰「己」。var f e(a,d(b,c))夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。取一以施「己」。夫「庚」。夫「辛」。取三以施「壬」。名之曰「癸」。var j i(f(e(a,d(b,c))),g,h)函数实例如 examples/factorial.wy定义递归的「階乘」術先得一數「甲」若等於一則直接返回否则施「階乘」於「乙」递归调用最后書之打印施「階乘」於五的结果。导入wenyanJavaScript吾嘗觀「「算經」」之書。方悟「正弦」「餘弦」之義。var {sin,cos} require(math);导入机制的底层实现在 src/reader.tsimportReader详见导入机制与标准库章节。杂项wenyanJavaScript吾有一數。曰五。書之。console.log(5);注释wenyanJavaScript批曰。「「文氣淋灕。字句切實」」。/*文氣淋灕。字句切實*/注曰。「「文言備矣」」。/*文言備矣*/疏曰。「「居第一之位故稱初。以其陽爻故稱九」」。/*居第一之位故稱初。以其陽爻故稱九*/编译流水线从文言到三种目标语言从源码结构看一次编译经历如下流水线词法分析src/parser.tswy2tokens处理「」字符串字面量、「「」」转义与汉字数字生成 Token 流关键字表定义在 src/keywords.ts数字关键字零一二三四五六七八九十…由 src/converts/hanzi2num.ts 支持语法分析 / AST 构建Token 序列被解析为 AST 节点ASCNode随后送入转译器多目标转译src/transpilers/index.ts 以{ js, py, rb }映射注册三个转译器它们继承自 src/transpilers/base.ts将同一 AST 分别输出为 JavaScript、Python 与 Ruby 代码宏展开与导入打包compile过程中会先经 src/macro.ts 的extractMacros/expandMacros处理或云…蓋謂…宏定义并经bundleImports内联导入模块可选的静态类型检查--strict会调用 src/typecheck.ts 的类型检查器在编译期发现类型不匹配执行仅 JSevalCompiledsrc/execute.ts在受控作用域内eval编译产物并把数字、布尔输出转换为汉字。关键词NUMBER_KEYWORDS用于词法阶段把连续汉字数字累积为一个数值 Token这正是标点可选能够成立的关键——数字与标识符的边界由关键字集合而非标点决定。导入机制与标准库README 语法表中的导入示例是吾嘗觀「「算經」」之書。方悟「正弦」「餘弦」之義。即从模块算經中导入「正弦」「餘弦」两个符号。从 src/reader.ts 的实现看导入解析遵循以下规则搜索路径依次在 CLI 的--dir指定目录、向上查找到的藏書樓目录MODULE_LIBRARY_NAME见 src/cli.ts、源文件所在目录、当前工作目录中查找模块名.wy或模块名/序.wyINDEX_FILENAME为「序」见 src/reader.tsHTTP 导入支持https://形式的远端模块但默认被安全策略拦截isHostTrusted白名单机制需显式传allowHttp才会放行缓存同一 URI 的导入结果会写入importCache避免重复读取。仓库自带的文言标准库位于 lib/ 目录包括基础数学库 lib/算經.wy、易经相关 lib/易經.wy、历法库 lib/曆法.wy 与 lib/曆表.wy、线性代数库 lib/列經.wy、组合数学库 lib/籌經.wy、混沌/随机库 lib/渾沌經.wy按目标语言分发的版本在 lib/js/位經、天地經、格物、畫譜、西曆法、lib/py/ 与 lib/rb/。导入测试覆盖见 test/import.test.ts 与嵌套导入夹具 test/fixture/nested-import/四庫全書/。渲染器把文言代码排版成古书样式 SVG这是 wenyan 最具特色的功能之一。src/render.ts 能把.wy源文件渲染成仿历史印刷书籍版式的矢量图SVG竖排文字、朱红批注、栏线边框一应俱全颜色常量RED/BLACK定义于 src/render.ts。README 给出的命令为wenyan examples/turing.wy --render 圖靈機 --output .注意当前版本 CLI 中--render为布尔开关标题需通过--title指定见 src/cli.ts 与 src/cli.ts等价且与当前 CLI 完全一致的写法是wenyan examples/turing.wy --render --title 圖靈機 --output .渲染行为细节对应 src/cli.ts 的doRender渲染结果始终写入文件若只生成一页输出为文件名.svg多页长程序时输出为文件名.001.svg、文件名.002.svg… 依次编号渲染前会剥离换行、制表符与空格把『』归一化为嵌套引号「「」」再进行词法分析见 src/render.ts排版按竖排栏位推进页宽792、栏宽由CW等常量控制见 src/render.ts注释以朱色小字呈现渲染器还实现了反向解析unrender可把生成的 SVG 解析回原始文言代码因此wenyan命令行也支持直接输入.svg文件作为源见 src/cli.ts。下图即是用文言编写的通用图灵机程序 examples/turing.wy 渲染而成的古书版式 SVG仓库 renders/ 目录保留了mandelbrot.svg、turing.svg、turing-wfont.svg等渲染成品可供参考。测试与验证项目使用 Jest 作为测试框架package.json 中npm test即运行jest --detectOpenHandles覆盖范围包括test/examples.test.ts逐一编译并运行 examples/ 下的示例快照存放于 test/snapshots/examples.test.ts.snaptest/import.test.ts验证嵌套导入与模块解析test/numbers.test.ts 与 test/reader.test.ts数字转换与词法/读取器行为test/stdlib.math.test.ts、test/stdlib.calendar.test.ts、test/stdlib.wonton.test.ts标准库函数正确性。此外 documentation/wenyan.g4 提供了上下文无关文法的 ANTLR 描述documentation/ 目录还有编译器 API、运行时、宏、嵌套函数调用、Try-Catch 等专题文档可作为深入阅读的入口。路线图与已知问题README 末尾列出了社区功能请求与已知问题摘录如下供参与贡献者参考功能请求名称优先级需要帮助状态语言规范★★★★★正在进行中类 / 对象文法★★★对象文法已经添加导入语句★★★导入语句已经添加标准库Math 数学 / Bitwise ops 位运算 / Random 随机★★★★★√正在进行中测试套件★★★★√正在进行中Switch 语句★★★函数式程序设计★★★更严格的编译器★★★★其他语言的编译器★★√编辑器的插件★★√适用于 VSCode、Vim、Sublime 的插件已添加将 js / py / anything 转换回 wenyan文言★√转义 / 生成特殊符号★★★对「「」」的替换语法★★对 。的替换语法★★在线 IDE 的字体和垂直文本★★将注释呈现为小型内联文本★★更多示例★★√已知问题名称优先级需要帮助状态汉字到数字的转换问题★★★★★汉字到数字转换中多字符数字没有被加入支持★★★如果你愿意帮助实现表中需要帮助一栏带 √ 的功能或任何其他功能都欢迎提交 Pull Request 参与协作。综上wenyan-lang 从语法表到 CLI、从导入机制到古书渲染器构成了一条完整且可运行的文言编程工具链。下一步建议先跑通wenyan examples/factorial.wy再用--compile --lang py生成 Python 版本对照阅读最后用--render把 examples/mandelbrot.wy 渲染成一册线装书亲自体会文心与代码的相遇。【免费下载链接】wenyan文言文編程語言 A programming language for the ancient Chinese.项目地址: https://gitcode.com/gh_mirrors/we/wenyan创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考