Skip to content

wenyan-lang/wenyan-jvm

Repository files navigation

wenyan-lang_jvm

You can run WenYan Programming Language in JVM.

贡献您的标准库

  1. 找到标准库文件夹在这里贡献标准库
  2. 库映射文件下添加
final Map<Language,Map<String,String>> libs = [
            (Language.GROOVY) : [
                    "算經" : "cn.wenyan.lang.算經",
                    "位經" : "cn.wenyan.lang.位經",
                    "列經" : "cn.wenyan.lang.列經",
                    "物經" : "cn.wenyan.lang.物經",
                    "易經" : "cn.wenyan.lang.易經"
            ]
    ]

按照这个样式添加即可

  1. 编译调试后再pr,感谢

声明

  1. 关注本项目不要忘记关注一下语法源:LingDong的项目,因为本项目基于LingDong项目标准开发
  2. 语法非作者(MagicLu)原创。
  3. 本项目预计未来成形后,将会考虑贡献给WenYan本库。
  4. 本项目与LingDong项目一样,遵循MIT许可证
  5. 本项目非商业用途,任何人均可贡献,任何人也可以在合适范围内修改README
  6. 本项目使用方法可以参见文档
  7. 关于项目开启的原因可以参见 #411
  8. 本项目的目标语言是groovy,以实现动态语言,主要是为了实现wenyan可以调用java相关类库(并尽量确保js版本的wy文件),以实现在虚拟机运行。
  9. 对于文渊阁的支持,只需要在项目的src执行wyg i 名称即可。编译器提供了相关参数实现文渊阁的编译

相关链接

  1. wenyan_lang
  2. 文渊阁
  3. 更新日志
  4. LICENSE
  5. 语法库
  6. 文心雕龙

关于作者

是时,吾哀感生之须臾,若成大事,于漫岁月之中,如九渊之瀑,同万山之江,见日月星河之走兽,叹古今中外之大事。 夸夸而谈,此为吾之感是也,多愁善感,此为吾之心是矣。 时而求不以物喜不以己悲者,授之于人,而余愧。虽异古人之酌,摘湖中之月。此世千变万化,亦不知后事。 异隐者采菊,观贤者之莲。忆诸葛之往事,憾先主之心胸而无以馈,奸雄无阻而得大业。 叹于时,此非吾之生邪?

  1. 作者技术水平有限,所以不能很快实现全部语法,并且不能非常严谨的实现

  2. 不能确保全部来自javascript版的wenyan脚本通过编译。

  3. 作者欢迎所有人发送pull request/issue,拒绝issue灌水和讨论语言使用性,如果有类似的issue,将 无条件关闭,不予回答

  4. 由于作者尚未系统学习编译原理,没有使用抽象语法树,通过「正则」和「流程」(Stream) 完成了语言编译。

  5. 作者是也是一名文言文爱好者(或者是文学爱好者)

项目的特别功能

  • 项目的自定义系统
    1. 您可以通过项目的自定义系统自由的将文言文代码翻译为其他语言,通过添加Language.groovy的配置

    2. 插件系统(实验)

      • 继承Plugin.scala,标记Main类,打包为jar包,添加组件即可
  • wenyan_shell
    • java -jar wenyan.jar shell 可以开启交互式命令页面
  • 文渊阁 for java
    • 尚在策划
    • 基于文渊阁和maven的项目管理插件,可以实现文言文语言和java源代码混合编译
  • wenyan_java项目管理
    • 文言项目管理,可以参见TestMain.javaproject_example文件夹
    • 构建方案
      1. 随便建两个文件夹,为src和target(这名字可以自定义,这是我建议的名字)
      2. src下建一个MakeFile.txt,里面写上主类的路径
      3. java -jar wenyan.jar -c @src/MakeFile.txt target -sc src -m 主运行类名(类名 = 文件名) 编译,会在target输出全部编译文件
      4. java -jar wenyan.jar -o target -n 主类名 -r 运行

与javascript/python/ruby版本的区别

  1. 这里支持了编译为groovy
  2. 对于文件名称要求严格,不能使用特殊符号标记

实现效果

已经可以运行wenyan-lang的图灵机,图灵完备

turing

目前实现的语法

