#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,真是眼高手低啊