/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
Forwarded from iseki
呀…能处理那种缩进风格的文法了?🤔
Forwarded from Deleted Account
两个 bug 都解决了。我把一个整数大小比较写错了。
Forwarded from Deleted Account
@iseki_w 是的,支持 layout 的解析和(调试性)复显了(毕竟正经的语言肯定会重写这类代码,我没保留 layout 本身的解析结果)。
Forwarded from Deleted Account
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from Deleted Account
这么做都是为了 ParserKt……
Forwarded from Deleted Account
有很大把握可以在明天完成对 contextual LayoutPattern 的支持以及对 ParserKt 最后的检查,这样绝句的实现从 Layout 到 Infix 动态解析到汉字数值终于扫清了所有障碍,终于可以松口气了。
Forwarded from Deleted Account
val item = RepeatUn(asInt(), digitFor('0'..'9')) { i -> i.toString().map { it - '0' } }
val tail = Seq(::CharTuple, item('-'),item('>')).toStringPat()
val layout = Convert(Repeat(asString(), item(' ')).Many() prefix item('\n'), { it.length }, { "".padStart(it) })
val p = LayoutPattern(item, tail, layout)

就是这四行代码定义的布局解析器,现在我重构后已经支持 依据 item 和 tail 确定新布局里的解析项目了,但还没测试。

/** [Pattern.show] for resulting pattern should be general, since [show] does not use this function */
protected open fun decideLayerItem(parsed: T, parsedTail: L): Pattern<IN, T> = item
在我看来,ParserKt 的 LayoutPattern 和 传统方法 最大的差别就是
- PKT 的是 scannerless parsing,lexer-parser 的话那不是最后一层操作(各有优缺)
- Lexer 用数据栈、PKT 用系统栈(个人 profile,用系统栈貌似块那么几ms)
- PKT 没有利用 state,而把 state 建立在递归用栈里(当然它其实也是完全支持 contextual parsing 的)
- PKT 依赖 Deep { Root, Nest, Term } 这种递归数据结构存储解析结果,要再次转化为 AST 必须使用 Deep.Visitor(缺点)
- PKT 的 LayoutPattern 支持 rebuild,对调试很方便
- PKT 的 decideLayerItem; item, tail, layout 都是抽象的,而且 onNestIndent、onTermIndent 也都可重写。代码复用性很高(优点)
Forwarded from Deleted Account
@CodeHz 大佬,冰封之前也写过 lexer 层面把布局解析为内部 END token 的做法,你觉得我们这两个实现有啥优缺点呢 ~ 请dalao分析……
/tmp/duangsuse.sock
https://github.com/daorys1/mulan/blob/master/ulang/runtime/env.py#L213
lg.add('LBRACE', '{\\r*\\n*', flags=(re.DOTALL))
lg.add('RBRACE', '\\r*\\n*}', flags=(re.DOTALL))

代码质量奇差、异想天开
空格语法结构分不清,也不知道是简单了还是困难了,还是本来很 low 却很难伺候。
ParserKt 坚守节操,不修改 Feed 的基本定义,LL(1) 的问题完全可以利用 contextual 解析器,去区分……
Forwarded from Deleted Account
开始想 LL(1) 了,ParserKt 的 Feed,不可能 lookhead 任何字符,处理 /// 的分词,进退两难……
不知道是不是应该把分词降低到更低的层次、不知道是不是该模拟 state machine、不知道可不可能专门做兼容……
/tmp/duangsuse.sock
ParserKt 坚守节操,不修改 Feed 的基本定义,LL(1) 的问题完全可以利用 contextual 解析器,去区分……
ParserKt 针对 greedy trie pattern 根本没办法修复,因为它的 Feed 模型相当严格,一旦出现 peek = sticky end 的问题,非常难以解决——要判断是不是,必须 consume,consume 完若不是则一定会导致此字符已被消耗无法再用。

也不是不能利用扩展 Pattern 解决,确实是可以添加一个上下文,要求顺序解析 p1 p2 其中之一不为 notParsed,可那毕竟不是个容易复用的办法……
这个计算器足够,$#%#@……
/tmp/duangsuse.sock
ParserKt 针对 greedy trie pattern 根本没办法修复,因为它的 Feed 模型相当严格,一旦出现 peek = sticky end 的问题,非常难以解决——要判断是不是,必须 consume,consume 完若不是则一定会导致此字符已被消耗无法再用。 也不是不能利用扩展 Pattern 解决,确实是可以添加一个上下文,要求顺序解析 p1 p2 其中之一不为 notParsed,可那毕竟不是个容易复用的办法……
在 ParserKt 里,读取字符串非常简单,只需要 lookahead-1

val digit = digitFor('0'..'9')
val hex = Decide(digit, digitFor('A'..'Z', 'A', 10), digitFor('a'..'z', 'a', 10)).mergeFirst { if (it in 0..9) 0 else 1 }

val escapes = mapOf('"' to '"', 't' to '\t', 'b' to '\b', 'n' to '\n', 'r' to '\r', '\\' to '\\')
val namedEscape = MapPattern(escapes) { error("unknown escape '$it'"); '?' }
val unicodeEscapePart = object: Repeat<Char, Int, Int>(asInt(16), hex) {
override val bounds = 4..4
override val greedy = false
override fun unfold(value: Int) = value.toString(16).padStart(4, '0').map { hex.read(SingleFeed(it))!! } }
}
val unicodeEscape = Convert(unicodeEscapePart, Int::toChar, Char::toInt).clamWhile(hex, '?') {"bad unicode escape"}

val escaped = Decide(namedEscape, unicodeEscape).mergeFirst { if (it in escapes.values) 0 else 1 } prefix item('\\')
/tmp/duangsuse.sock
https://github.com/duangsuse-valid-projects/Share/blob/master/Others/kt_misc/pkt_9/String.kt#L17 ParserKt 总算稳当了些…… 🥳
fun KeywordPattern<String>.greedy() = Piped(this) { it ?: //FIXME is not possible
try { takeWhile { it !in this@greedy.routes }.joinToString("").takeIf(String::isNotEmpty) }
catch (_: Feed.End) { notParsed }
}

我还是不能容忍一个无法实际实现,有 bug 的 pattern 存在于 ParserKt 里。
混乱不堪的计算器