#js #dom #parsing 提问: DOM 里如何拿到 <h1>~<h6> 标题树?
假设所有 heading 都在
和解析 #Python, yaml 的缩进实质相同,我给两种方法(递归层宽、Int栈循环)
输出类似
算法对输入数据的抽象有点问题,关键点两个:
1. 何时解析一个子节点(上面 "## b")
2. 获取头部深度及建设每层
和 Python 解析的主要区别在于:
1. 在解析非 <hN> 项时不需要取其深度
2. 没有 : 后无换行的“单行简写”(可选 : layout) 的说法
但是我们仍然会写兼容 Python 缩进解析的代码,用抽象层掩盖 DOM 的对非 <hN> 元素深度(因无此概念)的不处理。
畸形的基础抽象:
0. 实现最大的要点是:仅需过一遍,但内部元素皆可能“跌破”两层嵌套,需要级联化处理层结束的逻辑、终末项的实际属从层;
此外第一层是特殊的——它无需 heading 开头,但内部模式和前者一致。
1. 建设每层子树结构不需要提供函数值,统一存储形式允许完后重赋值即可
2. 可以提供
递归层宽: #js #code
(补充:算法我都写出来了,调试了很久,待会贴链接)
Int栈算法:
其实就是比较骚的循环显式栈化重写
本身也不是什么复杂的算法(真正“复杂”的在于如何设计高性能、易组合的复用架构),分词器层面处理就只能用栈,然后业界主流实现是转化成 internal 的 END 词条然后交给 yacc 一样的状态机,把嵌套结构解析第二遍。
老ParserKt 的实现是 LayoutPattern (不如 fastparse 的
以上
假设所有 heading 都在
document.body.children
里和解析 #Python, yaml 的缩进实质相同,我给两种方法(递归层宽、Int栈循环)
输出类似
["# a", e2, e3, ["## b", ee2], e5]
这种算法对输入数据的抽象有点问题,关键点两个:
1. 何时解析一个子节点(上面 "## b")
2. 获取头部深度及建设每层
[head, *items]
的函数和 Python 解析的主要区别在于:
1. 在解析非 <hN> 项时不需要取其深度
2. 没有 : 后无换行的“单行简写”(可选 : layout) 的说法
但是我们仍然会写兼容 Python 缩进解析的代码,用抽象层掩盖 DOM 的对非 <hN> 元素深度(因无此概念)的不处理。
畸形的基础抽象:
var lastHDepth = 0/*当前文段层深度*/;实现的一些细节:
const RE_HTAG = /H(\d+)/g
, isHeading=(e) => RE_HTAG.test(e.tagName)
, getHeadingDepth=(e) => { var n=parseInt(RE_HTAG.exec(e.tagName)[1]); lastHDepth=n+1; return n; }
, getElementDepth=(e) => lastHDepth;
0. 实现最大的要点是:仅需过一遍,但内部元素皆可能“跌破”两层嵌套,需要级联化处理层结束的逻辑、终末项的实际属从层;
此外第一层是特殊的——它无需 heading 开头,但内部模式和前者一致。
1. 建设每层子树结构不需要提供函数值,统一存储形式允许完后重赋值即可
2. 可以提供
onXXX()
函数值检查缩进深度步进是否合法递归层宽: #js #code
(补充:算法我都写出来了,调试了很久,待会贴链接)
Int栈算法:
其实就是比较骚的循环显式栈化重写
本身也不是什么复杂的算法(真正“复杂”的在于如何设计高性能、易组合的复用架构),分词器层面处理就只能用栈,然后业界主流实现是转化成 internal 的 END 词条然后交给 yacc 一样的状态机,把嵌套结构解析第二遍。
老ParserKt 的实现是 LayoutPattern (不如 fastparse 的
" ".rep(indent+1).map(_.len).flatMapX(new Layout(i).factor.rep(1, sep = ("\n"+" "*i))
)
方便),写第一遍看起来易用性还不好;当然,这是个泛用 #algorithm ,功能根本不止解析人类易读嵌套结构。以上
GitHub
ParserKt/ParserKt
Naive one-pass recursive descent, scannerless parser framework for Kotlin - ParserKt/ParserKt
deep.html
2.1 KB
#HTML #code #parsing #algorithm 本以为很快就行的,结果想了半天调试了半天😂,最后一个不是因为十进制移位和数据视口费时,反而是 tailcall 循环忘了加 return,真是眼高手低啊
duangsuse::Echo
#js #dom #parsing 提问: DOM 里如何拿到 <h1>~<h6> 标题树? 假设所有 heading 都在 document.body.children 里 和解析 #Python, yaml 的缩进实质相同,我给两种方法(递归层宽、Int栈循环) 输出类似 ["# a", e2, e3, ["## b", ee2], e5] 这种 算法对输入数据的抽象有点问题,关键点两个: 1. 何时解析一个子节点(上面 "## b") 2. 获取头部深度及建设每层 [head, *items] 的函数…
ParserKt 的新简单版(因为之前说的又懒得写了...正好做个实用的子集 特性未必少) 估计会支持很甜但低开销的缩进 Block 支持,此外 operator parsing 也改进了贼多,从未深化制度的二叉树转为亲自管理逆波兰 List 惰性结构了(因为这次重设,leftRec 左递归最终还没出现就退役了…… 我们怀念它)
(另:冰封哥在上面引用的文章里说 Python 不支持多行 lambda 是因为 Pyteam 的人不了解如何解析可选 layout block,我不太赞同他,多行 lambda 在表达式,和 if: while: 等语句有点区别 会有碍排版整齐性,这点不少圈内人也认同) #plt #ce #parsing
待会这个 html 和昨天要重写的弄完了,就说说新版如何完整支持各种工业语言的解析,以及如何与编辑器建桥代码高亮。
(另:冰封哥在上面引用的文章里说 Python 不支持多行 lambda 是因为 Pyteam 的人不了解如何解析可选 layout block,我不太赞同他,多行 lambda 在表达式,和 if: while: 等语句有点区别 会有碍排版整齐性,这点不少圈内人也认同) #plt #ce #parsing
待会这个 html 和昨天要重写的弄完了,就说说新版如何完整支持各种工业语言的解析,以及如何与编辑器建桥代码高亮。
#parsing #Python #regex #dontknow 感觉有一定价值,但一般 Kotlin,Py,JS 里都有 raw string 能解决转义符冲突
https://tttttt.me/py_zh_real/13697
https://tttttt.me/py_zh_real/13697
Telegram
eW91dHUuYmUvZFF3NHc5V2dYY1EK in Python 交流群
\.换成[.]可读性更高
#Java #serialize #parsing, [18.01.21 10:11]
chen leiothrix: json反序列化的时候,有key对应两种不同结构有什么办法能针对性读取吗
捏造的信仰: [In reply to chen leiothrix]
这种情况的原因是类型信息缺失。如果你用 Jackson 可以看这篇 https://segmentfault.com/a/1190000023218408
ヾ(^▽^*)))Sam: 这种你的分别处理
要根据value值去if else
没啥好办法
I lluZ: 是的,直接当 map 处理,没法反序列化成一个 List<POJO>
ヾ(^▽^*)))Sam: list不行,因为你的数组不属于同一个类型无法搞
chen leiothrix: json反序列化的时候,有key对应两种不同结构有什么办法能针对性读取吗
捏造的信仰: [In reply to chen leiothrix]
这种情况的原因是类型信息缺失。如果你用 Jackson 可以看这篇 https://segmentfault.com/a/1190000023218408
ヾ(^▽^*)))Sam: 这种你的分别处理
要根据value值去if else
没啥好办法
I lluZ: 是的,直接当 map 处理,没法反序列化成一个 List<POJO>
ヾ(^▽^*)))Sam: list不行,因为你的数组不属于同一个类型无法搞
Telegram
ヾ(^▽^*)))Sam in Java 编程语言
要根据value值去if else
duangsuse::Echo
https://github.com/ice1000/jimgui/blob/master/core/test/org/ice1000/jimgui/tests/Demo.java ... 看了以后我对冰封哥的审美有点失望 虽然这只是一个直接的重写,我看出 jimgui 没有比 ImGui 本身更高的封装,它仅以 add container 的方式暴露了 tree ,这不符合之前写 TkGUI 时我的期望。 这里也有一个 initNewFrame + listen keyEvent & StringBuilder…
吃饭的路上(最近有点劳累过度了,思量着 ANSI BadApple 赶紧结束休息几天吧),谈到所谓“优雅性”,想了一下 ParserKt 新 LexerFeed 的问题,感觉很 complicated ,流对象的各种属性真的不好办
首先是说这个给冰封提到底有没有意义的问题(毕竟 PM 冰封是一个比较要心理准备的事情,心理难度比与 Python 红姐、九月姐 谈笑风生不低多少),最后结论是有。
虽然 jimgui 的本意未必是做“定义式”的 GUI 框架,更像是学习 JNI 设计,而且 Kotlin wrapper 很可能会有好的接口,技术交流也是不应有太多压力的。
TkGUI 的代码生成方法利用了 Python 无编译期/运行期,虚拟机相关组件基本可用的动态性,以及动态类型;很难(或者说意义不大)移植到 Java ,但我的本意是 GUI 可以这么写, ImGui 的做法可以说是业界惯例(就我的观察, GTK, Wx 的大部分封装不需要为子控件选择 parent, 但没有一个支持树形代码定义一个视图,即便其语言有足够表现力),Java 的 Swing Frame,Panel 和 Fx Stage,Scene,Group 都必须用 mutate 对象的方法「创建」模板化的视图树(当然这是过程式的自然映照,无可厚非), Qt 和 C#, VB 有 uic 这样的 code generator ;而 TkGUI 的 way 更像是 parser combinator 那样,尽可能少用外部工具,直接在语言里组合。
这个 way 就是一句话,“优美的代码能直观地反映它所处理数据的结构”,程序结构和数据结构相互照应、谐调统一,虽然会有额外开销,但一件事情只有你重视了才能找到各方面的最优解决办法,否则就永远只是传说。
再谈 ParserKt 的问题,其实最初版本相较于一些同类已经可以算是优雅了(当然离我想的还更远)
几个月前的重计划里包含了“削除 Parser 里 Lexer 相关代码”的改动,可以说是解决了我心头一厌(很多 PEG 生成器都逃不开跳空格注释的问题,要么然写文法里,要么然走 lexer/parser 的老路,要么然可配置性不够好,这是比较草的,因为我觉得在 a b c “按顺序”模式里默认插跳空格的逻辑是接近正解的)
具体实现还算好, Lexer/Parser 的区分、 Token 而非 Char 流的存在,核心原因是空格和注释对语法结构是无效的——最好能无视,免得解析器混杂
scannerless parser 很好,但跳空格其实有更容易的解决方法——为 Input stream 添加 filter ,到底还是 java 那一套自由组合的 stream 最好,连 skipped whitespaces 以及 AST element spans 它都可以往
核心思想容易,实现上也有些问题—— Lexer 和 parser 在最近的语言里越来越模糊了,你可以看到 KotlinLexer 里会处理一些嵌套问题(就需要 push/pop state number 了),而且
这么做势必造成计算力的浪费(分词器和解析器对同一份数据做了类似的动作——检查它的嵌套结构),以及编程的冗余、重复代码,是应该努力避免的。
解析器与“分词器”之间的交流,显然是 parser combinator 的优势——它们的结构对程序员是完全透明的,可以自由定义、随意组合,让 Parser 去驱动其输入流上的 Lexer ,告诉分词器现在是什么状态,需不需要跳空格(例如 "" 里就不能跳);分词器是一个针对
有的观众就会问了:这么好的方法,比你高到不知哪里去的聪明人可多了,怎么就你想出来?
首先,不能说是没人想,要看编程实践怎么用、怎么组合这些技巧,不是说你去做了,效果就真的能像想象的那样好
其次,如果你没把代码重写 9遍,也容易被 Lexer/parser 和 scannerless 的那群既有实践误导,以为必须有 tokenizer ,或者流只能是一层,不能有“滤过”操作的
如果被动性[2](非阻塞,要不然无法共享 string 等词法的定义)以及 Parser 对其的主动性(传递在解析词条类型号)不能被保证, 许多人对输入字符序列的抽象不够灵活(万恶之源),使得他们不能够发现这一点。 (所以你在编程的时候,记得重复的少写一点、稀奇的功能特性多写一点,说不定还能帮助你对程序模型整体的理解)
(这种设计也很好的发扬了 ParserKt 的 one-pass 设计,而 C 系语言 // /* 注释与除号的区分早有给
但这个封装有很大问题—— ParserKt 最初只有
尽管这是根基(SliceFeed, Iterator/ReaderFeed 子类),它也是不切实际的,所以很快有了
而那些接收 Input 的 Input ,就只能用一个代理(delegate)类
如果说你组织流嵌套的方法是手工的,应该不需要滥用多态去做“动态类型”,又或者是自动的——真的到那种“可组合”的地步吗?
最后我觉得,还是做则不能打破 Lexer 需求 Input (SourceLocated) 的类型, 还是取消这样的限制吧…… 真不知该怎样解决这问题 #parser #parsing #learn #Kotlin #project #suggest
[^1] 现在我更倾向
isCompleteRead 是重新建模的(结果存逆波兰栈的)算符链解析器需要的,在非 complete read 时,可以像 Lua 一样直接进行简单的常量折叠,否则不仅不能折叠,还要存语法元素行号、前部空格等(重现原文所需的)信息
[^2] 其实我理解错了,这也是因为 LexerFeed 最开始是能自动识别底层输入的状态机,上级请求字符时肯定是要 blocking consume 直到非空格字符的,所谓非阻塞是因为对非空格单个字符它照样要处理状态转移;现在我倾向把它做成“能暂时屏蔽的自动 ws skip”一些,因为这才能真正统一复用文法/词法规则 ,虽然那样就没有花里胡哨的
首先是说这个给冰封提到底有没有意义的问题(毕竟 PM 冰封是一个比较要心理准备的事情,心理难度比与 Python 红姐、九月姐 谈笑风生不低多少),最后结论是有。
虽然 jimgui 的本意未必是做“定义式”的 GUI 框架,更像是学习 JNI 设计,而且 Kotlin wrapper 很可能会有好的接口,技术交流也是不应有太多压力的。
TkGUI 的代码生成方法利用了 Python 无编译期/运行期,虚拟机相关组件基本可用的动态性,以及动态类型;很难(或者说意义不大)移植到 Java ,但我的本意是 GUI 可以这么写, ImGui 的做法可以说是业界惯例(就我的观察, GTK, Wx 的大部分封装不需要为子控件选择 parent, 但没有一个支持树形代码定义一个视图,即便其语言有足够表现力),Java 的 Swing Frame,Panel 和 Fx Stage,Scene,Group 都必须用 mutate 对象的方法「创建」模板化的视图树(当然这是过程式的自然映照,无可厚非), Qt 和 C#, VB 有 uic 这样的 code generator ;而 TkGUI 的 way 更像是 parser combinator 那样,尽可能少用外部工具,直接在语言里组合。
这个 way 就是一句话,“优美的代码能直观地反映它所处理数据的结构”,程序结构和数据结构相互照应、谐调统一,虽然会有额外开销,但一件事情只有你重视了才能找到各方面的最优解决办法,否则就永远只是传说。
再谈 ParserKt 的问题,其实最初版本相较于一些同类已经可以算是优雅了(当然离我想的还更远)
几个月前的重计划里包含了“削除 Parser 里 Lexer 相关代码”的改动,可以说是解决了我心头一厌(很多 PEG 生成器都逃不开跳空格注释的问题,要么然写文法里,要么然走 lexer/parser 的老路,要么然可配置性不够好,这是比较草的,因为我觉得在 a b c “按顺序”模式里默认插跳空格的逻辑是接近正解的)
具体实现还算好, Lexer/Parser 的区分、 Token 而非 Char 流的存在,核心原因是空格和注释对语法结构是无效的——最好能无视,免得解析器混杂
scannerless parser 很好,但跳空格其实有更容易的解决方法——为 Input stream 添加 filter ,到底还是 java 那一套自由组合的 stream 最好,连 skipped whitespaces 以及 AST element spans 它都可以往
Map<K,V>
存储好了,这就同时解决了 AST data class 不好写的问题,在不必使用这些信息时,也提升了性能,就从根源上解决了许多联带(代码复用、类型冗余和构造器隐式参数、分词解析器如何相互协调的)问题。核心思想容易,实现上也有些问题—— Lexer 和 parser 在最近的语言里越来越模糊了,你可以看到 KotlinLexer 里会处理一些嵌套问题(就需要 push/pop state number 了),而且
>=
与 fun():P<T>=
的区分也使得它必须识别一些本该由文法处理的模式——在过去这是不可想象的,C 的词法规则相当简单这么做势必造成计算力的浪费(分词器和解析器对同一份数据做了类似的动作——检查它的嵌套结构),以及编程的冗余、重复代码,是应该努力避免的。
解析器与“分词器”之间的交流,显然是 parser combinator 的优势——它们的结构对程序员是完全透明的,可以自由定义、随意组合,让 Parser 去驱动其输入流上的 Lexer ,告诉分词器现在是什么状态,需不需要跳空格(例如 "" 里就不能跳);分词器是一个针对
Feed
流的状态机,本身也是一个 Feed
,而 onChar
的时候被动进行状态转移,就可以 filter 掉那些解析器不想看的字符,同时也能选择性地保留(如语法高亮) 的数据,一举多得。有的观众就会问了:这么好的方法,比你高到不知哪里去的聪明人可多了,怎么就你想出来?
首先,不能说是没人想,要看编程实践怎么用、怎么组合这些技巧,不是说你去做了,效果就真的能像想象的那样好
其次,如果你没把代码重写 9遍,也容易被 Lexer/parser 和 scannerless 的那群既有实践误导,以为必须有 tokenizer ,或者流只能是一层,不能有“滤过”操作的
如果
LexerFeed
的(这种设计也很好的发扬了 ParserKt 的 one-pass 设计,而 C 系语言 // /* 注释与除号的区分早有给
InfixPattern
扫描操作符的 TriePattern
专定子类可轻易完成,PKT 的组合性不加盖的)但这个封装有很大问题—— ParserKt 最初只有
Feed { val peek; fun consume() }
,不像一些 nextChar()
或 curChar()
数据视口不一致、命名迷惑的框架,它的流模型只允许程序员着眼一项(最本质的问题),结束时抛 Feed.End
异常尽管这是根基(SliceFeed, Iterator/ReaderFeed 子类),它也是不切实际的,所以很快有了
Input(s: Feed): Feed, SourceLocated, ErrorHandler
[1],以及一大堆 Feed
上试着 (this as Input)
的扩展函数,允许解析器带行号,尽量减小开销(统计行号信息是要在 Char 输入上,而一些输入根本无需 Input 的一些成员)而那些接收 Input 的 Input ,就只能用一个代理(delegate)类
Input.By
去 proxy 这 underlying stream 实现的一些特性,这种问题严重后有点像“责任链”的字面含义——不断尝试 unwrap 一个 (可能是Input的)Feed ,寻找某个 trait 的实现者。如果说你组织流嵌套的方法是手工的,应该不需要滥用多态去做“动态类型”,又或者是自动的——真的到那种“可组合”的地步吗?
最后我觉得,还是做
LexerInput(s:Input): Input.By
比较好,这样 LexerInput(Input(s=SliceFeed(Slice("wtf") )))
这样的二层就会成为必要的组合法,如果需要其他层,[^1] 现在我更倾向
Input: Feed, FeedControl, SourceLocated { val states:Map<String,Any>; val onError; val isCompleteRead:Boolean }
isCompleteRead 是重新建模的(结果存逆波兰栈的)算符链解析器需要的,在非 complete read 时,可以像 Lua 一样直接进行简单的常量折叠,否则不仅不能折叠,还要存语法元素行号、前部空格等(重现原文所需的)信息
[^2] 其实我理解错了,这也是因为 LexerFeed 最开始是能自动识别底层输入的状态机,上级请求字符时肯定是要 blocking consume 直到非空格字符的,所谓非阻塞是因为对非空格单个字符它照样要处理状态转移;现在我倾向把它做成“能暂时屏蔽的自动 ws skip”一些,因为这才能真正统一复用文法/词法规则 ,虽然那样就没有花里胡哨的
List<Triple<Char,Int,Int>>
了(毕竟有效性在那)GitHub
ParserKt/ParserKt
Naive one-pass recursive descent, scannerless parser framework for Kotlin - ParserKt/ParserKt
Forwarded from duangsues.is_a? SaltedFish
#cplusplus #English #PLT #ce #parsing #llvm https://zhuyi.fan/post/write-a-bf-compiler-with-joy.html
🌝🌚 看来是 CS ,爱了爱了
https://raptazure.github.io/posts/purs-react/ #functional #JS #tt #English 草这又是个大佬... 类型论大佬都喜欢英语
#oi #school #life 这位同学亲切一点,好像还在学德语🤔
🌝🌚 看来是 CS ,爱了爱了
https://raptazure.github.io/posts/purs-react/ #functional #JS #tt #English 草这又是个大佬... 类型论大佬都喜欢英语
#oi #school #life 这位同学亲切一点,好像还在学德语🤔
zhuyi.fan
Write a BF Compiler with Joy
Post Write a BF Compiler with Joy of Personal Blog: Schrodinger's Utopia. Discuss about codegen, esolang, llvm, parser, peg, programming here!
列一些有趣的社区项目 #math #listing #Java
https://www.desmos.com/calculator/i6fijibmbz
#GUI 系列:
https://github.com/darsam44/Mini-desmos (吐嘈: 真的不迷你)
https://github.com/DanielZhangD/Javmos
https://github.com/LitterallyTheCoolestGuy69/Desmos-But-Scuffed
#Python 转换/等式代码生成脚本系列:
https://github.com/MrNewdary/svg2desmos/blob/main/svg2desmos.py
https://github.com/anematode/parametrizer/blob/master/undeletable.py
https://github.com/allesspassig/despy/blob/master/despy.py
https://github.com/emily-yu/image-to-desmos OpenCV #cv
#music https://github.com/AlexApps99/MIDI2Desmos 听 MIDI 函数图系列...
多项式课系列:
https://github.com/galbar07/Desmos
https://github.com/yonatan555/Desmos-Polynom
https://github.com/JiangTianXiang/Grade-12-Calculus-Graphing-Calculator
https://github.com/WhoIsKatie/Javmos
https://github.com/TimChoy/javmos
https://github.com/DvirTomer/Desmos-Polynom
乱入:
https://github.com/andrewpareles/Calculator/blob/master/main.ml
https://github.com/Tuttivers/ExponentialSeekbar-sample/blob/master/NearMeSeekBar.kt#L75 #Kotlin #Android
https://mukunthag.github.io/SHM/ 振荡器什么的...
https://github.com/Rob--/root-approximations/blob/master/evaluatex.js#L190 #JavaScript #lib #parsing 几百行的符号代数系统...
可移植性/项目管理极差的 GUI:
https://github.com/Pi-Man/Graphing-Calculator/tree/master/Graphing-Calculator
https://github.com/RohanK22/cppmathtool
http://well-made-territory.surge.sh/Desmos.html
https://github.com/softchickenidiot/3D-Grapher/tree/master/3D Grapher
https://www.desmos.com/calculator/i6fijibmbz
#GUI 系列:
https://github.com/darsam44/Mini-desmos (吐嘈: 真的不迷你)
https://github.com/DanielZhangD/Javmos
https://github.com/LitterallyTheCoolestGuy69/Desmos-But-Scuffed
#Python 转换/等式代码生成脚本系列:
https://github.com/MrNewdary/svg2desmos/blob/main/svg2desmos.py
https://github.com/anematode/parametrizer/blob/master/undeletable.py
https://github.com/allesspassig/despy/blob/master/despy.py
https://github.com/emily-yu/image-to-desmos OpenCV #cv
#music https://github.com/AlexApps99/MIDI2Desmos 听 MIDI 函数图系列...
多项式课系列:
https://github.com/galbar07/Desmos
https://github.com/yonatan555/Desmos-Polynom
https://github.com/JiangTianXiang/Grade-12-Calculus-Graphing-Calculator
https://github.com/WhoIsKatie/Javmos
https://github.com/TimChoy/javmos
https://github.com/DvirTomer/Desmos-Polynom
乱入:
https://github.com/andrewpareles/Calculator/blob/master/main.ml
https://github.com/Tuttivers/ExponentialSeekbar-sample/blob/master/NearMeSeekBar.kt#L75 #Kotlin #Android
https://mukunthag.github.io/SHM/ 振荡器什么的...
https://github.com/Rob--/root-approximations/blob/master/evaluatex.js#L190 #JavaScript #lib #parsing 几百行的符号代数系统...
可移植性/项目管理极差的 GUI:
https://github.com/Pi-Man/Graphing-Calculator/tree/master/Graphing-Calculator
https://github.com/RohanK22/cppmathtool
http://well-made-territory.surge.sh/Desmos.html
https://github.com/softchickenidiot/3D-Grapher/tree/master/3D Grapher
Desmos
Final Project
#web #js #dalao #friend https://www.yunyoujun.cn/posts/make-an-avg-engine/
我觉得这个大佬比较亲切,或许以后会有机会接触? 🤔
动苏一贯喜欢风格清新、为人友善开放乐于表达的大佬
虽然看起来这个大佬还在发展阶段,相信我也有可以从中学习的地方
https://github.com/YunYouJun/advjs/blob/main/packages/parser/src/index.ts #TypeScript #parsing 这个大佬也有设计“基于 Markdown 的语言”的想法 😂
我觉得这个大佬比较亲切,或许以后会有机会接触? 🤔
动苏一贯喜欢风格清新、为人友善开放乐于表达的大佬
虽然看起来这个大佬还在发展阶段,相信我也有可以从中学习的地方
https://github.com/YunYouJun/advjs/blob/main/packages/parser/src/index.ts #TypeScript #parsing 这个大佬也有设计“基于 Markdown 的语言”的想法 😂
云游君的小站
ADV 游戏引擎计划
希望能成为一个有趣的人
#日常精神分裂 #parsing #JS #scheme
A: 之前说好了要写的 s-expr 解析器,看来是写不了了?还打算复用 JSON.parse 的,以及支持缩进布局,那样就会很有价值吧
B: 之前还打算支持 {;} 可选缩排的,发现和 data notation 侧冲突了,看来是眼高手低😂
A: 其实关键在于易实现性吧,你想用尽量少的代码和低层API实现给应用用的解释器,无论解析结果怎么用?
B: 对了,子序列法比流递归下降法代码量少吗?
A: 无论从什么角度看,加上对 JSON 子语言解析器的复用都不会更省啊……
S表达式是由 Atom/List 两种元素组成的嵌套表,或者说 值/调用参组 的树形列表,一般首项为函数值, 尾余为参数;是三十行以内能实现带调用和 (let 的 动态作用域版。
譬如在解析 () 里的 a b c 单项中,我们实际在读 SList 即 toplevel 的 Expr list ,假设 a 是另一个 () 则:
流递归下降从 ( 后再解析 SList ,它主动完结后刚好在 ) 闭处
无论是靠返回结束索引号的非规范递归下降还是 StringView substr 返回消耗/片段的皆此
子序列在 ( 处直接 findPairedIndex ,这个算法只需处理 "\"" 字符串然后取闭包含子串递归解析,不过这个扫码过程是没有缓存但只需计数开括号的,相对外部()会多数很多遍。
我可以觉得,不用流不等待「不知何处结束」的子串解析结果再检查闭括号较易理解,但是它实际做了无用功,调用栈还是那么高。
B: 就没有什么又易懂又简单的方法去递归下降吗?子序列真的有那么无用吗?
A: 我打算用 function 值把流建模成 s(0)==length, s(1)=="a", s(-1)(1)=="b" 这个样子,还算轻易。
JSON 静态变作流解析有方法,递进长度子串+检查异常pos取头 足矣,全长仍错时即无解析
递归下降如果不显式 substr 而是交 (共享/复制&同步) StrView 的话 #parser 的确对新手不好理解,但套路不复杂。
子序列的话我考虑了一下,如果我们采用复杂点的 visitor 去边解析边执行(自然也可存下再执行)是能实现 if 里兼容一侧语法错误的,显得很 Javascriptic 🌝
B: 很神奇,具体怎么做呢
A: 存参成树允许再遍历的 visitor 就不说,可以给部分递归 () 的 case 变成
其实我并不喜欢边解析边执行,只是有时候(比如 %s fmtstr 等)工作就是很死板所以无所谓了,况且这分块惰性解析涉及函数调用求值序的问题,那就是扯到函数抽象、词法作用域里的闭包 #ce #plt ,不简洁不能体现对灵活的嵌套处理过程的即时利用
A: 之前说好了要写的 s-expr 解析器,看来是写不了了?还打算复用 JSON.parse 的,以及支持缩进布局,那样就会很有价值吧
B: 之前还打算支持 {;} 可选缩排的,发现和 data notation 侧冲突了,看来是眼高手低😂
A: 其实关键在于易实现性吧,你想用尽量少的代码和低层API实现给应用用的解释器,无论解析结果怎么用?
B: 对了,子序列法比流递归下降法代码量少吗?
A: 无论从什么角度看,加上对 JSON 子语言解析器的复用都不会更省啊……
S表达式是由 Atom/List 两种元素组成的嵌套表,或者说 值/调用参组 的树形列表,一般首项为函数值, 尾余为参数;是三十行以内能实现带调用和 (let 的 动态作用域版。
譬如在解析 () 里的 a b c 单项中,我们实际在读 SList 即 toplevel 的 Expr list ,假设 a 是另一个 () 则:
流递归下降从 ( 后再解析 SList ,它主动完结后刚好在 ) 闭处
无论是靠返回结束索引号的非规范递归下降还是 StringView substr 返回消耗/片段的皆此
子序列在 ( 处直接 findPairedIndex ,这个算法只需处理 "\"" 字符串然后取闭包含子串递归解析,不过这个扫码过程是没有缓存但只需计数开括号的,相对外部()会多数很多遍。
我可以觉得,不用流不等待「不知何处结束」的子串解析结果再检查闭括号较易理解,但是它实际做了无用功,调用栈还是那么高。
B: 就没有什么又易懂又简单的方法去递归下降吗?子序列真的有那么无用吗?
A: 我打算用 function 值把流建模成 s(0)==length, s(1)=="a", s(-1)(1)=="b" 这个样子,还算轻易。
JSON 静态变作流解析有方法,递进长度子串+检查异常pos取头 足矣,全长仍错时即无解析
递归下降如果不显式 substr 而是交 (共享/复制&同步) StrView 的话 #parser 的确对新手不好理解,但套路不复杂。
子序列的话我考虑了一下,如果我们采用复杂点的 visitor 去边解析边执行(自然也可存下再执行)是能实现 if 里兼容一侧语法错误的,显得很 Javascriptic 🌝
B: 很神奇,具体怎么做呢
A: 存参成树允许再遍历的 visitor 就不说,可以给部分递归 () 的 case 变成
()=>readList(s.substr(findPairedIndex(s,)))
闭包,然后参数求值(反正这语赋值处只有实参组) 时支持惰性求值的程序里兼容下先解析。其实我并不喜欢边解析边执行,只是有时候(比如 %s fmtstr 等)工作就是很死板所以无所谓了,况且这分块惰性解析涉及函数调用求值序的问题,那就是扯到函数抽象、词法作用域里的闭包 #ce #plt ,不简洁不能体现对灵活的嵌套处理过程的即时利用
https://github.com/emmetio/stream-reader #js #parsing
Emmetio 这个组织给了我一种很怀念的感觉。明明做过那么多,我却仍然不记得 () 用一个栈是该怎么解析的,貌似要手动维护栈顶被嵌套吧。
其实它做了那么多,我觉得影响也蛮大的,但 64 个项目它就只火了一个,但真的可以称之为前端码农与工程师的分界线,一个可以被称为『业界锚点』的项目,都是5年多前了,他用的一些 doc.fragment 这种 API 我都不熟悉。
你会发现整个社区基本都是一个人维护的,给人一种普通人历经挫折终于成功重构了自己和恶心的领域惯例的感觉。
ParserKt 是 peek&consume 的绝对纯字符流,可玩多了「魔法」和「极简」后我也想把 parser 的操作回归工程常规,毕竟它本来就是负责把 str 与 obj,list 数据对应的,不可能脱离工程逻辑风格,各种内部 API 上低限制多变量也值得尝试,能省代码量。
从项目名也能看到很多 expander, matcher, parser 和 binding,plugin; analyzer,resolver,formatter 等杂项工具
当然,其实他的技术也未必拔尖(😒可是对那些连 substr(i,n) slice(i0,i1) index 计算都不习惯的人来说这算是神), CSS 解析器只弄了数据侧框架(约等于没搞明白文本表示和程序/数据结构的关系),许多明明只是 snippet 级的算法还专门建立 repo 去存。
但是啊。
我真觉得这种「不务正业」但做到的事却最终从根本上影响了「正业」的人是很有趣的
至少他们是那种明白什么是重要,什么可以省略的人,在越来越嘈杂的 Web 这种心情很可贵。
我最近也在写一个 emet.js,当然它目前并没应用上取前缀解析子程序,祈祷我对所谓「模式」的理解能支持住它吧,当然,哪怕完全不用解析器技术单靠 API 设计我也能让 DOM/JS 更好融合在一起,可果然是新东西好玩一些啊。😋
Emmetio 这个组织给了我一种很怀念的感觉。明明做过那么多,我却仍然不记得 () 用一个栈是该怎么解析的,貌似要手动维护栈顶被嵌套吧。
其实它做了那么多,我觉得影响也蛮大的,但 64 个项目它就只火了一个,但真的可以称之为前端码农与工程师的分界线,一个可以被称为『业界锚点』的项目,都是5年多前了,他用的一些 doc.fragment 这种 API 我都不熟悉。
你会发现整个社区基本都是一个人维护的,给人一种普通人历经挫折终于成功重构了自己和恶心的领域惯例的感觉。
ParserKt 是 peek&consume 的绝对纯字符流,可玩多了「魔法」和「极简」后我也想把 parser 的操作回归工程常规,毕竟它本来就是负责把 str 与 obj,list 数据对应的,不可能脱离工程逻辑风格,各种内部 API 上低限制多变量也值得尝试,能省代码量。
从项目名也能看到很多 expander, matcher, parser 和 binding,plugin; analyzer,resolver,formatter 等杂项工具
当然,其实他的技术也未必拔尖(😒可是对那些连 substr(i,n) slice(i0,i1) index 计算都不习惯的人来说这算是神), CSS 解析器只弄了数据侧框架(约等于没搞明白文本表示和程序/数据结构的关系),许多明明只是 snippet 级的算法还专门建立 repo 去存。
但是啊。
我真觉得这种「不务正业」但做到的事却最终从根本上影响了「正业」的人是很有趣的
至少他们是那种明白什么是重要,什么可以省略的人,在越来越嘈杂的 Web 这种心情很可贵。
我最近也在写一个 emet.js,当然它目前并没应用上取前缀解析子程序,祈祷我对所谓「模式」的理解能支持住它吧,当然,哪怕完全不用解析器技术单靠 API 设计我也能让 DOM/JS 更好融合在一起,可果然是新东西好玩一些啊。😋
GitHub
GitHub - emmetio/stream-reader: Reads text as stream
Reads text as stream. Contribute to emmetio/stream-reader development by creating an account on GitHub.
duangsuse::Echo
#plt 呃,这几天眼睛有点疼,那个网页重构也接近尾声了(目的就是交个PR),马上把雄狮扭眼的”热度蹭完“,我就能开始二进制pybind了 ……但是到2月我就必须开始制作一个H5动画礼物,以现在这个效率…… (而且之前说的 Java 入门又鸽子了,尽管对话框和离线javac的问题解决,其他内容还是需费精力 说真的我没一次蹭上国内热度,因为每次都是我趁机学了些”没用的“(比如彩字符画、粒子动画、MBR程序、C指针和数组啦),然后数据不好看 😂 这次也是一样,我用shift重映射圆心距l=1~len 环上像…
我太阳,才发现这个别人能发博文的东西,我竟然连标题和名字都没起,试运行成功贴上就pass了…… 这不是在线教SICP(程序的构造和解释)吗🤪 #lisp #fp #zhihu #statement
放到以前我绝对搞大新闻一样,就像之前仿造(但也没成功)Lice 时专门建了项目画了logo,然后文档拼缀别人的,最后模板代码写完不会了 🙈
但说起来,元编程最后也不过是编程。你了解编程语言,很好,但语言只是载体,美丽的、各种各样的应用才是我们的最终目的。
你能写编译器,很好,但也不过是完成了文本模式和树遍历,加上一些理论。 编译器的中/后端分析优化 也是同样的处理流程,也有简单和最优的做法,「编译器」,对这个流程而言并不特殊。「编程」,对代码可变的计算机并不特殊。
就像让语言运行(尽管一些没执行序)于计算机的工具,也竟只不过是种应用,如果你了解可复用的前缀解析器:
#js #code #parsing
顺便一提: eCall 的首项其实不是
那么语言的实现,以及各种DSL(make,ant.xml) 与普通CLI程序(grep,sed,..)没啥不同。 得到了菜刀,就更要懂得取舍其能力。 菜刀不能用来干什么? 如果这么用,人多后风险是什么? 怎么最简及最优地添加功能? 这才是编程语言爱好者该思考的问题。 编程语言是更精确的自然语言,优化一篇文章和优化一段代码,是存在不少相似性的;编程和数学都能”提升思维“,但编程更擅长表达。表达也是智力。
解释或编译,JIT为REPL执行或动态优化,都是相同目标的不同选择,大同小异,关键在懂得它和已知知识的差异。
(补充: Fun,Call,var 在函数式一般称 abs,app,subst .当然王某那篇 就没有用这些稀奇名字. 我这里没有let-in 和 (+ 的 prim 操作,都是通过JS 函数相互引入。换Java用reflect也可
Java/Kt实现之所以长,是因为要强类型检查 而且fun eval() 和override啥的重复许多遍,语义上并没有新概念
C/Py实现之所以长,是在文法期(lex-yacc)和纸面推导磨叽太久、语言本身特性缺失(union:int nodeTag)和
工程界一般科普做个计算器(Node/队列指针)还是很直接的,可是不能表达变量和按语序参数,会造成很多问题(CSS支持变量后就变贼有用了)
毕竟大家开始学编程时都是按直觉的,
你把东西写长,不会让它更”生产“或”可配置“ ”易懂“;写短,不会”更快“或”有内涵“,语义不多不少,它就在那。我觉得这是仍没见过汇编的程序员该有的认识。不知道为什么,重视语义的人很少,仿佛世界上只有语法和”JSON,YAML“这些名字,而操作它们的库API也都是孤立的,并不存在一个”概念“把所有的一切语法和表象连起来。
举个例子,S表达式就能表示HTML🙃。有人想过拿JSON保存这个吧,但是因为含大量children:[]被怼,但S表达式
现在不少人就把它的影子当新DSL呢!我们是不是该说这是「历史倒流」呢🌝
也有许多往JS内嵌XML呢! 作为代码移植的好帮手,还真是十分有必要不独立转化而新建jsx语言呢,这样就能在单文件写html了不是?
语言对程序员来说并不遥远。它笼罩着编程的方方面面。
无论是以何种形式使用,对语言的理解决定程序员的能力,并不是做的事多了,就懂语言。
解释器实现不是不能自顶向下拆开讲,因为许多人某层面就知道那一种做法(比如刚才
另一方面咱领域人少,一些只顾自己写开心的魔法师(人和领域是互相选择的。冷门专业冷门人)就多些,真正做科普的就少
我们从小就被教导要努力向谁看齐、要按套路管理自己的生活乃至一生,要给各种技术排名次、造『鄙视链』,可是我看到许多Vlogger,每个人都有不同的经济条件、地理位置和性格,但真的无法把他们的视频风格分出高低谁谁淘汰,他们都能让你开阔眼界——普通的生活也能如此有意思,原来做记录也可以不像在记录,却达到更好效果。
确实,技术不是最难解决的问题;把眼光放开阔,许多问题或许就是人为制造,可以从更远的地方追溯修整方案呢! #recommended
谁告诉你 combinator 和 Maybe 及类型推导,跨编译就是函数式专属的(Kotlin),谁说逻辑式就必须复杂(miniKanren),谁说{}或end 最严谨(Python),Web怎么会只有”前端“功能呢(ES6+H5API)
如果世界上存在最优的编程语言——是哪个? 最简单的/功能最多的/最快的?
许多衡量标准本身就是冲突的,先有目的,然后才有最优解。 先懂为什么,然后才看做法
我们所学的知识和理论,有多少是罔顾了原因,只有做法和自恰性的? 文档并不是只有易理解与否,还有与现实、与其他的对应性,因为编程是一件实事,目的之下一切可替换的事。
到最后你才发现,根本不存在最优解,你所看到的优秀,不过是圈子里广为流传的假象。 世界上那么多人,所谓的大牛仍是天外有天,为什么你必须向他学习呢,难道你不能有比他做得好/做得广泛之处吗。
语言不重要,思想重要。
放下排名、放下”最佳实践“,做自己想做的
放到以前我绝对搞大新闻一样,就像之前仿造(但也没成功)Lice 时专门建了项目画了logo,然后文档拼缀别人的,最后模板代码写完不会了 🙈
但说起来,元编程最后也不过是编程。你了解编程语言,很好,但语言只是载体,美丽的、各种各样的应用才是我们的最终目的。
你能写编译器,很好,但也不过是完成了文本模式和树遍历,加上一些理论。 编译器的中/后端分析优化 也是同样的处理流程,也有简单和最优的做法,「编译器」,对这个流程而言并不特殊。「编程」,对代码可变的计算机并不特殊。
就像让语言运行(尽管一些没执行序)于计算机的工具,也竟只不过是种应用,如果你了解可复用的前缀解析器:
#js #code #parsing
feed=(s,i=0)=>d/*+peek -take*/=>{let q=d<0,r;if(q)d=-d;r=s.slice(i,i+d);if(q)i+=d; return r}
feed=(s,i=0)=>d=>d<0?(d=-d,s.slice(i,i+d,i+=d) ): s.slice(i,i+d) //返回前可加过滤空格(当前tok==0? 跳空格)和'\n'数行号
sign=s=>{let k=s(1),i; if(-1!= (i="+-正负".indexOf(k)) )return i%2==1}
num=s=>{let n=0,di;for(;/\d/.test(di=s(1));)n=n*10+(s(-1)-'0'); return n} //可以用-0 确保for至少有1次.
Seq=(...ps)=>s=>{let a=[],p;for(p of ps){r=p(s);if(!r)break;a.push(r)} return a}
pSelf=pOf=>{let p=s=>p(s); p.give=(P=pOf(p))=>p=P; return p}//wait give
"+123 负3 正2 -1".split(' ').map(code=>
Seq(sign,num)(feed(code)) )
呃,测试就不做了,大家作为小练习吧(反正外面也没讲的,不信你搜(顺便一提: eCall 的首项其实不是
d[kf]
,能继续(yes?fa:fb)(1)
,这也是个易混点。 let x=1 in e 与 ((\x. e) 1) 不完全一样,前者不涉及”函数作值“那么语言的实现,以及各种DSL(make,ant.xml) 与普通CLI程序(grep,sed,..)没啥不同。 得到了菜刀,就更要懂得取舍其能力。 菜刀不能用来干什么? 如果这么用,人多后风险是什么? 怎么最简及最优地添加功能? 这才是编程语言爱好者该思考的问题。 编程语言是更精确的自然语言,优化一篇文章和优化一段代码,是存在不少相似性的;编程和数学都能”提升思维“,但编程更擅长表达。表达也是智力。
解释或编译,JIT为REPL执行或动态优化,都是相同目标的不同选择,大同小异,关键在懂得它和已知知识的差异。
(补充: Fun,Call,var 在函数式一般称 abs,app,subst .当然王某那篇 就没有用这些稀奇名字. 我这里没有let-in 和 (+ 的 prim 操作,都是通过JS 函数相互引入。换Java用reflect也可
Java/Kt实现之所以长,是因为要强类型检查 而且fun eval() 和override啥的重复许多遍,语义上并没有新概念
C/Py实现之所以长,是在文法期(lex-yacc)和纸面推导磨叽太久、语言本身特性缺失(union:int nodeTag)和
__init__
这种,而且但凡是个公开lib作者都爱过度设计(overdesign),很难写简洁的parser工程界一般科普做个计算器(Node/队列指针)还是很直接的,可是不能表达变量和按语序参数,会造成很多问题(CSS支持变量后就变贼有用了)
毕竟大家开始学编程时都是按直觉的,
int n; new ListSeter(){ void f(List a){a[0]=n;} }
里new了的Type实质是函数(SAM单方法接口),而SAM实质又是包含n和算式的数据(闭包),for(i0;i<;i++)
是 for(i in 0..N)
这样都没想过吧。 框架定义,我就用,这是外国 Java 在 Kotlin 出现后如此被动的原因。 😅你把东西写长,不会让它更”生产“或”可配置“ ”易懂“;写短,不会”更快“或”有内涵“,语义不多不少,它就在那。我觉得这是仍没见过汇编的程序员该有的认识。不知道为什么,重视语义的人很少,仿佛世界上只有语法和”JSON,YAML“这些名字,而操作它们的库API也都是孤立的,并不存在一个”概念“把所有的一切语法和表象连起来。
举个例子,S表达式就能表示HTML🙃。有人想过拿JSON保存这个吧,但是因为含大量children:[]被怼,但S表达式
(div.wtf (id xx) (a (href xx title 上级))
就能表示HTML-DOM。现在不少人就把它的影子当新DSL呢!我们是不是该说这是「历史倒流」呢🌝
也有许多往JS内嵌XML呢! 作为代码移植的好帮手,还真是十分有必要不独立转化而新建jsx语言呢,这样就能在单文件写html了不是?
语言对程序员来说并不遥远。它笼罩着编程的方方面面。
无论是以何种形式使用,对语言的理解决定程序员的能力,并不是做的事多了,就懂语言。
解释器实现不是不能自顶向下拆开讲,因为许多人某层面就知道那一种做法(比如刚才
zipMap
我不提出来 理解难度就++, 或者我写一大堆XXNode, 人也get不到调用和查变量的重点),他觉得无可替换(或者”这就是最快的“),而篇幅又巨大,对初学者会非常不友好另一方面咱领域人少,一些只顾自己写开心的魔法师(人和领域是互相选择的。冷门专业冷门人)就多些,真正做科普的就少
我们从小就被教导要努力向谁看齐、要按套路管理自己的生活乃至一生,要给各种技术排名次、造『鄙视链』,可是我看到许多Vlogger,每个人都有不同的经济条件、地理位置和性格,但真的无法把他们的视频风格分出高低谁谁淘汰,他们都能让你开阔眼界——普通的生活也能如此有意思,原来做记录也可以不像在记录,却达到更好效果。
确实,技术不是最难解决的问题;把眼光放开阔,许多问题或许就是人为制造,可以从更远的地方追溯修整方案呢! #recommended
谁告诉你 combinator 和 Maybe 及类型推导,跨编译就是函数式专属的(Kotlin),谁说逻辑式就必须复杂(miniKanren),谁说{}或end 最严谨(Python),Web怎么会只有”前端“功能呢(ES6+H5API)
如果世界上存在最优的编程语言——是哪个? 最简单的/功能最多的/最快的?
许多衡量标准本身就是冲突的,先有目的,然后才有最优解。 先懂为什么,然后才看做法
我们所学的知识和理论,有多少是罔顾了原因,只有做法和自恰性的? 文档并不是只有易理解与否,还有与现实、与其他的对应性,因为编程是一件实事,目的之下一切可替换的事。
到最后你才发现,根本不存在最优解,你所看到的优秀,不过是圈子里广为流传的假象。 世界上那么多人,所谓的大牛仍是天外有天,为什么你必须向他学习呢,难道你不能有比他做得好/做得广泛之处吗。
语言不重要,思想重要。
放下排名、放下”最佳实践“,做自己想做的
Htmleaf
基于HTML5 WebGL的图像扭曲变形动画特效效果演示_jQuery之家-自由分享jQuery、html5、css3的插件库
这是一款基于HTML5 WebGL的图像扭曲变形动画特效。该特效中,通过Three.js来制作从一幅缩略图,扭曲变形为全屏大图的动画特效,共有6种炫酷的动画效果。