Forwarded from Deleted Account
不可读的这么多花括号
不容易符合直觉的
if () for 只是这种原因的话也要加上花括号,而没有在语法上区分开不容易符合直觉的
Forwarded from Deleted Account
dist 你改成 cost 或许好看一些... dist 这个本身就和 distrib... 有点缩写混了
ee 这样意义小的名字应该避免
ee 这样意义小的名字应该避免
Forwarded from Deleted Account
有的逻辑能 merge 就 merge,
trivial 的部分能明确化就明确化
if (costs[link] > costs[current] + link.cost) {
costs[link] = costs[current] + link.cost;
works.push( (node) {d[link.to], link.to} );
}
可以弄成 minBy 的抽提...
睡觉了,虽然我都没注意到 to 是一个箭头 晚安
trivial 的部分能明确化就明确化
if (costs[link] > costs[current] + link.cost) {
costs[link] = costs[current] + link.cost;
works.push( (node) {d[link.to], link.to} );
}
可以弄成 minBy 的抽提...
if (costs[link] > costs[current] + link.cost) {
costs[link] = costs[current] + link.cost;
works.push( (node) {costs[link.to], link.to} );
}
auto selected = minBy(costs[link], id, costs[current], [](auto x) { x+link.cost });
🤔 好像不行呢...睡觉了,虽然我都没注意到 to 是一个箭头 晚安
#acg https://ihentai.moe/ 虽然我之前没有去过 ehentai,但是我见过某 ehentai 的工具
ehentai 总体结构比较简单,就是一个以 gid 为 key 本子元数据为结果的 dict
这里是一位大佬根据令一位大佬 8k 本本子数据 创建的站
数据在 GitHub 上可以访问,不过需要 Git LFS(large filestore) (本子缩略图什么的>2G)
也是看到开源哥的点赞才知道有这玩意...
ehentai 总体结构比较简单,就是一个以 gid 为 key 本子元数据为结果的 dict
这里是一位大佬根据令一位大佬 8k 本本子数据 创建的站
数据在 GitHub 上可以访问,不过需要 Git LFS(large filestore) (本子缩略图什么的>2G)
也是看到开源哥的点赞才知道有这玩意...
/tmp/duangsuse.sock
未来还会加入解析组合子选项(可以做一些数据量小的 EDSL 了
得等我先完成那几个插件,然后修整一点时间...
刚才去了解了个博客,就有 GraphQL, Express, Koa, React, Vue 什么的流行技术入眼
刚才去了解了个博客,就有 GraphQL, Express, Koa, React, Vue 什么的流行技术入眼
/tmp/duangsuse.sock
未来还会加入解析组合子选项(可以做一些数据量小的 EDSL 了
解析组合子是什么?
下面会简单科普一下 LL(1)、LR(1)、LALR 和一般手写的递归下降(recursive descent)解析器的 一些 知识(
每次看到很多各种各样的线性 数据结构,比如说,字符串
不管是采用怎样的字符集、怎样的编码,字符串都是一堆可以判断相等性的『字符』组成的『序列』
那么,如果为了方便,想从这个序列里提取出一些结构(比如从
就需要一种依据序列 进行语法树推导的算法
一般被称作解析算法
LL(1) 的第一个 L 是 "Left to right",指这是个解析器 Left-To-Right 从左到右扫描输入序列
LL(1) 的第二个 L 是 "Leftmost derivation",LL(1) 是自顶向下构造提出数据(推导)的
LL(1) 的这个 (1) 代表任何时候,LL(1) 只需向前阅读一个项目,即可决定解析流程走向了(终结符 terminal 推导预判)
LL 解析器一般用的是显式的栈(stack) 而非递归下降法的机器栈(语言提供的调用栈)
LR(1) 的第二条则正好相反,它不是自顶向下收束,而是自底向上规约(大概吧... Parser 和 grammar 的关系还是蛮大的,LR 的 back-substraction 是什么鬼,我怎么感觉这些自动机有点重造编程语言执行者的嫌疑...
LALR 我听过《Ruby 原理剖析》说是“Look-Ahead Left Rightmost derivation”
以上都可能很不准确,中国国内能找到很少的资料(恐怕大部分都还是转发...)而且我懒得看资料(因为我又不是专门学面向解析器的编译原理的.... 或者 NLP 什么的)
总之我不是特别喜欢这类自动机... 看起来虽然优化明显一些,但是它们也是只能一个字符一个字符的推导... SIMD 扫描字符串可能都没有。而且很多 parser compiler 生成出的程序还贼大... 对手动优化也不友好的
不过这里要讲的是一般的手写递归下降法解析器
即使很多语言官方都是在用 Lex/Yacc style 的 parser combinator (比如 PHP 就是 re2c、GCC C 前端之前也应该用过自动生成的解析器)
这个递归下降呢... 思路很简单,就是利用所用编程语言自有的结构,比如判断、循环、递归,来扫描目标输入
自动机的状态,是由这门编程语言的控制流转换图构成的
比如扫描一个简单的数字(类似 130, 229 这种
跑题了... 不过的确是有『工业级』语言 使用手写的递归下降解析器的,比如 Lua
这个
不过目前看来,虽然 (intoIter 从 array-like 转化的) iterator 是可以随便 tell/seek 的,但是没有 API 来 reset。
不过 LookAhead-1 还是可以实现的。方法就是预取 — 利用 lookAhead1 函数得到的流,有一个
Python 的缩进语义需不需要预判呢?其实缩进语义本身是有点 Non-Context free 的,毕竟你没法写出一种刻板的描述,
一个
Python 的列表 List comprehension LL(1) 能不能实现呢?
先来看看例子:里面 '' 包裹的是文本,[] 包裹的是可选内容、<> 包裹的也是文本、{} 包裹是重复 0-n、{{}} 是 1-n
大写的是非终结符(可以被替换为终结符序列),小写的是终结符。
首先重写一下式子
首先咱收束个
当然这里是不可能 的,不过还是可以做到。下一项的可能性:
1.
2,3. 都是
这个时候也是可以通过预取 1 推导的:为什么?判断是
所以 Python 的这个语法也是 LL(1) 兼容的
下面会简单科普一下 LL(1)、LR(1)、LALR 和一般手写的递归下降(recursive descent)解析器的 一些 知识(
每次看到很多各种各样的线性 数据结构,比如说,字符串
不管是采用怎样的字符集、怎样的编码,字符串都是一堆可以判断相等性的『字符』组成的『序列』
那么,如果为了方便,想从这个序列里提取出一些结构(比如从
"$a . $b" 里提取 [dollar a, '.', dollar b])就需要一种依据序列 进行语法树推导的算法
一般被称作解析算法
LL(1) 的第一个 L 是 "Left to right",指这是个解析器 Left-To-Right 从左到右扫描输入序列
LL(1) 的第二个 L 是 "Leftmost derivation",LL(1) 是自顶向下构造提出数据(推导)的
LL(1) 的这个 (1) 代表任何时候,LL(1) 只需向前阅读一个项目,即可决定解析流程走向了(终结符 terminal 推导预判)
LL 解析器一般用的是显式的栈(stack) 而非递归下降法的机器栈(语言提供的调用栈)
LR(1) 的第二条则正好相反,它不是自顶向下收束,而是自底向上规约(大概吧... Parser 和 grammar 的关系还是蛮大的,LR 的 back-substraction 是什么鬼,我怎么感觉这些自动机有点重造编程语言执行者的嫌疑...
LALR 我听过《Ruby 原理剖析》说是“Look-Ahead Left Rightmost derivation”
以上都可能很不准确,中国国内能找到很少的资料(恐怕大部分都还是转发...)而且我懒得看资料(因为我又不是专门学面向解析器的编译原理的.... 或者 NLP 什么的)
总之我不是特别喜欢这类自动机... 看起来虽然优化明显一些,但是它们也是只能一个字符一个字符的推导... SIMD 扫描字符串可能都没有。而且很多 parser compiler 生成出的程序还贼大... 对手动优化也不友好的
不过这里要讲的是一般的手写递归下降法解析器
即使很多语言官方都是在用 Lex/Yacc style 的 parser combinator (比如 PHP 就是 re2c、GCC C 前端之前也应该用过自动生成的解析器)
这个递归下降呢... 思路很简单,就是利用所用编程语言自有的结构,比如判断、循环、递归,来扫描目标输入
自动机的状态,是由这门编程语言的控制流转换图构成的
比如扫描一个简单的数字(类似 130, 229 这种
/(\d+)/):#include <stdio.h>就是用这个 while,那这个实际上有一点问题,就是不能保证 (实际上是
#include <ctype.h>
#define PARSER int ch;
#define GETC (ch = getchar())
unsigned int readUnsigned() {
PARSER
unsigned readn = 0;
while (isdigit(GETC)) { readn*=10; readn+=(ch -'0'); }
}
/d*/),其实 int ch; 可以提升到全局作用域,这样在函数入口处就可以检查下(是不是 isdigit,会不会至少循环一次)语法正确与否了跑题了... 不过的确是有『工业级』语言 使用手写的递归下降解析器的,比如 Lua
这个
fp.js 的解析器呢... 一般会把输入看成是流,最好还能 mark/reset,这样就能轻而易举地实现 (多) branch不过目前看来,虽然 (intoIter 从 array-like 转化的) iterator 是可以随便 tell/seek 的,但是没有 API 来 reset。
不过 LookAhead-1 还是可以实现的。方法就是预取 — 利用 lookAhead1 函数得到的流,有一个
next 属性可以窥视到下一个项目,这样可以实现需要预判的语法Python 的缩进语义需不需要预判呢?其实缩进语义本身是有点 Non-Context free 的,毕竟你没法写出一种刻板的描述,
一个
':' 会开启新 layout(语法布局,就是缩进层次),可是 CFG 可以有 sequence 和 branch,但它没法有 context — 算不出来下一层布局是多少个空格开头什么的,也就是 Non-CFG 的了(当然,这种情况可以先扫描一遍转化 layout 语法为 CFG 语法(添加 <begin> 和 <end> 之类的隐藏关键字什么的),这样就依然可以扫描Python 的列表 List comprehension LL(1) 能不能实现呢?
先来看看例子:里面 '' 包裹的是文本,[] 包裹的是可选内容、<> 包裹的也是文本、{} 包裹是重复 0-n、{{}} 是 1-n
大写的是非终结符(可以被替换为终结符序列),小写的是终结符。
List = '[' Items ']'那这是不是 LL(1) 可以推导的呢?Left, Leftmost derivation, LookAhead(1)
Items = Expr {',' Expr}
[1,2,3,4] #valid
[0] #valid
ListComp = Expr <for> ident <in> Expr [ <if> Expr ]
Items |= ListComp
[x for x in xs] #valid
[sin(x) for x in xs if x < 10] #valid
首先重写一下式子
List = '[' Expr {',' Expr}
| Expr <for> ident <in> Expr
| Expr <for> ident <in> Expr <if> Expr
']'
我们看看,是不是靠着 LookAhead1 就可以判断解决所有的 | 分支呢?这关系到解析器状态的转换 🤔首先咱收束个
Expr,然后怎么办呢?从字符组织,不得不看看 字符的情况了当然这里是不可能 的,不过还是可以做到。下一项的可能性:
1.
{',' Expr}
看 ',' 即可2,3. 都是
<for> 这就混了(| Expr <for> ident <in> Expr不过两边 左 的文法都是一致的,所以找一下最右边的情况
| Expr <for> ident <in> Expr * <if> Expr
']'
(*) 这个时候也是可以通过预取 1 推导的:为什么?判断是
<if> | ']' 即可所以 Python 的这个语法也是 LL(1) 兼容的
/tmp/duangsuse.sock
解析组合子是什么? 下面会简单科普一下 LL(1)、LR(1)、LALR 和一般手写的递归下降(recursive descent)解析器的 一些 知识( 每次看到很多各种各样的线性 数据结构,比如说,字符串 不管是采用怎样的字符集、怎样的编码,字符串都是一堆可以判断相等性的『字符』组成的『序列』 那么,如果为了方便,想从这个序列里提取出一些结构(比如从 "$a . $b" 里提取 [dollar a, '.', dollar b]) 就需要一种依据序列 进行语法树推导的算法 一般被称作解析算法 LL(1)…
那么又说跑题了(而且含金量不高... 没有讲到实际实现 parser compiler 以及这些自动机本身的模型和要点)
咱来考虑一下 FP.js 应该提供怎么样的解析组合子,我希望这个解析组合子的应用尽可能要少些废话... 🤔
尤其要利用 JavaScript 的 constructor 函数,拒绝 手写....
咱来考虑一下 FP.js 应该提供怎么样的解析组合子,我希望这个解析组合子的应用尽可能要少些废话... 🤔
尤其要利用 JavaScript 的 constructor 函数,拒绝 手写....
/tmp/duangsuse.sock
目前在想... 手工检查一下(癖好)加上 FP 特性即可
This media is not supported in your browser
VIEW IN TELEGRAM