Forwarded from Justf News (Justf | 瞎子)
/tmp/duangsuse.sock
lg.add('LBRACE', '{\\r*\\n*', flags=(re.DOTALL)) lg.add('RBRACE', '\\r*\\n*}', flags=(re.DOTALL)) 代码质量奇差、异想天开 空格语法结构分不清,也不知道是简单了还是困难了,还是本来很 low 却很难伺候。
https://github.com/daorys1/mulan/blob/master/ulang/codegen/ulgen.py#L387
不错,还真是研究员的风格。叫 chr 的 变量就会变成叫 char 的。
不错,还真是研究员的风格。叫 chr 的 变量就会变成叫 char 的。
GitHub
daorys1/mulan
[UNOFFICIAL] re-implementation of mulan(also known as muLang) - daorys1/mulan
为什么有很多人执着于中文编程? - invalid s的回答 - 知乎 #zhihu #PLT
https://www.zhihu.com/question/355223335/answer/947391737
https://www.zhihu.com/question/355223335/answer/947391737
Zhihu
为什么有很多人执着于中文编程? - 知乎
嗯,很有趣的图表。这个问题,前两天每天两万浏览。但它显然伤害了一些人的利益。于是两天后,它的浏览量…
/tmp/duangsuse.sock
为什么有很多人执着于中文编程? - invalid s的回答 - 知乎 #zhihu #PLT https://www.zhihu.com/question/355223335/answer/947391737
看了这篇,压死骆驼的最后一根稻草,我觉得那些不能落地的,都不算是做得实事。
中文编程曾经是笑话,我将让它不再是笑话。
中文编程曾经是笑话,我将让它不再是笑话。
我简单看了一下 ulang 的实现,ParserKt 所实现的第一门语言 可能就是它了
+ runtime/env 运行时利用库
+ runtime/main, runtime/repl 实现功能入口
顺便说一句,ParserKt 是正经的 LL(1) 流递归下降解析器,什么 match bracket 的 REPL 对我们简直是小儿科,何须用什么 is_close?
词法处理我之前已经做了,没做完。(PKT 的 one-pass LL(1) 处理 C 风格注释是太困难了)
+ codegen 语义、代码生成(Python AST 转化)
+ runtime/env 运行时利用库
+ runtime/main, runtime/repl 实现功能入口
顺便说一句,ParserKt 是正经的 LL(1) 流递归下降解析器,什么 match bracket 的 REPL 对我们简直是小儿科,何须用什么 is_close?
val entries = JoinBy(item(';'), stringFor(!elementIn(';', '}')) ).mergeConstantJoin()
val brk = SurroundBy(item('{') to item('}').clam {"unclosed {"}, entries)
val white = elementIn(' ', '\t') named "white"
val ws = stringFor(white).toConstant("")
val wsNL = stringFor(newlineChar or white named "ws").toConstant("")
val repl = JoinBy(newlineChar, SurroundBy(wsNL to ws, brk)).OnItem { println(it) }.mergeConstantJoin('\n')
+ parser 语法词法处理我之前已经做了,没做完。(PKT 的 one-pass LL(1) 处理 C 风格注释是太困难了)
+ codegen 语义、代码生成(Python AST 转化)
GitHub
mulan/ulang/runtime/env.py at master · daorys1/mulan
[UNOFFICIAL] re-implementation of mulan(also known as muLang) - daorys1/mulan
Forwarded from /tmp/duangsuse.sock
看了这篇,压死骆驼的最后一根稻草,我觉得那些不能落地的,都不算是做得实事。
中文编程曾经是笑话,我将让它不再是笑话。
中文编程曾经是笑话,我将让它不再是笑话。
Forwarded from Deleted Account
你是指什么?我只是觉得,知乎那个中文编程组织
其实…… 努力不一定能成功、付出也不一定能得到回报
我的意思大概是,不打算和他们扯上关系。
其实…… 努力不一定能成功、付出也不一定能得到回报
我的意思大概是,不打算和他们扯上关系。
知乎专栏
中文编程
因地制宜,尽量用中文写代码
/tmp/duangsuse.sock
我简单看了一下 ulang 的实现,ParserKt 所实现的第一门语言 可能就是它了 + runtime/env 运行时利用库 + runtime/main, runtime/repl 实现功能入口 顺便说一句,ParserKt 是正经的 LL(1) 流递归下降解析器,什么 match bracket 的 REPL 对我们简直是小儿科,何须用什么 is_close? val entries = JoinBy(item(';'), stringFor(!elementIn(';', '}')) ).me…
ParserKt 并不是 LL(1) 的。实际上对于 Feed 模型,不存在 lookahead—— 一个字符的 lookahead 都不可行!!!
怎么说呢,
怎么说呢,
//、/*、0x 1.0 这样的文法,支持起来非常困难,会把解析器对代码易用性的优化“打回原型”。Contextual 这个解析模式,本来是用于给下面的解析过程加上下文的,在这样困难的时节却也可以用来适配类似的字符流模式,但由于不同的 Pattern 永远不是一家,这样的定义是困难的。我不知道大家会怎么想 ParserKt,它现在还没实际上的文档(虽然代码里的提纲文档很丰富并且注重简洁性)
它不是算法出生,没有一点复杂的算法,说白了就是编程语言实现的时候会做的那些事,一个简单的泛型流、一个递归下降解析模式。
没有 lookahead、没有 lookbehind、没有冲突、没有匹配、没有编号、没有状态机,支持很抽象的文法模式,但它没有“编译期”,这同时是它的优点和缺点。
尽管文件里也包含一些比较复杂的算法(动态中缀链、字典树),内联文档和示例是一点也不缺的。所以不管怎么喷都不能喷它太复杂——同类框架里就它最简单了,甚至比一些 JavaScript 的框架还简单。
ParserKt 对 Feed 的严苛约束,以及对
但我不得不承认,对泛型流(甚至包括 nullable type)的支持,以及流的 sticky end (不能 consume 的 peek) 造成了很大的混淆
ANTLR 可以支持 EOF,但 ParserKt 没有与之等价的方法,它的 EOF 是一个 CharConstantPattern,那不完全等价。
它不是算法出生,没有一点复杂的算法,说白了就是编程语言实现的时候会做的那些事,一个简单的泛型流、一个递归下降解析模式。
没有 lookahead、没有 lookbehind、没有冲突、没有匹配、没有编号、没有状态机,支持很抽象的文法模式,但它没有“编译期”,这同时是它的优点和缺点。
尽管文件里也包含一些比较复杂的算法(动态中缀链、字典树),内联文档和示例是一点也不缺的。所以不管怎么喷都不能喷它太复杂——同类框架里就它最简单了,甚至比一些 JavaScript 的框架还简单。
ParserKt 对 Feed 的严苛约束,以及对
Pattern.show 的支持看起来是搞笑,但那真的是为了简化模型,方便上手定义新 Pattern 做的,如果支持 Mark/Reset 甚至 lookahead/lookbehind,那么整个解析器的读取逻辑就不容易让人关注重点,我不喜欢那样。但我不得不承认,对泛型流(甚至包括 nullable type)的支持,以及流的 sticky end (不能 consume 的 peek) 造成了很大的混淆
ANTLR 可以支持 EOF,但 ParserKt 没有与之等价的方法,它的 EOF 是一个 CharConstantPattern,那不完全等价。
其实 ParserKt 的 rebuild 有时候也会成为累赘…… 比如说,在支持 仅仅是一种表达形式的值 的时候…… 几乎毫无意义,还导致了各种 mergeXXX 的乱入
ParserKt 讲究的的确是“无遗漏(完全解析)”、“一遍过(one-pass)”,但随着编写的解析器开始倾向实际工程,完全不损失信息逐渐变得不可能,于是才出现了开始的 Convert (no convert back) 以及现在的 mergeConstantJoin 和 mergeFirst, mergeSecond, flatten, toConstant 这类指定默认值或者转化存储法的修饰方法……
但现在 Decide 这样的解析器,也是没办法再转化了,不得不写 mergeFirst 来合并它的 caseNo…… 即便我根本不打算利用 rebuild,
为了兼容更多更复杂的文法,Contextual、Piped 之类的解析器的使用也开始频繁,没办法完美地解决从不完整的数据 rebuild 的问题,但仍希望更多解决方案能在将来被加入。
ParserKt 讲究的的确是“无遗漏(完全解析)”、“一遍过(one-pass)”,但随着编写的解析器开始倾向实际工程,完全不损失信息逐渐变得不可能,于是才出现了开始的 Convert (no convert back) 以及现在的 mergeConstantJoin 和 mergeFirst, mergeSecond, flatten, toConstant 这类指定默认值或者转化存储法的修饰方法……
但现在 Decide 这样的解析器,也是没办法再转化了,不得不写 mergeFirst 来合并它的 caseNo…… 即便我根本不打算利用 rebuild,
为了兼容更多更复杂的文法,Contextual、Piped 之类的解析器的使用也开始频繁,没办法完美地解决从不完整的数据 rebuild 的问题,但仍希望更多解决方案能在将来被加入。
/tmp/duangsuse.sock
看了这篇,压死骆驼的最后一根稻草,我觉得那些不能落地的,都不算是做得实事。 中文编程曾经是笑话,我将让它不再是笑话。
有了 ParserKt 的帮助,绝句便可以轻松地实现各种复杂的文法(诸如动态定义中缀操作符、缩进块、中文数字),而且不需要几行代码、与 Kotlin 程序设计语言无缝交接。
/tmp/duangsuse.sock
又写了个 JSON 解析器出来
其实如果说 ParserKt 设计绝句解析器的可能性,已经完成了。
汉字数值读写不存在问题,绝句里实际上不存在需要 lookahead 才能够判断的注释,都是单字符的 🙃
ParserKt 实际上已经能用了,SURDIES, FoldPattern, SingleFeed, CCDP(Convert, Contextual, Deferred, Piped), SJIT(SurroundBy, JoinBy, InfixPattern, TriePattern), NumUnitPattern, LayoutPattern,这些都是经历实际测试的 class 了,它们能够解决对各种序列结构的读取和显示。
现在是时候从 duangsuse 的 Share 那里分家出来了。严谨化 sample、建立独立的文档、JitPack 打包,把 ParserKt 包装出来。
https://github.com/duangsuse-valid-projects/Share/blob/2c35e429d9923eafe6d2aa9c1db07c3df6dc7e9a/Others/kt_misc/pkt_9/Parser.kt
8 天前 ParserKt 的第九次重构开始,从 449 行增长到今天的 1, 425 行
https://github.com/duangsuse-valid-projects/Share/blob/2c35e429d9923eafe6d2aa9c1db07c3df6dc7e9a/Others/kt_misc/pkt_7/Parser.kt
18 天前 ParserKt 的第七次重构起始,这个寒假里最费事的玩意……
希望它能好好的“报效”我为它花的时间,保佑以后都不用写各种奇奇怪怪的解析程序/文法定义了。
ParserKt 是我写出复用性、灵活性、健壮性最好的解析器框架了,但不得不说,如果没有 Kotlin 的类型推导它就是一堆废话,希望大家不要忘了幕后的人们啊。
#PL #Project #Algorithm
汉字数值读写不存在问题,绝句里实际上不存在需要 lookahead 才能够判断的注释,都是单字符的 🙃
ParserKt 实际上已经能用了,SURDIES, FoldPattern, SingleFeed, CCDP(Convert, Contextual, Deferred, Piped), SJIT(SurroundBy, JoinBy, InfixPattern, TriePattern), NumUnitPattern, LayoutPattern,这些都是经历实际测试的 class 了,它们能够解决对各种序列结构的读取和显示。
现在是时候从 duangsuse 的 Share 那里分家出来了。严谨化 sample、建立独立的文档、JitPack 打包,把 ParserKt 包装出来。
https://github.com/duangsuse-valid-projects/Share/blob/2c35e429d9923eafe6d2aa9c1db07c3df6dc7e9a/Others/kt_misc/pkt_9/Parser.kt
8 天前 ParserKt 的第九次重构开始,从 449 行增长到今天的 1, 425 行
https://github.com/duangsuse-valid-projects/Share/blob/2c35e429d9923eafe6d2aa9c1db07c3df6dc7e9a/Others/kt_misc/pkt_7/Parser.kt
18 天前 ParserKt 的第七次重构起始,这个寒假里最费事的玩意……
希望它能好好的“报效”我为它花的时间,保佑以后都不用写各种奇奇怪怪的解析程序/文法定义了。
ParserKt 是我写出复用性、灵活性、健壮性最好的解析器框架了,但不得不说,如果没有 Kotlin 的类型推导它就是一堆废话,希望大家不要忘了幕后的人们啊。
#PL #Project #Algorithm
GitHub
duangsuse-valid-projects/Share
🐕 duangsuse's shared files(e.g. productive software projects, documents) - duangsuse-valid-projects/Share
/tmp/duangsuse.sock
其实如果说 ParserKt 设计绝句解析器的可能性,已经完成了。 汉字数值读写不存在问题,绝句里实际上不存在需要 lookahead 才能够判断的注释,都是单字符的 🙃 ParserKt 实际上已经能用了,SURDIES, FoldPattern, SingleFeed, CCDP(Convert, Contextual, Deferred, Piped), SJIT(SurroundBy, JoinBy, InfixPattern, TriePattern), NumUnitPattern, Lay…
你们觉得好笑吧,ParserKt 的中文计算器写了 62 行还带 REPL,star 最多的 TypeScript 原生解析器框架(非 parser gen)就多支持了个函数调用,总共写了 300 多行
再加几个 example 上来就抵过 ParserKt 整个项目的代码量了,现在谁是 KISS,谁是『令人不明觉厉、显得很大佬』?
再加几个 example 上来就抵过 ParserKt 整个项目的代码量了,现在谁是 KISS,谁是『令人不明觉厉、显得很大佬』?
GitHub
duangsuse-valid-projects/Share
🐕 duangsuse's shared files(e.g. productive software projects, documents) - duangsuse-valid-projects/Share
那是不比较代码本身的,然后我们再对比一下两者的定义:
== 加减乘除运算符 ==
ParserKt 费了 7 行定义完了所有出现的运算符,并且包含它们的优先级信息。
SAP/chevrotain 单单定义加减乘除长啥样,就用掉 24 行代码
并且,它还把加减法都归类为 AdditionalOperator…… 显然对数学运算符,有没有对称性会比这种优先级上的工作有意义。
再说两个细节,数字读取和括号表达式。
star 很多的框架写了 5 行。
ParserKt 只需写一行就完了,加上错误处理也只用一行。
如果说完全等价的,
== 加减乘除运算符 ==
val ops = KeywordPattern<InfixOp<Number>>().apply {
listOf("*", "乘").forEach { register(it infixl 0 join fn(Int::times)) }
listOf("/", "除以").forEach { register(it infixl 0 join fn(Int::div)) }
register("除" infixl 0 join flip(fn(Int::div)))
register("分" infixl 0 join { a: Number, b: Number-> (a.toDouble() / b.toDouble()) as Number })
listOf("+", "加") .forEach { register(it infixl 1 join fn(Int::plus)) }
listOf("-", "减") .forEach { register(it infixl 1 join fn(Int::minus)) }
} ParserKt 费了 7 行定义完了所有出现的运算符,并且包含它们的优先级信息。
const Plus = createToken({
name: "Plus",
pattern: /\+/,
categories: AdditionOperator
}) //... SAP/chevrotain 单单定义加减乘除长啥样,就用掉 24 行代码
并且,它还把加减法都归类为 AdditionalOperator…… 显然对数学运算符,有没有对称性会比这种优先级上的工作有意义。
const AdditionOperator = createToken({
name: "AdditionOperator",
pattern: Lexer.NA
})
至于左递归 additionExpression, multiplicationExpression 就没啥可说了,毕竟属于解析器框架提供接口上的区别,这些定义用掉 18 行。再说两个细节,数字读取和括号表达式。
$.RULE("parenthesisExpression", () => {
$.CONSUME(LParen)
$.SUBRULE($.expression)
$.CONSUME(RParen)
}) star 很多的框架写了 5 行。
val atomParen = SurroundBy(parens.toCharPat(), Deferred{expr}) ParserKt 只需写一行就完了,加上错误处理也只用一行。
const NumberLiteral = createToken({
name: "NumberLiteral",
pattern: /[1-9]\d*/
})
$.RULE("atomicExpression", () => {
$.OR([/**/{ ALT: () => $.CONSUME(NumberLiteral) }, ...
单单定义 NumberLiteral 叫什么名字、长什么样子,就写了 4 行val digit = digitFor('0'..'9')
val zeroNotation = Decide(
StickyEnd(item('0') or EOF, 0) { if (octal.test(peek)) error("no octal notations"); -1 }
)
val numPart = Contextual<Char, Int, Int>(digit) {
if (it == 0) zeroNotation
else Repeat(asInt(10, it), digit).Many()
}.discardFirst()
带上可以继续扩展/抽提的结构和直接数值读取,8 行。如果说完全等价的,
Contextual(digitFor('1'..'9')) { Repeat(asInt(10, it), digitFor('0'..'9')) }.ignoreFirst(),1 行。GitHub
SAP/chevrotain
Parser Building Toolkit for JavaScript. Contribute to SAP/chevrotain development by creating an account on GitHub.