/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
拜拜坏习惯
This media is not supported in your browser
VIEW IN TELEGRAM
val ops = KeywordPattern<InfixOp<Int>>().apply {
register("*" infixl 0 join Int::times)
register("/" infixl 0 join Int::div)
register("+" infixl 1 join Int::plus)
register("-" infixl 1 join Int::minus)
}

新的 Infix operator DSL
绝句还是太嫩了…… 即便是要直接翻译到 Kotlin,这具体定义还差着老远呢。
Kotlin 说的对,要“改良”我的确是还没那个经历、没那个资格呢
还是 Kotlin 厉害,我很服,先以适配 Kotlin 为主要目标,看着办吧。

异常的确是个好问题,如果以 coroutine 的思路思考问题我的确是在说笑了,所以主动减负是个明智的选择,先做点边缘工作看看行不行吧。
我们的 ParserKt 也能用了,解决 literal int/string 读写的问题不是大问题、中缀表达式也不成问题
可是单单就语法前端层面来看,大的结构也是没有实践过,还是没经验、没自信,毕竟咱的框架是 from scratch,靠的都是咱比较片面的老经验。但新的东西到底是要有的,路,走的人多了不也就能用了么?

咱的解析器框架是少有的,完全依靠 Kotlin 标准库的基本抽象数据构造的库,没有什么栈啊状态机的,完全泛型化、可组织化,包含对 error handling 和 rebuild——或许还是头一次呢!——的解决方案

整个框架 700 行,还提供了 Tuple 和 Fold 这两个复用性相当高的抽象,每个文件都有专门的注释纲领,是相当概括和克制的。

ParserKt 提供了相当概括的接口——Tuple/Fold,Pattern 是可 read 可 show,都是基于 Feed/Input 流的
常用的是 SURDIES—Seq/Until/Repeat/Decide 、item/elementIn/satisfy

现在想让它先继续试着去实践一下那个 JSON 解析器,再来解决 MiniScheme 的问题,但是这个 MiniScheme 的语法和语义得先规范定义一点……
/tmp/duangsuse.sock
#math #Java #Kotiln #gui
这张是原来的设计。
就先这么规定,字面数据类型 bool, int, long, float, double, char, string, (null)
我们的数组和“对象”,没有专门的文本表达
数字呢,首先拒绝 0(digit) 这种表示法,其次是要支持 0x, 0b
浮点还是 Kotlin 那种 int.fraction 模式,但是暂不支持 exponents
字符串得支持 \"\'\t\b\n\r\$\\\uXXXX 以及 inline string
名字,暂时就是 [_A-Za-z] {[_A-Za-z0-9]},若只有 _ 构成则不可用

空格" \t\f"、换行"\n\r"、可嵌套注释“”

好,那么先解决这些的读取问题, 再来谈更高层的结构读取。
/tmp/duangsuse.sock
这张是原来的设计。 就先这么规定,字面数据类型 bool, int, long, float, double, char, string, (null) 我们的数组和“对象”,没有专门的文本表达 数字呢,首先拒绝 0(digit) 这种表示法,其次是要支持 0x, 0b 浮点还是 Kotlin 那种 int.fraction 模式,但是暂不支持 exponents 字符串得支持 \"\'\t\b\n\r\$\\ 和 \uXXXX 以及 inline string 名字,暂时就是 [_A-Za-z] {[_A…
我来发表下看法哈。

这个 0x 0b 的数值,以及对 01 这种的检查,是昨天解决了的

// 0x / 0b / 123
val zeroNotation = Decide(
hexPart prefix item('x'),
binPart prefix item('b'),
Peek(!digit) { if (peek == '0') takeIfStickyEnd(-1) else 0 }.clamWhile(digit, 0, "no octal notations")
)


至于 true 和 null 这些关键字怎么解决呢,它们是和 apples, list 这类的名字一起出现的
可以用字典树,我们为了解析这个专门弄了 TrieReplace<V>,可以实现 true 和 Name 的。

至于关键字和空格呢,有 ws 定义的先例嘛,关键字也可以用 KeywordPattern
其实我们的 MiniScheme 的语言表达式设计是很克制的,连函数调用和结构定义的空格都用 () [] 区分开了,所以不存在 keyword 和动态生成值的问题,大胆干吧

至于递归解析拿不到引用的问题,不是有 Deferred 么
已经就此问题提出解决
ParserKt 的 rebuild 这个特性在处理数值的时候真是让人又爱又恨
不 Un 了不 Un 了
This media is not supported in your browser
VIEW IN TELEGRAM
ParserKt 唯一的好处可能就是代码复用了,PKT 的代码复用真是相当优秀,而且没有性能问题
比其它递归下降组合子又多了 rebuild 和 clam 和 tuple 什么的
fun digitsIn(range: CharRange, padding: Int = 0)
= Convert(elementIn(range), { it-range.first+padding }, { range.first+(it - padding) })
val binDigit = digitsIn('0'..'1')
val decDigit = digitsIn('0'..'9')

val hexDigitLo = digitsIn('a'..'f', padding = 10)
val hexDigitUp = digitsIn('A'..'F', padding = 10)
val hexDigit = DecideUn(decDigit, hexDigitUp, hexDigitLo) { if (it in 0..9) 0 else 1 }

fun asLong(radix: Int, initial: Long = 0L) = JoinFold(initial) { this*radix + it }
fun integralFor(digit: Pattern<Char, Int>, repr: IRepr): Pattern<Char, Integral>
= Convert(Repeat(asLong(repr.radix), Convert(digit, Int::toLong))) { Integral(it, repr) }

val binPart = integralFor(binDigit, IRepr.Bin)
val decPart = integralFor(decDigit, IRepr.Dec)
val hexPart = integralFor(hexDigit, IRepr.Hex)
又失败了,但是获得了一点经验和进步……
ParserKt 的 rebuild,即便现在有特别的兼容单向 read-only patterns,真的对设计来说有很大的影响啊
因为就创作者我来说,设计的时候会自觉地实现 unfold, undecide,即便那是没有意义的,一旦失败会对心情有很大的影响
Forwarded from Deleted Account
sealed class Sexp { data class Term(val name: String): Sexp(); data class Nest(val list: List<Sexp>): Sexp() }
lateinit var sexp: Pattern<Char, Sexp>
val str = Until(elementIn(' ', *parens.items()), asString(), anyChar)
val atom = Convert(str) { Sexp.Term(it) }
val nestItems = SurroundBy(parens.asPat(), JoinBy(item(' '), Deferred{sexp}).ignoreSecond())
val nest = Convert(nestItems) { Sexp.Nest(it) }
sexp = Decide(nest, atom)
Forwarded from Deleted Account
就这一点代码我居然写了半个小时还面向 REPL 编程,还发现了框架 toString 的一个 bug……
('('{('('{(recursive)...' '}')'|(anyItem)~(' '|'('|')'))...' '}')'|(anyItem)~(' '|'('|')'))
Deleted Account
sealed class Sexp { data class Term(val name: String): Sexp(); data class Nest(val list: List<Sexp>): Sexp() } lateinit var sexp: Pattern<Char, Sexp> val str = Until(elementIn(' ', *parens.items()), asString(), anyChar) val atom = Convert(str) { Sexp.Term(it)…
今天晚上,我还会完成文法布局的 Pattern 编写

可以认为,ParserKt 现在对 read-only pattern 和序列 validate 的支持已经比较完备了
对于文法布局的支持应该会像对 infix chain 的一样,不会有问题