const p = require('./fp').parserc;
let __ = p.wsP(), _ = p.ws0P();
function NumList(l, ws0, rxs) {
this.wss = []; this.ary = [];
this.wss.push(ws0); // {ws0} x...
if (rxs === ']') { return; }
this.ary.push(rxs[0]); this.wss.push(rxs[1]); // x {a}, y, ..
for (let [wl, x, wr] of rxs[2]) { this.ary.push(x); this.wss.push(wl, wr); }
}
let numP = p.someFold(p.elemP('0123456789'.split(''), 'digit'), [0, (a,x) => a*10+(x-'0')], f => 'number value expected');
let pa = p.seq([p.charP(','), _, numP, _], xs => [xs[1], xs[2], xs[3]]);
let List_ItemsP = p.manyFold(pa, [p.makeNew(Array), (v,xs)=>{v.push(xs); return v;}]);
let ListP = p.seq([ p.charP('['), _, p.possible([ p.charP(']'), p.seq([numP, _, List_ItemsP, p.charP(']')]) ]) ], p.makeNew(NumList));
pp = p.run(ListP); 尾逗号的问题是正常情况,因为这个毕竟是 manyFold, 解析到不能匹配了就 fail... 第一个 charP 还是可以解析那个尾逗号的
如果需要不支持尾逗号的话,还需语法变形才行...(当然你也可以设置 pa 的 msgr 为直接 throw error 的那种,所有组合基本都只会 handle pfail,不会 handle msgr 抛出的 exception)
/tmp/duangsuse.sock
const p = require('./fp').parserc; let __ = p.wsP(), _ = p.ws0P(); function NumList(l, ws0, rxs) { this.wss = []; this.ary = []; this.wss.push(ws0); // {ws0} x... if (rxs === ']') { return; } this.ary.push(rxs[0]); this.wss.push(rxs[1]); // x {a}…
🤔 JavaScript 不能 copy... 好麻烦哦,我只好弄个函数 来帮忙造新 Array... 毕竟不能一直用一个实例去折叠...
/tmp/duangsuse.sock
那咱来看一下这个 继续 🐱 我们刚才说道了第一个组合解析器 — seq 函数,现在测试一下 首先,你需要同步 FP.js 库的版本,以引入新的一些抽象操作 const p = require('./fp').parserc; function DefItem(_d, w0, name, w1, _eq, w2, val) { this.wss = [w0, w1, w2]; this.name = name; this.value = val; } ps = p.seq([p.kwP('def')…
有了这些语法定义和之前对
用啥 XML 呢???万能的 XML。
幸运的是,这意味着你已经可以编写 GeekSpec 这样的 DSL 了!(记得 GeekSpec 可是把之前需要两天的『劳动密集』繁复任务量,缩减到了两个小时!)可能过一段时间我会再写更多的,甚至实现一个 ES5 (JavaScript)的解析器... 之前本频道也有教写计算器(动态二元运算符优先级解析程序)什么的
下面我只发实现,如果你还不知道怎么做,请复习一下刚才的内容,动手实践一下
如果还不知道的话,大概是需要时间理解了。
def abc = 123 \ [1,2,3,4] 的解析程序,我们现在已经可以实现这样的语法了:TheDefLang = {{ Def }}
Def = (<def> Name <=> Value NL) | (<lets> Name Name) | (<just> Name)
NL = '\n'|'\r'
Letter = ('a'~'z'|'A'~'Z'|'_')
Digit = ('0'~'9')
Name = Letter (Letter|Digit)*
Value = Bool | Num | Str | Name | Array | Map
Bool = <true> | <false>
Num = Digit+
Str = <"> char* <">
Array = <[> (<]> | Value { <,> Value } <]>)
KVPair = Name <:> Value
Map = <{> (<}> | { KVPair { <;> KVPair } <}>)
Def 语言是一门简单的数据描述语言,你可以定义(全局)变量、引用变量、赋值变量、返回变量。用啥 XML 呢???万能的 XML。
幸运的是,这意味着你已经可以编写 GeekSpec 这样的 DSL 了!(记得 GeekSpec 可是把之前需要两天的『劳动密集』繁复任务量,缩减到了两个小时!)可能过一段时间我会再写更多的,甚至实现一个 ES5 (JavaScript)的解析器... 之前本频道也有教写计算器(动态二元运算符优先级解析程序)什么的
下面我只发实现,如果你还不知道怎么做,请复习一下刚才的内容,动手实践一下
如果还不知道的话,大概是需要时间理解了。
酷 壳 - CoolShell
信XML,得自信 | | 酷 壳 - CoolShell
XML可能是计算有史以来最NB的发明了,以至于我们以没有XML的程序是难登大堂的程序,不用XML,你都不好意思当程序员。于是,我们看到了很多很雷人的用法(《信XML,得永生》),当然一些朋友当时并没有看懂,不过我不怪大家,因为我们依然深信使用XML可以让你有强大的Zhuangbility,于是我们有下面这两种相当Geiliable的用法。 一、XML中的XML 这个例子是某公司的一个SOAP实现—
/tmp/duangsuse.sock
有了这些语法定义和之前对 def abc = 123 \ [1,2,3,4] 的解析程序,我们现在已经可以实现这样的语法了: TheDefLang = {{ Def }} Def = (<def> Name <=> Value NL) | (<lets> Name Name) | (<just> Name) NL = '\n'|'\r' Letter = ('a'~'z'|'A'~'Z'|'_') Digit = ('0'~'9') Name = Letter (Letter|Digit)* Value…
那个.... 为了演示方便(REPL 的话也行,因为这门语言不需要跨行的语句)
就只做 Def 本身的解析器
也方便大家学习一些(虽然第一次写,所以写的不怎么样)
就只做 Def 本身的解析器
Term 了 😽也方便大家学习一些(虽然第一次写,所以写的不怎么样)
Forwarded from 💊 辣鸡咕鸽毁我信仰 #CurryMyLife (Elepooooover | 是🐳 | 🏳️🌈 | see.wtf)
Google 电话应用将允许用户在不说话的情况下向 911 接线员发送信息
https://www.xda-developers.com/google-pixel-phone-911-no-talking/
挺好的功能,国内就别指望了(废话)
https://www.xda-developers.com/google-pixel-phone-911-no-talking/
挺好的功能,国内就别指望了(废话)
xda-developers
Google Pixel’s Phone app will soon let you send info to 911 without talking
The Google Pixel's phone app will soon allow you to send information to 911 without talking, such as the nature of your emergency and your location.
/tmp/duangsuse.sock
第一个完全自己写的数据描述语言? 🤔 编写的直播到此就 告一段落了,接下来是一些语言工具设计的考虑。
三个附加项目 —
0. 如何实现 DEF 语言的 AST Walker 求值器
1. 如何实现 DEF 语言的 REPL(不包含如何给 LookAhead1 流加不需要打两个 <NEWLINE> 即可求值的技术,因为我也不知道,好像很困难或者不容易零开销\太具侵入式)
2. 如何实现 DEF 语言的自动格式化 — 包含两种
一种是直接从 AST 输出、一种是检查 & 自动化提供矫正方案(在某个位置删除几个空格)
0. 如何实现 DEF 语言的 AST Walker 求值器
1. 如何实现 DEF 语言的 REPL(不包含如何给 LookAhead1 流加不需要打两个 <NEWLINE> 即可求值的技术,因为我也不知道,好像很困难或者不容易零开销\太具侵入式)
2. 如何实现 DEF 语言的自动格式化 — 包含两种
一种是直接从 AST 输出、一种是检查 & 自动化提供矫正方案(在某个位置删除几个空格)
首先是咱们的求值器,咱的复用解析器,已经被作为一个 CommonJS 模块包装好了。
下面来科普下,怎么写简单的求值器 — 就是后序遍历语法树。
为什么我们要自顶向下、从左到右解析这个代码呢?因为代码存在诸多分支和不确定,右边最终 reduce 出的结构可能依赖左边的输入字符来决定。LookAhead(1) 也是这个原因(因为不允许重置流,但有时候如果没有手段去重置的话,很多语法哪怕是 "" 字符串都几乎不能实现)
为什么我们要后序遍历语法树?
求值的顺序(AST Walker 对语法树遍历,或者说扩普排序的顺序)有关系吗?
如果保证所有节点都是『纯』的,它不依赖也不改变外部的环境(不是说对子节点的那种『值』的依赖)
则求值序实际上关系不大,因为只有对值本身的依赖
后序是什么意思?
语法的属性上,有综合节点和继承节点的说法:前者的『值』依赖自己的子节点;后者的『值』依赖自己的父节点
因为大部分节点都会依赖自己子节点的值,所以往往要先求值子节点、再父节点
所以要先算子节点,在依据孙子们的值,去解决爸爸(跑
— 所以应该怎么写
咱只需一席话语,̶饶̶舌(跑
考虑一下咱的实际语法,归纳一下呗。然后定义一个抽象语义。
我们的 Entry 是 Term — 就是一个 def|lets|just 项目
我们认为,这些东西的语义应该是『对数据结构进行组织』
所以:
def name = value 没有值,但是有一个副作用 — 把 value 赋值到全局环境的 name
lets name funame 没有值,但是有一个副作用 —
Value:
Name ident 的值是 Global[ident]
Bool 的值是 true / false
Num 的值是 Number 数字
Str 的值是 String
List 的值是 Array
KvList 的值是 Object
就这样,我们的求值程序的目标是逐条语句执行这些代码,操作全局状态机;最终输出
下面来科普下,怎么写简单的求值器 — 就是后序遍历语法树。
为什么我们要自顶向下、从左到右解析这个代码呢?因为代码存在诸多分支和不确定,右边最终 reduce 出的结构可能依赖左边的输入字符来决定。LookAhead(1) 也是这个原因(因为不允许重置流,但有时候如果没有手段去重置的话,很多语法哪怕是 "" 字符串都几乎不能实现)
为什么我们要后序遍历语法树?
求值的顺序(AST Walker 对语法树遍历,或者说扩普排序的顺序)有关系吗?
如果保证所有节点都是『纯』的,它不依赖也不改变外部的环境(不是说对子节点的那种『值』的依赖)
则求值序实际上关系不大,因为只有对值本身的依赖
后序是什么意思?
语法的属性上,有综合节点和继承节点的说法:前者的『值』依赖自己的子节点;后者的『值』依赖自己的父节点
因为大部分节点都会依赖自己子节点的值,所以往往要先求值子节点、再父节点
data Add = Lit Int | Add (Add, Add)— edit: 之前误把这个 Add 定义成
sum :: Add -> Int
sum (Add a, Add b) = sum a + sum b
sum (Lit x) = x
newtype (single product) 了,我没主意到它其实是 sum type(tagged union)... 现在已经修复 致歉所以要先算子节点,在依据孙子们的值,去解决爸爸(跑
— 所以应该怎么写
咱只需一席话语,̶饶̶舌(跑
考虑一下咱的实际语法,归纳一下呗。然后定义一个抽象语义。
我们的 Entry 是 Term — 就是一个 def|lets|just 项目
Term = DefT | LetsT | JustT
DefT = 'def' _ Name '=' Value
letter = [a-zA-Z_]
digit = [0-9]
Name = letter (letter | digit)*
Value = Name | Bool | Num | Str | List | KvList
Bool(Name) = "true" | "false"
Num = digit+
Str = '"' [any ->]* '"' -- '->' 的意思是 [any - '"']*
ListItems = (',' Value)*
List = '[' ( ']' | Value ListItems ']' )
KvPair = Value ':' Value
KvListItems = ( (','|';') KvPair)*
KvList = '{' ( '}' | KvPair KvListItems '}' )
LetsT = 'lets' Name Name
JustT = 'just' Name 我们认为,这些东西的语义应该是『对数据结构进行组织』
所以:
def name = value 没有值,但是有一个副作用 — 把 value 赋值到全局环境的 name
lets name funame 没有值,但是有一个副作用 —
Global[name] = getFun(funame) (Global[name])
just name 没有值,但它把 Global[name] 推入输出值列表Value:
Name ident 的值是 Global[ident]
Bool 的值是 true / false
Num 的值是 Number 数字
Str 的值是 String
List 的值是 Array
KvList 的值是 Object
就这样,我们的求值程序的目标是逐条语句执行这些代码,操作全局状态机;最终输出
just 操作过的列表。