开始
今天,我在使用自定义的配置文件语法时又发现了不足,那就是需要一种插值语法,可以减少很多重复。
比如,我有很多个字段都是http网址:
能不能不打这么多?答案是可以的,所以我设计了新语法————函数。
它类似ahk的api之Format
,但是只有插值{}
语法。
实现
在这里,我只给出它的一个demo,完成字符串的信息提取与动态的插值。
1. 语法
它的语法很简单,看下面的例子:
&fn(a, b) : http://{a}:{b}
vm : $fn(192.168.6.100, 8080)$
2. 解析
实际上,我们要关心的只有方法参数,与后面的方法体,即:
(a, b)
http://{a}:{b}
要做的是实现参数与方法体内变量位置的映射,比如上面的例子就是:
{
1 : 1 ; 方法体内第一个变量对应第一个参数
2 : 2 ; 同上
}
- 先从参数开始,我们要提取出参数名和对应的顺序:
def := '(a, b)'
def := StrReplace(def, A_Space)
if def[1] != '(' or def[-1] != ')'
MsgBox 'err'
def := def.substring(2, def.Length)
params := {}
StrSplit(def, ',').filter(v => v).foreach((v, i) => params[v] := i)
; MToString params
; => {a : 1, b : 2}
- 然后是方法体,需要提取出变量位置与还原出去除变量后的字符串:
body := 'http://{b}:{a}'
_pos := 1, idx := {}, post := ''
for i, v in body {
if v = '{' {
_pos := i
} else if v = '}' {
idx[idx.Length + 1] := body.substring(_pos + 1, i)
post := SubStr(post, 1, post.Length - i + _pos + 1)
}
post .= v
}
; MsgBox post
; => http://{}:{}
; MToString idx
; => { 1 : b, 2 : a}
- 第三步,建立映射关系
for k, v in idx.OwnProps() {
idx[k] := params[v]
}
; MToString idx
; => { 1 : 2, 2 : 1}
- 第四步,实现动态插值
这一步需要对ahk的语法十分了解。
__f__ := (_p*) => __f.Bind(post, idx, _p*)
MsgBox __f__(1, 2)()
__f(str, mapping, p*) {
i := 1, _chs := str.toChararray(), _r := '', _c := 1
while i + 1 <= _chs.Length {
if _chs[i] = '{' and _chs[i + 1] = '}' {
_r .= p[mapping[_c]], _c++, i++
} else _r .= _chs[i]
i++
}
return _r
}
最后,打印的结果就是:http://2:1
对应到配置文件语法就是下面这样:
; vm : $fn(2, 1)$
a := 2, b := 1
MsgBox __f__(a, b)()
标签:__,http,配置文件,idx,AHK2,语法,post,def
From: https://www.cnblogs.com/refiz/p/18343870