duangsuse::Echo
#zhihu #recommended #China #school https://www.zhihu.com/question/320967006 🤣和呵呵呵哈哈哈
#week 那么我懒得再说其他的消息了... (基本想看的看完了,欸你们更新怎么这么慢?)
现在我说说我这周的设计(和之前的 Cat 程序设计语言),并且预期能在下午六点之前完成 Parserc 包(包括 RangeMap、SourceManager、BinaryStreamProcessor 和 TextCombinator)
现在我说说我这周的设计(和之前的 Cat 程序设计语言),并且预期能在下午六点之前完成 Parserc 包(包括 RangeMap、SourceManager、BinaryStreamProcessor 和 TextCombinator)
写的太多不知从何说起...
时间还是不够啊
我不是把时间给虵(shé 🐸)了... QAQ
就先说绝句、二进制和字符流 Parser 框架 这些最令人 excited 的玩意
Parser 框架我还打算自己手写这些算法:
TrieTree (只需要 Trie,因为只是字符流嘛,Radix 树还不如自己手动 maybe 匹配解析... 虽然那样好像没有优化了)
RangeMap (到学校里想了会,发现还真不是那么简单的,滚动歌词什么的还真是可以简单点,但是 RangeMap 可以启用二分查找技术和区间碰撞检测,进而可以实现 NestedRageMap)
LinearRangeMap (线性查找的 RangeMap,充当演示,时间复杂度捉鸡)
HashRangeMap (空间开销捉鸡,而且不能给不可枚举的类型创建映射,比如 Rational Number)
BsearchRangeMap (这才是主流)
CollisionRangeMap (支持非边缘碰撞检测的 Bsearch)
FuzzyRangeMap (支持简单碰撞替换情况的 CollisionRangeMap,不过没有额外的碰撞类型计算)
NestedRangeMap (可以用来开发 IDE 的 CollisionRangeMap)
VersionizedMap (可以实现 Dynamic Scoping)
CollisionVersionizedMap (基于碰撞检测的 VersionizedMap)
HashCollisionVersionizedMap (HashMap,Hashtable 实现)
MultiMap (K -> Multiply Value 的 Map)
ReverseIndexedMultiMap (同上,还自动维护反向索引)
还有这些辅助的东西
MixedArrayLinkList (就是类似猾为那种『IO 热区检测优化』... 不过就是两种模式『Link 插入模式』『Array 访问模式』切换而已)
Pair, Range
ArrayMap
MixedArrayHashMap
RandomReadStream (完全保存输入流的所有已读字节,随时可以 mark / reset,即使输入流不让 Mark / reset)
StringView (覆盖 get, length, subsequence 方法的 CharSequence)
Cat 因为连一个解析器框架都没有不好定义语法呢(虽然已经有语法和语义稿了,足足写了五面多)
ApkPool 因为 GeekSpec 什么的技术都还没有准备好,就不能说了,不过我觉得如果有时间可以谈谈 Java 类的『行为 hashCode』是否可行
时间还是不够啊
我不是把时间给虵(shé 🐸)了... QAQ
就先说绝句、二进制和字符流 Parser 框架 这些最令人 excited 的玩意
Parser 框架我还打算自己手写这些算法:
TrieTree (只需要 Trie,因为只是字符流嘛,Radix 树还不如自己手动 maybe 匹配解析... 虽然那样好像没有优化了)
RangeMap (到学校里想了会,发现还真不是那么简单的,滚动歌词什么的还真是可以简单点,但是 RangeMap 可以启用二分查找技术和区间碰撞检测,进而可以实现 NestedRageMap)
LinearRangeMap (线性查找的 RangeMap,充当演示,时间复杂度捉鸡)
HashRangeMap (空间开销捉鸡,而且不能给不可枚举的类型创建映射,比如 Rational Number)
BsearchRangeMap (这才是主流)
CollisionRangeMap (支持非边缘碰撞检测的 Bsearch)
FuzzyRangeMap (支持简单碰撞替换情况的 CollisionRangeMap,不过没有额外的碰撞类型计算)
NestedRangeMap (可以用来开发 IDE 的 CollisionRangeMap)
VersionizedMap (可以实现 Dynamic Scoping)
CollisionVersionizedMap (基于碰撞检测的 VersionizedMap)
HashCollisionVersionizedMap (HashMap,Hashtable 实现)
MultiMap (K -> Multiply Value 的 Map)
ReverseIndexedMultiMap (同上,还自动维护反向索引)
还有这些辅助的东西
MixedArrayLinkList (就是类似猾为那种『IO 热区检测优化』... 不过就是两种模式『Link 插入模式』『Array 访问模式』切换而已)
Pair, Range
ArrayMap
MixedArrayHashMap
RandomReadStream (完全保存输入流的所有已读字节,随时可以 mark / reset,即使输入流不让 Mark / reset)
StringView (覆盖 get, length, subsequence 方法的 CharSequence)
Cat 因为连一个解析器框架都没有不好定义语法呢(虽然已经有语法和语义稿了,足足写了五面多)
ApkPool 因为 GeekSpec 什么的技术都还没有准备好,就不能说了,不过我觉得如果有时间可以谈谈 Java 类的『行为 hashCode』是否可行
duangsuse::Echo
写的太多不知从何说起... 时间还是不够啊 我不是把时间给虵(shé 🐸)了... QAQ 就先说绝句、二进制和字符流 Parser 框架 这些最令人 excited 的玩意 Parser 框架我还打算自己手写这些算法: TrieTree (只需要 Trie,因为只是字符流嘛,Radix 树还不如自己手动 maybe 匹配解析... 虽然那样好像没有优化了) RangeMap (到学校里想了会,发现还真不是那么简单的,滚动歌词什么的还真是可以简单点,但是 RangeMap 可以启用二分查找技术和区间碰撞检测,进而可以实现…
RangeMap 其实是相当有用的数据结构,前几天我亲自算过的,二分查找算法优化可以实现!所谓一个 RangeMap,有插入、删除、查询三个基本操作,就是给你一对 Comparable(Range)、以及他们的映射 Value,进行插入后,查询
i1 <= x < i2,或者说 x in range 就能获得之前的 Value比如:
val offsetLineMap = RangeMap()然后我们就可以利用 RangeMap,在 O(log2 n) 的时间复杂度(而不是 O(n) 辣鸡线性复杂度下)完成 offset -> line 的索引
val str = "abc\n123\n!@#"
var startLine = 0
for ((i, c) in str.withIndex) when (c) {
'\n' -> { offsetLineMap[startLine..i] = str[startLine..i]; startLine = i+1; }
else -> {}
}
offsetLineMap[0] -> "abc"
offsetLineMap[1] -> "abc"
offsetLineMap[2] -> "abc"
offsetLineMap[3] -> "123"
offsetLineMap[5] -> "123"
offsetLineMap[6] -> "!@#"
offsetLineMap[9] -> IndexOutOfBounds
当我们有了 NestRangeMap 这种逆天的数据结构(和普通 BsearchRangeMap 比更类似 HashMap 和 MultiMap 比)后,还能快速实现类似 IDEA 的辅助功能,给可能有嵌套结构的 AST(抽象语法树,JB 也有一个类似的 PSI,程序结构接口)加上索引这样,只要我们能拿到 TextField 的光标 offset,就能做类似
+ 拿到光标下的语法嵌套结构,能够知道语法路径在哪
这样的事情 🤪
这种功能很重要吗?的确很重要啊,如果你用线性查找这种省事但不讨好的算法,或者不考虑 Range 的碰撞,是绝对没有这种福利的
然而
NestedRangeMap 就可以实现这种操作,让人为之一振val documentOffsetNesting = NestedRangeMap()
val document = KommonMarks.parseString
("""
# H1
_a_ __b__ *c*
## H2
[name](url:)
""".trim())
/* Add pairs to nested range by document marker offsets */
documentOffsetNesting[0] => HeaderNode(children = [TextNode("H1")], n = 1)
documentOffsetNesting[5] => [DocumentSection(name = "H1", n = 1), TextDisplayNode(mode = Italic, text = "a")]
documentOffsetNesting[19] => HeaderNode(children = [TextNode("H2")], n = 2)
看到 documentOffsetNesting[5] 的返回值了吗?它能够提示某个 Markdown 元素的路径,是在哪个标签里对于
NestedRangeMap 来说,它会自动处理任何的区间碰撞(被分成五个大类型),将碰撞的部分替换成一个列表val rm = NestedRangeMap()程序员在写
rm[0...10] = "0 to 10"
rm[2..6] = "2 to 5" // "Full Overwrite" collision from index 2 to 6
rm[0] => "0 to 10"
rm[2] => ["0 to 10", "2 to 5"]
SourceManager 的时候,就只需要把某个语法结构的 startOffset 和 endOffset 记录一下就好了,NestedRangeMap 可以自动完成代码路径索引创建任务
duangsuse::Echo
写的太多不知从何说起... 时间还是不够啊 我不是把时间给虵(shé 🐸)了... QAQ 就先说绝句、二进制和字符流 Parser 框架 这些最令人 excited 的玩意 Parser 框架我还打算自己手写这些算法: TrieTree (只需要 Trie,因为只是字符流嘛,Radix 树还不如自己手动 maybe 匹配解析... 虽然那样好像没有优化了) RangeMap (到学校里想了会,发现还真不是那么简单的,滚动歌词什么的还真是可以简单点,但是 RangeMap 可以启用二分查找技术和区间碰撞检测,进而可以实现…
MultiMap 呢? 🤔
比如说,
很多时候,我们可能想写一些类似『CodeStyle』这样的程序,
更近一步,我们(可能)希望 IDE 有这样的功能:实时检查 CodeStyle,一个空格都不放过,并且能自动修复
我们可能希望,解析器能做最少的工作(比如,如果程序结构实际上没有被修改,修改的只是空格或者说字面量)
在不需要的时候,尽可能只做增量解析
我们可能希望,能知道程序代码在哪里有一些注释,有些内联文档
我们可能希望,能够通过某一个位置的
怎么找妥帖?应该先找到字符对应的语法结构,再找到这个语法结构的
我们可能希望,把排错信息存储在一个『其他的』地方,而不是 AST 结构类本身里面(就是使用 SourceManager 存储 SourceLocation)
而且不仅仅这样,我们甚至还希望能够通过
这些通通需要 Reverse index,有些再使用 RangeMap 就可以优雅地实现了(因为 AST 一般只会保留程序语义相关的内容,文档什么的都是忽视的,反向索引才行)
比如说上面的空格查找功能和 Marker highlight 功能
空格查找其实还真没有那么容易实现,不过靠 SourceManager 其实也不难,只是不容易『优雅』地实现
比如说,考虑以下简单形式化语法:
比如
假设我们有如下示例程序
def num = 1
def str = "Hello, world"
def boo = true
def null = nil
现在有一个人名叫小明,是个辣鸡程序员,非常喜欢捣乱,就把代码弄成了这个 B 样 😠
def
num = 1
def str
= "Hello, world"
def boo =
true
def
null = nil
这 TMD 还能看!
傻逼的人的选择必须是自己一个空格一个换行的删除,『手工』修复这段代码的缩进
聪明人的选择可能是 CodeStyle 自动 Format,可是,这是小明自己写的『编程语言』,你找不到支持这语言的格式化器
更笨点的人的选择可能是弄一个 DumpVisitor,手动格式化代码,但是很可惜,小明用的 IDE 非常脑残,它不推荐使用这种方式(直接
我们现在的问题是如何生成一个修改列表(只有“在某个 offset 删除 n 个字符”这一个操作)
帮助小明的同事修改好这个程序 😉
比如说,
很多时候,我们可能想写一些类似『CodeStyle』这样的程序,
更近一步,我们(可能)希望 IDE 有这样的功能:实时检查 CodeStyle,一个空格都不放过,并且能自动修复
我们可能希望,解析器能做最少的工作(比如,如果程序结构实际上没有被修改,修改的只是空格或者说字面量)
在不需要的时候,尽可能只做增量解析
我们可能希望,能知道程序代码在哪里有一些注释,有些内联文档
我们可能希望,能够通过某一个位置的
'{' 字符找到对应的 '}' 字符位置(比如,代码高亮的时候就用的到)怎么找妥帖?应该先找到字符对应的语法结构,再找到这个语法结构的
'}' 字符我们可能希望,把排错信息存储在一个『其他的』地方,而不是 AST 结构类本身里面(就是使用 SourceManager 存储 SourceLocation)
而且不仅仅这样,我们甚至还希望能够通过
SourceLocation 拿到某种语法结构,来实现索引功能(虽然 RangeMap 也可以实现,不过这种虽然没啥可行性,性能还更高)(没有可行性是因为对于 val n = 1 这种,用 SourceLocation 反向索引要求你只能选择一个『字符位置』索引到正确的结果,比如 val 的 'v' 字索引到了,光标指到后面的 '1' 的时候就啥都找不到)这些通通需要 Reverse index,有些再使用 RangeMap 就可以优雅地实现了(因为 AST 一般只会保留程序语义相关的内容,文档什么的都是忽视的,反向索引才行)
比如说上面的空格查找功能和 Marker highlight 功能
空格查找其实还真没有那么容易实现,不过靠 SourceManager 其实也不难,只是不容易『优雅』地实现
比如说,考虑以下简单形式化语法:
let whiteSpace = [ \n\r\t]这是一种描述方法,其中,每个重复的『终结符』都会留意之后的『终结符』是否匹配,如果匹配则自己结束匹配
let parser = terms
nl = [\n\r]
terms = term*
term =
<def> name <=> value <nl>
name =
[A-Za-z0-9_]+
value =
string | number | boolean | nil
string = <"> .* <">
number = [0-9\.]+
boolean = <true> | <false>
nil = <nil>
比如
string = <"> .* <">其中的
.* 自动先行判断后面的 <"> 是否 match,如果不 match 自己才能继续下一个,否则返回假设我们有如下示例程序
def num = 1
def str = "Hello, world"
def boo = true
def null = nil
现在有一个人名叫小明,是个辣鸡程序员,非常喜欢捣乱,就把代码弄成了这个 B 样 😠
def
num = 1
def str
= "Hello, world"
def boo =
true
def
null = nil
这 TMD 还能看!
傻逼的人的选择必须是自己一个空格一个换行的删除,『手工』修复这段代码的缩进
聪明人的选择可能是 CodeStyle 自动 Format,可是,这是小明自己写的『编程语言』,你找不到支持这语言的格式化器
更笨点的人的选择可能是弄一个 DumpVisitor,手动格式化代码,但是很可惜,小明用的 IDE 非常脑残,它不推荐使用这种方式(直接
setCode(String)),一定要你手动生成修改代码的方案才行我们现在的问题是如何生成一个修改列表(只有“在某个 offset 删除 n 个字符”这一个操作)
帮助小明的同事修改好这个程序 😉
duangsuse::Echo
MultiMap 呢? 🤔 比如说, 很多时候,我们可能想写一些类似『CodeStyle』这样的程序, 更近一步,我们(可能)希望 IDE 有这样的功能:实时检查 CodeStyle,一个空格都不放过,并且能自动修复 我们可能希望,解析器能做最少的工作(比如,如果程序结构实际上没有被修改,修改的只是空格或者说字面量) 在不需要的时候,尽可能只做增量解析 我们可能希望,能知道程序代码在哪里有一些注释,有些内联文档 我们可能希望,能够通过某一个位置的 '{' 字符找到对应的 '}' 字符位置(比如,代码高亮的时候就用的到)…
解决小明可怜同事的问题,首先我们必须得解析这段代码,但是解析的时候还不能忽略空格!
用伪代码,我们这么设计解析器(输入就是字符流,Scanner less parsing):
所以我们来看看小明同事的机制解决方案:
小明的同事解析出了可怜小明编写的可怜代码,下面是一部分:
definitions !! 0 == Definition "num" (Number 1)
definitions !! 1 == Definition "str" (String "Hello, world")
可是,机制的同事注意到了,这里没有给出任何的空格信息?那怎么判断呢?
于是还记得上面的
或者直接『对每一个 key,都 putAll(values, key)』
于是就有了
getAll spaces $ definitions !! 0 == [wsDefName "\n", wsNameEq " ", wsEqValue " ", wsValueEnd ""]
小明同事检查了一下空格:
filter (not . (flip elem) " ") [wsDefName "\n", wsNameEq " ", wsEqValue " ", wsValueEnd ""]
=> [wsDefName "\n", wsEqValue " "]
0 不是空格,应该删除!
1 比预期的 1 空格多了 2-1=1 空格!
在两个 ws 的起始位置删除 1 个字符就万事大吉了,今晚吃鸡(喷
这下小明同事解决问题了,只要我们使用 MultiMap 存储空格、文档之类的信息,就可以做到检查代码风格这种小事情
用伪代码,我们这么设计解析器(输入就是字符流,Scanner less parsing):
terms :: Parser [Definition]这... 我不是来教大家写 Parser Combinator 的,也不是来传道 Haskell 的(我连 Monad 的什么 MZero 啊 MPlus 啊都不知道,感觉就是顺序 Application 的一种方式,勉强一知半解范畴论)
terms = many term
wsP = satisfy $ `elem` " \n\r\t"
nameP = satisfy $ \x -> x == '_' || x `elem` 'A'..'a'
valueP
= keywordP "nil"
++ booleanP
++ numberP
++ stringP
term :: Parser Definition
term = do
keywordP "def"
wsDefName <- wsP
name <- nameP
wsNameEq <- wsP
keywordP "="
wsEqValue <- wsP
value = valueP
wsValueEnd <- wsP
newlineP
return $ Definition name value
所以我们来看看小明同事的机制解决方案:
小明的同事解析出了可怜小明编写的可怜代码,下面是一部分:
definitions !! 0 == Definition "num" (Number 1)
definitions !! 1 == Definition "str" (String "Hello, world")
可是,机制的同事注意到了,这里没有给出任何的空格信息?那怎么判断呢?
于是还记得上面的
wsXxx = wsP 吗?wsP :: Parser String它会返回记录空格的,于是机制的同事利用了多年的 Haskell Monad 经验,单子化了生成算法,引入了优美的线性... 反向索引,这里实现大概就是『把所有的 Value 拿去 collect 对应的 key,然后再 put 回来』
或者直接『对每一个 key,都 putAll(values, key)』
于是就有了
getAll spaces $ definitions !! 0 == [wsDefName "\n", wsNameEq " ", wsEqValue " ", wsValueEnd ""]
小明同事检查了一下空格:
filter (not . (flip elem) " ") [wsDefName "\n", wsNameEq " ", wsEqValue " ", wsValueEnd ""]
=> [wsDefName "\n", wsEqValue " "]
0 不是空格,应该删除!
1 比预期的 1 空格多了 2-1=1 空格!
在两个 ws 的起始位置删除 1 个字符就万事大吉了,今晚吃鸡(喷
这下小明同事解决问题了,只要我们使用 MultiMap 存储空格、文档之类的信息,就可以做到检查代码风格这种小事情
duangsuse::Echo
写的太多不知从何说起... 时间还是不够啊 我不是把时间给虵(shé 🐸)了... QAQ 就先说绝句、二进制和字符流 Parser 框架 这些最令人 excited 的玩意 Parser 框架我还打算自己手写这些算法: TrieTree (只需要 Trie,因为只是字符流嘛,Radix 树还不如自己手动 maybe 匹配解析... 虽然那样好像没有优化了) RangeMap (到学校里想了会,发现还真不是那么简单的,滚动歌词什么的还真是可以简单点,但是 RangeMap 可以启用二分查找技术和区间碰撞检测,进而可以实现…
待会继续说『绝句』的,我一定要先实现这个玩意... (虽然可能不如 parser 们更优雅,因为虽然它是完整的模板语言,也有被当成 CPP 这种『逐行处理』的风险... 汗)
先一言不合就念诗:
[唐] 杜甫
『两』个『黄鹂』;鸣『翠柳』
『一』行『白鹭』... 上『青天』
『窗』含『西岭;『千』秋『雪』』
『门』泊『东吴』。『万』里『船』
如果这执行玩意可以打印出下面这种东西,你们相信么?
🌴🦜🦜🎵
🐦🐦🐦🐦👆🌥
🏠👅西岭📆*1000years:❄️
🚪🅿️东吴🚢🚢🚢🚢*9997km
🤔???
先一言不合就念诗:
int main() {
~绝句~[唐] 杜甫
『两』个『黄鹂』;鸣『翠柳』
『一』行『白鹭』... 上『青天』
『窗』含『西岭;『千』秋『雪』』
『门』泊『东吴』。『万』里『船』
}说这玩意是代码你们相信么?
如果这执行玩意可以打印出下面这种东西,你们相信么?
🌴🦜🦜🎵
🐦🐦🐦🐦👆🌥
🏠👅西岭📆*1000years:❄️
🚪🅿️东吴🚢🚢🚢🚢*9997km
🤔???
www.gushiwen.org
绝句·两个黄鹂鸣翠柳原文|翻译|赏析_杜甫古诗_古诗文网
杜甫的绝句·两个黄鹂鸣翠柳原文及翻译:两个黄鹂鸣翠柳,一行白鹭上青天。窗含西岭千秋雪,门泊东吴万里船。注释 西岭:西岭雪山。 千秋雪:指西岭雪山上千年不化的积雪。 泊:停泊。 东吴:古时候吴国的领
duangsuse::Echo
待会继续说『绝句』的,我一定要先实现这个玩意... (虽然可能不如 parser 们更优雅,因为虽然它是完整的模板语言,也有被当成 CPP 这种『逐行处理』的风险... 汗) 先一言不合就念诗: int main() { ~绝句~ [唐] 杜甫 『两』个『黄鹂』;鸣『翠柳』 『一』行『白鹭』... 上『青天』 『窗』含『西岭;『千』秋『雪』』 『门』泊『东吴』。『万』里『船』 } 说这玩意是代码你们相信么? 如果这执行玩意可以打印出下面这种东西,你们相信么? 🌴🦜🦜🎵 🐦🐦🐦🐦👆🌥 🏠👅西岭📆*1000years:❄️…
和 PerlYuYan 略有不同,因为绝句是自带 scannerless 解析器的模板系统,而且不支持自然语言分词(我觉得这有益于可读性)
和 itorr 大佬的 e 网页、templetJS 也有不同,但有相似
绝句也是模板语言,可是它的功能比普通的模板语言要多,而且支持 2D 文法,所以 templet 的这种语法:
@:: lang=HTML
当 b 成立,输出 b,否则 e 当成立,输出 d,否则什么都不输出
当 a 成立,输出 c
templet.js 支持的
变量、子属性、变量判断、运算判断、数组循环、对象循环、管道
在绝句里都是语言支持,绝句还支持函数柯里化和函数作为值,函数即是所谓的宏
变量
@:: a -> 1
@:: a += 1
@write "a = $a"
子属性是 JavaScript 里的,绝句不面向对象,不支持
则就可以支持引用对象属性
变量判断说了,运算判断比较复杂,templet 是直接执行 JavaScript Function 的,因为绝句是单独解释的编程语言...
数组循环、对象循环,绝句因为是 Java 编写所以支持反射对象访问,不过对绝句来说 Object 会被映射为 Map...
函数管道,绝句支持函数式编程,可以这样定义一个函数:
#Android #GUI https://github.com/ayaseruri/TagsView
是时候好好学学前端了...
和 itorr 大佬的 e 网页、templetJS 也有不同,但有相似
绝句也是模板语言,可是它的功能比普通的模板语言要多,而且支持 2D 文法,所以 templet 的这种语法:
<p> {{$1==1}}
<code>一等一</code> 是正确的,所以我显示出来啦 {{/1==1}}
</p>
<p> {{$变量一==变量二}}
<code>变量一==变量二</code> 是不是正确的呢 {{/变量一==变量二}}
</p>
可以理解为 JavaScript 代码if (1==1) { writesM("<code>一等一</code> 是正确的,所以我显示出来啦"); }
if (变量一==变量二) { writesM("<code>变量一==变量二</code> 是不是正确的呢 {{/变量一==变量二}}"); }
而换到绝句,就是这样@:: lang=HTML
@// 语言分词支持是可以自己定义的,可以用 Java 定义也可以用绝句定义分词规则,定义『标记、字符串、注释、标识符』这几种词条(绝句提供了更好的方法,对 Heredoc、String interpolation 和多重 string 这三种模式都有支持)@? 1 = 1
<code>一等一</code> 是正确的,所以我显示出来啦@? 变量一 = 变量二
<code>变量一==变量二</code> 是不是正确的呢至于 if 的嵌套问题,二维文法可以解决
@?a当 a 成立,输出 a
a
@ ?b
b
@ ,? e
d
@ ,
c
当 b 成立,输出 b,否则 e 当成立,输出 d,否则什么都不输出
当 a 成立,输出 c
templet.js 支持的
变量、子属性、变量判断、运算判断、数组循环、对象循环、管道
在绝句里都是语言支持,绝句还支持函数柯里化和函数作为值,函数即是所谓的宏
变量
@:: a -> 1
@:: a += 1
@write "a = $a"
子属性是 JavaScript 里的,绝句不面向对象,不支持
<dl>这就是说如果要遍历一个对象(如果是数组,则使用
{{#hash}}
<dt>{{键}} <dd>{{值}}
{{/hash}}
</dl>
{{.}} 来引用当前项)则就可以支持引用对象属性
{键:1, 值:2}
templet 的实现是『对每个循环属性名使用索引前缀』... 我不知道为啥这么做,好像是因为模板处理器没有递归所以害怕冲突?(可是都用 var 好像不会冲突...)变量判断说了,运算判断比较复杂,templet 是直接执行 JavaScript Function 的,因为绝句是单独解释的编程语言...
数组循环、对象循环,绝句因为是 Java 编写所以支持反射对象访问,不过对绝句来说 Object 会被映射为 Map...
函数管道,绝句支持函数式编程,可以这样定义一个函数:
@无聊的操作(数字):从『将『数字』转为『字符串』』解析数字绝句的参数列表自然是要求比较高的... 目前想到了一个指定 index 的方法
@无聊的操作二(数字):
let 函数:(将...转为『字符串』++ 从...解析『数字』),
in 函数『数字』
@『a,2』操作『b,1』。 允许绝句代码这样使用 @操作(b,a)。 (或者 @操作(b)(a).)#Android #GUI https://github.com/ayaseruri/TagsView
是时候好好学学前端了...
GitHub
GitHub - audreyt/lingua-sinica-perlyuyan: Perl in Classical Chinese in Perl
Perl in Classical Chinese in Perl. Contribute to audreyt/lingua-sinica-perlyuyan development by creating an account on GitHub.
duangsuse::Echo
和 PerlYuYan 略有不同,因为绝句是自带 scannerless 解析器的模板系统,而且不支持自然语言分词(我觉得这有益于可读性) 和 itorr 大佬的 e 网页、templetJS 也有不同,但有相似 绝句也是模板语言,可是它的功能比普通的模板语言要多,而且支持 2D 文法,所以 templet 的这种语法: <p> {{$1==1}} <code>一等一</code> 是正确的,所以我显示出来啦 {{/1==1}} </p> <p> {{$变量一==变量二}} <code>变量一==变量二</code>…
This media is not supported in your browser
VIEW IN TELEGRAM
看到前端们的 HTML, CSS, JS, CSS 动画,又被自己菜自闭了。
勉强仗着自己还会点 HTML、SGML,会使用 DOM 以及能够抽象/符号化/结构化分析问题以及比别人快点,往往能和作者共意稍微有点好转的倾向...
duangsuse 在抽象分析的时候稍微看得清那些眼花缭乱的 API 使用、存储和算法结构一些
啥时候我要去写点前端。
勉强仗着自己还会点 HTML、SGML,会使用 DOM 以及能够抽象/符号化/结构化分析问题以及比别人快点,往往能和作者共意稍微有点好转的倾向...
duangsuse 在抽象分析的时候稍微看得清那些眼花缭乱的 API 使用、存储和算法结构一些
啥时候我要去写点前端。
#dev #pl #cs #story https://github.com/audreyt/lingua-sinica-perlyuyan/blob/master/Changes
https://github.com/ybay/yZhPy/blob/master/plugcn.py
https://github.com/ybay/yZhPy/blob/master/plugcn.py
GitHub
audreyt/lingua-sinica-perlyuyan
Perl in Classical Chinese in Perl. Contribute to audreyt/lingua-sinica-perlyuyan development by creating an account on GitHub.
duangsuse::Echo
写的太多不知从何说起... 时间还是不够啊 我不是把时间给虵(shé 🐸)了... QAQ 就先说绝句、二进制和字符流 Parser 框架 这些最令人 excited 的玩意 Parser 框架我还打算自己手写这些算法: TrieTree (只需要 Trie,因为只是字符流嘛,Radix 树还不如自己手动 maybe 匹配解析... 虽然那样好像没有优化了) RangeMap (到学校里想了会,发现还真不是那么简单的,滚动歌词什么的还真是可以简单点,但是 RangeMap 可以启用二分查找技术和区间碰撞检测,进而可以实现…
所以说,我觉得要完成这些类,才能做一个比较好的解析器框架:
== 数据结构和算法部分
TrieTree
CharTrieTree
RangeMap
LinearRangeMap
HashRangeMap
BsearchRangeMap
FuzzyCollisionRangeMap
CollisionRangeMap
NestedRangeMap
VersionizedMap
CollisionVersionizedMap
MultiMap
ReverseIndexedMultiMap
NaiveMap (就是简化掉一些非关键方法的 java.util.Map 外加一些静态辅助函数)
ArrayMap
== 辅助类部分
Pair
Range
MixedArrayLinkList
MixedArrayHashMap
RandomReadStream
StringView
MRL (Media Resource Locator)
== 框架部分
Identifible
SourceManager
SourceLocation
BinaryLocation
OffsetRange
InlineDoc
Comment
Spaces
PositionMarker
— exception
ReadError
OpenError
DecodeError
ParseError
WriteError
AllocationError
— matcher
Parser
Matcher
RepeatResult
SequenceResult
BranchResult
— text
TextInputStream
TextOutputStream
CharsetInputReader
TextInputOperator
TextCombinator
— binary
ByteOrdDataInput
OrderedDataInput
ByteOrdDataOutput
OrderedDataOutput
BinaryProcessor
StructReader
StructWriter
— annotation
BinaryStruct
Aligned ByteOrder Encoding
Let Repeats Skip Size
— unsigned
ubyte ushort uint ulong
== 数据结构和算法部分
TrieTree
CharTrieTree
RangeMap
LinearRangeMap
HashRangeMap
BsearchRangeMap
FuzzyCollisionRangeMap
CollisionRangeMap
NestedRangeMap
VersionizedMap
CollisionVersionizedMap
MultiMap
ReverseIndexedMultiMap
NaiveMap (就是简化掉一些非关键方法的 java.util.Map 外加一些静态辅助函数)
ArrayMap
== 辅助类部分
Pair
Range
MixedArrayLinkList
MixedArrayHashMap
RandomReadStream
StringView
MRL (Media Resource Locator)
== 框架部分
Identifible
SourceManager
SourceLocation
BinaryLocation
OffsetRange
InlineDoc
Comment
Spaces
PositionMarker
— exception
ReadError
OpenError
DecodeError
ParseError
WriteError
AllocationError
— matcher
Parser
Matcher
RepeatResult
SequenceResult
BranchResult
— text
TextInputStream
TextOutputStream
CharsetInputReader
TextInputOperator
TextCombinator
— binary
ByteOrdDataInput
OrderedDataInput
ByteOrdDataOutput
OrderedDataOutput
BinaryProcessor
StructReader
StructWriter
— annotation
BinaryStruct
Aligned ByteOrder Encoding
Let Repeats Skip Size
— unsigned
ubyte ushort uint ulong
#code #Java #Android 学到了 Androidx 的四个辅助 annotation
@NonNull @Nullable
@RestrictTo(RestrictTo.Scope)
@RequireApi(android.os.Build.VERSION_CODES)
@NonNull @Nullable
@RestrictTo(RestrictTo.Scope)
@RequireApi(android.os.Build.VERSION_CODES)
duangsuse::Echo
所以说,我觉得要完成这些类,才能做一个比较好的解析器框架: == 数据结构和算法部分 TrieTree CharTrieTree RangeMap LinearRangeMap HashRangeMap BsearchRangeMap FuzzyCollisionRangeMap CollisionRangeMap NestedRangeMap VersionizedMap CollisionVersionizedMap MultiMap Rev…
由于时间不够(6 点左右要走的,和虵 🐸 的时间不够是不一样的,我还有很多自己的时间)
只能写一些关于 Binary Stream Processing 的类了,此外我还会顺手练习一下 #Haskell 的 parser combinators (写个 JSON 解析器?)
这样一部分包括
Range
MultiMap
ReverseIndexedMultiMap
RandomReadStream
RandomReadStream.BinaryView
MRL
Identifible
SourceManager
BinaryLocation
OffsetRange
PositionMarker
ReadError
OpenError
DecodeError
ParseError
WriteError
AllocationError
ByteOrdDataInput
OrderedDataInput
ByteOrdDataOutput
OrderedDataOutput
BinaryProcessor
StructReader
StructWriter
BinaryStruct
Aligned ByteOrder Encoding
Let Repeats Skip Size
ubyte ushort uint ulong
只能写一些关于 Binary Stream Processing 的类了,此外我还会顺手练习一下 #Haskell 的 parser combinators (写个 JSON 解析器?)
这样一部分包括
Range
MultiMap
ReverseIndexedMultiMap
RandomReadStream
RandomReadStream.BinaryView
MRL
Identifible
SourceManager
BinaryLocation
OffsetRange
PositionMarker
ReadError
OpenError
DecodeError
ParseError
WriteError
AllocationError
ByteOrdDataInput
OrderedDataInput
ByteOrdDataOutput
OrderedDataOutput
BinaryProcessor
StructReader
StructWriter
BinaryStruct
Aligned ByteOrder Encoding
Let Repeats Skip Size
ubyte ushort uint ulong
#Haskell... Haskell 的 Text.ParserCombinators.ReadP 的 operator 还真多... 我的根本比不上... 弄了半天我连怎么解析二元运算符都忘了,唉,当入门吧...
duangsuse::Echo
虽然求值算法是递归的,但是解析的... 我暂时写不好 ReadP 解析嵌套二元运算... 所以先放着吧...
[DuangSUSE@duangsuse]~/Projects% ./Calculator
1+1
(1 + 1) = 2
2+2
(2 + 2) = 4
4/2
(4 / 2) = 2
400*100
(400 * 100) = 40000
0-1
(0 - 1) = -1
目前只能这么玩。。。。