duangsues.is_a? SaltedFish
60 subscribers
609 photos
6 videos
91 files
562 links
🌶🐔🐟 duangsuse 的日常
尤其喜欢发些奇奇怪怪的东西
和转载别人的东西
Download Telegram
#ce #parsing 半夜,想到一些关于分词处理的事,突然人格分裂。 🌝
深夜,关于分词器(Lexer,Tokenizer)数据建模的问题,动苏又开始人格分裂(划掉)进行讨论。

A:CASC 的 Lexer 我看了,除了不常规的 SyntaxFacts 用于数据转换,TokenKind+Token(kind,String) 是挺常见的,不过它当然没有创建对象,是 Lexer-instance 上的 variable ,C 实现一般这么做。
B:我觉得 toplevel disambiguate 的 routine 不该叫 void Lex() ,应该做成 Iterator<Toekn>的形式
A:面向对象、局部化的做法很好也便于组织语法树,但是 return new 会增加内存压力,就为给 String 加 Kind ,很亏
B:其实看看最后返回的 Token 基本都是 (kind=LParen, text="(") 这样的东西,token type 最后只是被 when 了一下没有别的用也不影响 toString()
A:是,我觉得为了严谨也不该弄出 type ,可是具体怎么去掉
B:分词器解析器,二者之间传递的除了序列的拆分,无非是传递关键字种类、String literal、Int 的信息,一般只要一 String 就够,但是会区分不出 "(" 代表 LParen 还是用户输入的 "(" 字符串
B:要区分词条是 kw 还是 lit-text ,可以选择加 Kind 也可以直接将其存返回 String 里,作为固定后缀吧,考虑部分人用 StringBuilder 建立,以及 substr 取前缀速度可能快一些。数据存储没有通用的规范,建立方消耗方都明白即可
A:这样就可以省去 TokenKind 的定义了,而且解析上也少写一大堆无聊的 1:1关系建立代码
B:不仅如此,弄完后你会发现一大堆之前一行行写读取的 token 其实都有类似 Regex 的通用模式,并不需要为它们单独编程 所以可以复用统一大量代码
B:Int、Char 的这些完全可以扫到字符串里再重读,其实完全可以直接把 type char 放到 Iterator 上,没有就代表不是值词条,只是关键词
B:突然想到一个更好的方法:反正关键词是固定的,直接定义成 String 用 ==(而非 equals) 全等判断呗,这样也方便解析器构造,如果没有自然就是值词条,Lua 就是这么弄的。
A:还是觉得建模成 Iterator ,不要全部放 instance var 的建议最有实用价值,kind 怎么定义也是个人喜好啦。
Forwarded from niconiconi
Forwarded from niconiconi
我就搞不懂了 怎么最近超爱写这种代码
Forwarded from Perol
每个view都能自行setTag
Forwarded from Perol
你可以通过view里的tag来写你的业务逻辑
Forwarded from 𝒉𝒋𝒕𝒉𝒋𝒕𝒉𝒋𝒕 | 想去沙漏双星
话说在MIUI开着小窗(挂在边上&展开)的情况下,底下应用会进入onPause()吗(
Forwarded from Diana
请问下 android后台定时任务是用什么来做的
Forwarded from Diana
之前用TimerTask 手机锁屏或者切换应用的话会出现不执行的情况
Forwarded from Deleted Account
左边红线为状态栏, 长黑线为绘制区域,1080P的视频无法填充整个屏幕,如红色快, 如果我把视频居中,整个左边黑块就很大, 能不能占用状态栏的高度, 这是pixel 4 API29
Forwarded from Deleted Account
这是全屏应用为就不能撑满左边呢, 我是新手啊,对特性和厂家标准不是很理解,那位大佬告知一下
Forwarded from 平行线
window.attributes.layoutInDisplayCutoutMode
Forwarded from Tsung @ionull Wu
workmanage是靠系统调度
Forwarded from Tsung @ionull Wu
很久没写过service,现在如果有后台权限的话,用户退出,service还跑吗
duangsues.is_a? SaltedFish
https://t.iss.one/c/1119363280/109316 #reveng ndk onCreate https://t.iss.one/c/1119363280/109356 #huawei homoOs( #旧事重提 https://t.iss.one/c/1119363280/109367 xposed #wechat https://t.iss.one/c/1119363280/109378 #china #robotic #旧事重提 光年实验室 https://t.iss.one/c/1119363280/109402 #framework…
Forwarded from dnaugsuz
你必须学习一个,这并不是复杂的 break continue 控制流,仅仅是索引的区间、递进循环而已

形如:
for (i in 0..10) op(i);
for (int i=0; i<=10; i++) op(i);
int i=0; while (i<=10) { op(i); i++ }
其中, op 可为任何引用到变量 i 的表达式/语句块,下文皆此。
op=System.out::println; 则你会看到 0,1,2,...,10 这 11 个数

这是 inexclusive range ,也就是带右值的 exclusive range 。比如 1..100 ,总共 100 个数 (== 100-1 +1)

编程时常用 exclusive 区间:
for (i in 0 until 10) print(i)
0,1,...,9
如果你要 s[i] 遍历整个字符串 s ,
因为索引以 0 起始(方便机器计算 以及避免区间连接时的麻烦),它的末引数其实是 length-1 ,代码便是:
for (i in 0 until s.length) op(i)
for (i in 0..s.lastIndex) op(i)
for (int i=0; i<s.length; i++) op(i);
其中 val String.lastIndex get() = length-1
其实,若 i 步长为 1,继续条件 (i<=n) == (i<n+1) 且等效 (i != n+1) 、 (i-1 != n) 。

(i<=n) 的区间示例是 (1..n) ,
终止条件 == !继续条件 ,即 while break 后 (i>n) 即 (i==n+1)。


想想,如果你要按2字符为单位迭代一个字符串 s ,便要设置不是1的递增步长。
for (i in 0 until s.length step 2) op(s[i])
这样 s="Winnie"; op=print 时 Wni 便被输出

这样就有一个好:细心的小朋友就会发现实质上这给字符列表分了块—— 0,1; 2,3; 4,5 这 2*3 项
int i;/*另种写法*/
for (i=0; i<s.length-1; i++) op(s[i], s[i+1]);

这样实际就实现了某种 zip([1,2],[2,1]) ,但也要提前写上 IndexOutOfBounds(缩 IOB) 的检查,那么作为练习,实现
<T> void forEachChunk(int size, List<T> xs, Consumer<List<T>> op);
以及自定签名的 zip, zipWithNext 函数。

当然,以上示例的 for while 都没有加 {} ,在工程上这是不利于可读性的;而且我举的例子大部分可用 for (T x : xs) op(x); 即 for (x in xs) op(x) 和仅 Kotlin 的 for ((i,x) in xs.withIndex()) op(i,x) 替换,实际上用到的时候不多。

索引计算的常识和 <,<=,== 及 +,+= (a+=b 等价 a=a+b) 这些运算密切相关,必须学习一个。
Forwarded from dnaugsuz
感觉这个内容并不困难,就是看看而已

记得以前好多程序员喜欢 List<T> wtf; 然后 for (T item : items) wtf.add(op(item)); 的,感觉很冗