變量
wenyan groovy
吾有一數。曰三。名之曰「甲」。 def jia=3
吾有一言。曰「「噫吁戲」」。名之曰「乙」。 def yi = '噫吁戲'
吾有一爻。曰陰。名之曰「丙」。 def bing = false
吾有一列。名之曰「丙」。 def bing = []
吾有三數。曰一。曰三。曰五。名之曰「甲」曰「乙」曰「丙」。 def jia = 1,yi=3,bing=5
吾有一數。曰五。書之 def ans_1=5 println(ans_1)
吾有一言。曰「乙」。書之 println(yi)
有數五十。名之曰「大衍」。 def dayan = 50
昔之「甲」者。今「大衍」是也。 jia = dayan
吾有一元 (auto type)
数组
wenyan groovy
吾有一列。名之曰「甲」。充「甲」以四。以二。 def a = []; a.add(1);
夫「甲」之一。 a[0]
夫「玫瑰」之「「名」」 rose["name"]
夫「甲」之其餘。 a.slice(1)
夫「寶劍」之長。 sword.size();
銜「甲」以「乙」。以「丙」 jia.putAll(yi) jia.putAll(bing)
註釋
wenyan groovy
批曰。「「文氣淋灕。字句切實」」。 /*文氣淋灕。字句切實*/
注曰。「「文言備矣」」。 /*文言備矣*/
疏曰。「「居第一之位故稱初。以其陽爻故稱九」」。 /*居第一之位故稱初。以其陽爻故稱九*/
控制
wenyan groovy
為是百遍。⋯⋯ 云云。 for (i in 1..100){ ... }
若「甲」等於「乙」者。......也。 if(jia == yi){
若非。 }else{
恆為是。⋯⋯ 云云。 while (true) { ... }
乃止。 break
凡「天地」中之「人」。⋯⋯ 云云。 for (human in world){ ... }
或若 else if
若其然者 if (ans) {
若其不然者 if (!ans) {
數學
wenyan groovy
加一以二。 1+2
加一於二。 2+1
加一以二。乘其以三。 (1+2)*3
除十以三。所餘幾何。 10%3
減七百五十六以四百三十三。名之曰「甲」。 def a = 756-433;
夫「甲」「乙」中有陽乎 a || b
夫「甲」「乙」中無陰乎。 a&&b
导入
wenyan groovy
吾嘗觀「「算經」」之書。方悟「正弦」之義。 import static 算经.正弦
吾嘗觀「「某樓」」中「「某閣」」中「「某書」」之書 import 某樓.某閣.某書
函数
wenyan groovy
吾有一術。名之曰「吸星大法」。是術曰。⋯⋯是謂「吸星大法」之術也。 def a(){...}
吾有一術。名之曰「六脈神劍」。欲行是術。必先得六數。曰「甲」。曰「乙」。曰「丙」。曰「丁」。曰「戊」。曰「己」乃行是術曰。⋯⋯是謂「六脈神劍」之術也。 def b(a,b,c,d,e,f){...}
施「翻倍」於「大衍」 b(dayuan)
施「翻倍」 b()
夫「甲」。夫「乙」。夫「丙」。取二以施「丁」。取二以施「戊」。取一以施「己」。夫「庚」。夫「辛」。取三以施「壬」。名之曰「癸」。 def j = i(f(e(a,d(b,c))),g,h)
wenyan groovy
或云「「書「甲」焉」」。蓋謂「「吾有一言。曰「甲」。書之」」。 Compiled Code
异常处理
wenyan groovy
姑妄行此 try
其他异常有关语句均实现
对象
wenyan groovy
吾有一物。名之曰「甲」。 def a = [:]
吾有一物。名之曰「甲」。其物如是。物之「「乙」」者。數曰三。物之「「丙」」者。言曰「「丁」」。是謂「甲」之物也 def a = [b:3,c:"d"]
昔之「戊」之「「丁」」者。今不復存矣。 戊.remove("丁")

特殊语法

特殊语法是本编译器独有的语法糖,有些是由于编译器实现的机制所导致的产物

本編譯器允許直接使用書之,可以輸出最後定義的變量

调用静态方法

吾嘗觀「「java」」中「「lang」」中「「Math」」之書。
施「Math.pow」於「大衍」於二。名之曰「矣」。書之

使用java对象

施「new String」於「大衍」。名之曰「矣」。
施「矣.getClass」。書之。

如何使用

-m: 参数: 主类,编译时,设置编译主类,比如cn.main.HelloWorld,对应着@sourceFile/cn/main/HelloWorld.wy

-n: 参数: 主类,运行时,设置运行主类,比如cn.main.HelloWorld,对应着@sourceFile/cn/main/HelloWorld.wy

-o: 参数: OutFile,单独设置编译文件输出的文件夹

-p: 该指令已经废弃,使用无效

-r: 参数: 程序参数,运行主文件,-r后面跟着args,即程序参数,这个选项必须放在最后面,比如 -o xxx -c xxx -r 1 2 3

-c: 参数: makeFile和outFile,设置编译文件路径,如@MakeFile.txt或者HelloWorld.wy,后面是输出的文件夹根目录

-g: 该指令废弃,不要使用

-wd: 参数: name,相当于wyg i name,确保有node.js

-sc: 参数: sourcePath,指定源文件的根目录,根目录下面的文件夹则作为package名称

-wyg: 参数: 藏書樓的上一级目录,将文渊阁编译进去,后面跟着藏書樓的上一级目录即可,需要有-sc和-o的内容

-l: 参数: jarFiles,加入依赖的jar包,如hello.jar;eat.jar

-lv: 分詞可視化

-st: 开启强类型编译

直接加载文言文脚本

import cn.wenyan.compiler.WenYanTools

def compiler = WenYanTools.makeCompiler()

def javaClass = compiler.compileToClass("HelloWorld","吾有一言,曰『问天地好在』,書之。")

javaClass.getDeclaredMethod("run").invoke(javaClass.newInstance())

目前需要迫切实现的

  • shell 高级操作
    • 导入jar包/wy文件
  • idea 插件
  • maven插件

编译器原始的第三方包导入

  1. 编译器将wy文件编译为class字节码文件
  2. 将class字节码文件打包为jar包
  3. 通过编译器-l导入进去即可

对于部分不兼容的特性

PS: 由于一些代码按照js特性去实现的,很多特性我都是通过语法糖暴力实现。但这些我确实无力去实现了

  1. 对于函数调用,如果是闭包函数,请先吾有一術。名之曰「xx」。定义,这样才能确保前面的函数调用后面实现的函数
今有一術。名之曰「包渾沌」。欲行是術。必先得一物。曰「渾沌物」。乃行是術曰。
	吾有一言。曰「「 」」名之曰「挪符」。
	吾有一言。曰「「\n」」名之曰「抬符」。
	吾有一術。名之曰「包數」。
	吾有一術。名之曰「暗包渾沌」。
	吾有一術。名之曰「包列」。
	吾有一術。名之曰「包物」。
	吾有一術。名之曰「包數」。欲行是術。必先得一數曰「甲」。乃行是術曰。
		吾有一言。名之曰「正負」。
		若「甲」小於零者。
			乘「甲」以負一。昔之「甲」者。今其是矣。
			昔之「正負」者。今「「負」」是矣。
		云云。
		除「甲」以一。所餘幾何。名之曰「小數」
		減「小數」於「甲」。名之曰「整數」。
		吾有二言。名之曰「小」曰「整」。
		恆為是。若「整數」不大於零者乃止也。
			除「整數」以十。所餘幾何。名之曰「位」。
			加「位」以一。夫「位名」之其。加其以「整」。昔之「整」者。今其是矣。
			減「整數」以「位」。除其以十。昔之「整數」者。今其是矣。
		云云。
		恆為是。若「小數」不大於零者乃止也。
			乘「小數」以十。昔之「小數」者。今其是矣。
			除「小數」以一。所餘幾何。名之曰「位」。
			加「位」以一。夫「位名」之其。加其於「小」。昔之「小」者。今其是矣。
			減「小數」以「位」。昔之「小數」者。今其是矣。
		云云。
		加「正負」以「整」。昔之「整」者。今其是矣。
		夫「小」之長。若其然者。
			加「整」以「「·」」。加其以「小」。乃得矣。
		云云。
		乃得「整」。
	是謂「包數」之術也。

	吾有一術。名之曰「暗包渾沌」。欲行是術。必先得一言曰「類」。一元曰「實」。一數曰「挪抬」。乃行是術曰。
		吾有一言。名之曰「渾沌語」。
		若「類」等於「「物」」者。
			加「渾沌語」以「抬符」昔之「渾沌語」者。今其是矣。
			夫「實」。加「挪抬」以一。取二以施「包物」。加其於「渾沌語」。昔之「渾沌語」者。今其是矣。
			為是「挪抬」遍。加「渾沌語」以「挪符」。昔之「渾沌語」者。今其是矣也。
			加「渾沌語」以「「也」」加其以「抬符」。昔之「渾沌語」者。今其是矣。

		或若「類」等於「「列」」者。
			加「渾沌語」以「抬符」昔之「渾沌語」者。今其是矣。
			夫「實」。加「挪抬」以一。取二以施「包列」。加其於「渾沌語」。昔之「渾沌語」者。今其是矣。
			為是「挪抬」遍。加「渾沌語」以「挪符」。昔之「渾沌語」者。今其是矣也。
			加「渾沌語」以「「也」」加其以「抬符」。昔之「渾沌語」者。今其是矣。

		或若「類」等於「「言」」者。
			加「渾沌語」以「引起」加其以「實」加其以「引迄」。加其以「抬符」昔之「渾沌語」者。今其是矣。
		或若「類」等於「「爻」」者。
			吾有一言。曰「「陽」」。名之曰「爻名」
			夫「實」。若其不然者。昔之「爻名」者。今「「陰」」是矣也。
			加「渾沌語」以「引起」加其以「爻名」加其以「引迄」。加其以「抬符」昔之「渾沌語」者。今其是矣。
		或若「類」等於「「數」」者。
			施「包數」於「實」。名之曰「數名」。
			加「渾沌語」以「引起」加其以「數名」加其以「引迄」。加其以「抬符」昔之「渾沌語」者。今其是矣。
		云云。
		乃得「渾沌語」
	是謂「暗包渾沌」之術也。

	吾有一術。名之曰「包列」。欲行是術。必先得一物曰「渾沌列」。一數曰「挪抬」。乃行是術曰。
		吾有一言。名之曰「渾沌語」。
		凡「渾沌列」中之「實」
			施「識類」於「實」。名之曰「類」。

			為是「挪抬」遍。加「渾沌語」以「挪符」。昔之「渾沌語」者。今其是矣也。
			加「渾沌語」以「類」。
			昔之「渾沌語」者。今其是矣。

			施「暗包渾沌」於「類」於「實」於「挪抬」。加其於「渾沌語」。昔之「渾沌語」者。今其是矣。
		云云。
		乃得「渾沌語」
	是謂「包列」之術也。

	吾有一術。名之曰「包物」。欲行是術。必先得一物曰「渾沌物」。一數曰「挪抬」。乃行是術曰。

		吾有一言。名之曰「渾沌語」。

		施「列物之端」於「渾沌物」。名之曰「諸端」。

		凡「諸端」中之「端」
			施「取物」於「渾沌物」於「端」。名之曰「實」。
			施「識類」於「實」。名之曰「類」。

			為是「挪抬」遍。加「渾沌語」以「挪符」。昔之「渾沌語」者。今其是矣也。
			加「渾沌語」以「「之」」。加其以「引起」。加其以「端」。加其以「引迄」。加其以「類」。
			昔之「渾沌語」者。今其是矣。

			施「暗包渾沌」於「類」於「實」於「挪抬」。加其於「渾沌語」。昔之「渾沌語」者。今其是矣。
		云云。
		乃得「渾沌語」
	是謂「包物」之術也。

	施「包物」於「渾沌物」於一。名之曰「餛飩語」。
	加「抬符」以「餛飩語」。加其於「「物」」。加其以「「也」」。乃得矣。
是謂「包渾沌」之術也。

  1. 下一级定义域重新定义上一级已经定义的变量
var  = 1;
    var  = 1;
    for (var _rand1 = 0; _rand1 < ; _rand1++) {
        var _ans1 =  * ;
        var  = _ans1;
        var _ans2 =  - 2;
        var  = _ans2;
        var _ans3 =  * 2;
        var  = _ans3;
        var _ans4 =  / ;
        var  = _ans4;
        var _ans5 =  - ;
        var  = _ans5;
    };
  1. 对于第一级的函数是无法引用的,如果要引用,也是有办法
今有一術。名之曰「包渾沌1」。欲行是術。必先得一物。曰「渾沌物」。乃行是術曰。
    ....
是謂「包渾沌1」之術也。

今有一術。名之曰「包渾沌」。欲行是術。必先得一物。曰「渾沌物」。乃行是術曰。
    今有一術。名之曰「包渾沌3」。欲行是術。必先得一物。曰「渾沌物」。乃行是術曰。
        施「包渾沌1」於「渾沌物」
    是謂「包渾沌」之術也。
是謂「包渾沌」之術也。

这样通过引用包混沌3即可,由于语言特性的限制,对于第一级函数的引用我正在研究