/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
Forwarded from Deleted Account
现在我在写 FP.js 的 parser 组合子,等到测试写完了,就可以用 FP.js 的组合子风格来写各种解析器了(
Forwarded from Yuuta⠀
你 TM 自己选吧!—— Outlook
This media is not supported in your browser
VIEW IN TELEGRAM
/tmp/duangsuse.sock
👋 Sticker
今天我来给大家分享一下心得(迫真) #dev

我昨天和今天都在写一个非常无聊的程序.... 就是一个解析组合子,欸这个知识背景它不需要啊,因为我是来分享写测试的心得的。

这个呢... 我需要写一个蛮复杂的状态机式程序,一个叫 Feeder 的类,它是用来表示用户输入的,就是一个字符流,我需要给它加上 CR/LF/CRLF 的行号和列号支持

至于两者的支持思路比较简单(毕竟之前我写了一个 lookAhead1 的包装流,所以可以同时看到两个连续字符)
不过测试的时候还是出现了一个低级的初始数值问题 — 我没有很好地分析程序控制流和数值断言,弄错了列号的意义:
abc
— ‘\n’ 本身是 col=1 d — col=2
而且因为程序控制流本身不是特别好看(因为有个非常长的带赋值副作用的表达式)

程序测试,就是这一个 next 方法,花了我至少一个半小时的时间,只是由于这个原因...
测试的过程中,我误会了原来错误的一个 root cause,也应用过一个错的修复,但最后暴力通过 REPL 一次一次计算的看知道错误在哪里了

不过上面的内容都很没意思,其实写这些只是想分享一个心得:测试的时候一定要保证测试本身的正确性,要不然测试写错程序通过了,反而可能跟着错... 测试失败了要找原因细想,不要为了通过测试而乱改测试。
心得就是一句话(迫真):不要为了通过测试而写测试,要为了保证程序符合预期而测试,不符合要两边找原因。
Forwarded from Deleted Account
另外这个是符合优雅性和正确性的,CRLF 折行内本来就不算一行,所以没有行号这回事(所以 CRLF 扫描完 CR 后行号是 -1 有合理性,因为它根本就不应该被视为单独的两行)
优雅性:可以把最后一个 branch 的 (... = false) 改成 true,这样就可以做到自动在 CRLF 的 LF 处『折行』(之后可以判断 --lineNum
实际用起来也正确,可是连续 <CR> <LF> 的 LF 毕竟不算完整的一行,不吼
好耶!是我写的第一个解析组合子!
如果能用它重写 GeekSpec 就大赞了!去你娘的 PEG!
/tmp/duangsuse.sock
好耶!是我写的第一个解析组合子!
目前这个解析器的设计存在严重的问题: seq, possible 等组合子可以组合很多子解析器,但是子解析器只被设计为对 seq 有效

比如 kwP,它会为 seq 将调用的 next() 使用一次 feeder.duplast() 在需要时免于 nextchar,可是在 possible 里使用,就会导致问题(重复的字符,因为 possible 不会像 seq 一样去 next())

另外还有 LL(1)-like 本来就存在的问题: 字符阅读后只能被『消耗』,很多看起来正常的组合比如 possible(seq(...), seq(...)) 是无法正常工作的(不能在 match 判断完一个 seq 之后,对之后的 seq 也有相同的上下文)
目前存在问题的版本
现在想要完全抛弃旧的组合策略是非常困难的事,因为 — 已经是这种滥用的样子了... 本来要是给每个解析器决定是否自己管理 next(),也是很容易的事情,可现在却没有那么简单了(各种 workaround) 可是不重构的话,很难实现 possible 这种组合子....
总之,现在结构需要优化、修复的还有很多,也有很多冗余构造需哟删掉,啊啊啊啊啊啊
甚至开始怀疑,是不是就不应该采用只可以取一项 / Lookahead 1 的字符流,PEG 好一些呢?
/tmp/duangsuse.sock
总之,现在结构需要优化、修复的还有很多,也有很多冗余构造需哟删掉,啊啊啊啊啊啊 甚至开始怀疑,是不是就不应该采用只可以取一项 / Lookahead 1 的字符流,PEG 好一些呢?
我决定咸鱼,It's a feature! 看!你可以利用 possible 函数,自己再独立实现不能被用于 possible 这样的 wsP, elemP, kwP 这种(啊啊啊,原来组合能力都这么差.... 可是也没有办法啦,流又不能随便重试的也无法实现自由的 possible 组合啊... 是我设计的时候搞错了
... Anti-feature....
/tmp/duangsuse.sock
我决定咸鱼,It's a feature! 看!你可以利用 possible 函数,自己再独立实现不能被用于 possible 这样的 wsP, elemP, kwP 这种(啊啊啊,原来组合能力都这么差.... 可是也没有办法啦,流又不能随便重试的也无法实现自由的 possible 组合啊... 是我设计的时候搞错了 ... Anti-feature....
这样的话技术问题除了 chainRec* 就解决了,possible 的组合项要自己写专门的解析器,不能用 seq 解析的 kwP, wsP 什么的(感觉好没有必要的样子... 虽然本来也就是没法用而已)

someFold 和 manyFold 本身和 seq 差别不大,就是需要判断直到不能解析为止,给 seq 解析设计的组合子还是可以复用的。

现在先保证真正可能消耗字符流的解析器都给 seq 设计(也是没有办法的事情,这不是 PEG 类的流结构,我这个是不能 mark/reset 的...)
然后再去完成复杂一点的组合吧;;;
/tmp/duangsuse.sock
我决定咸鱼,It's a feature! 看!你可以利用 possible 函数,自己再独立实现不能被用于 possible 这样的 wsP, elemP, kwP 这种(啊啊啊,原来组合能力都这么差.... 可是也没有办法啦,流又不能随便重试的也无法实现自由的 possible 组合啊... 是我设计的时候搞错了 ... Anti-feature....
啊, 不对,想了一会,我知道了,我知道自己在干什么了、我知道 nextItem 到底是该怎么用、为什么要有 duplast 函数了
其实是我的基本解析组合子写的不对,如果任何解析器解析失败,都应该 revert 掉自己对流之前的消耗
可是对于大的解析组合来说,他们做不到,但 charP, satisfy, elemP 还是做得到的,这点我之前没有注意到

而对于 seq 和 possible 组合,他们接受的都是 fail 或者不消耗的时候自动 revert 读取的组合子,
possible 也一样,虽然 possible 本身不 next,可是 possible 接受的所有解析器只判断一个项目并且保证失败恢复流,我只需修改 duplast 使它只能重置一回 lastItem 就可以了(?
This media is not supported in your browser
VIEW IN TELEGRAM
想想看 seq 的方式和 possible 的方式还可能是无法调节,重置,可是如果是在 possible 里,如果让 possible 处理这个不一致则会显得莫名其妙(而且很难看,因为目标是 next,如果一个成功什么都不做、如果一个失败你还得 next 一下,莫名其妙)

我还是决定.... 不要 possible 算了,possible 的用户都自己写。

some, many 组合应该不受影响(他们也是每项 next 的,解析不了让子解析器重置就可以了)。