研究算法,要解析语言。而语言的解析,是从设计语法开始的。Spp 语言就是描述语法的语言。
Spp 现有 5 种语言的实现,选择一个最熟悉的(Golang 最快):
https://gitee.com/str/go-spp
https://gitee.com/str/lua-spp
https://gitee.com/str/ruby-spp
https://gitee.com/str/perl-spp
https://gitee.com/str/python-spp
首先确保你的电脑里安装了 Golang 或其他语言的运行环境。 git 目录下有一个 Spp.go 的文件,下载下来, 在命令行里输入:
> go run Spp.go
This is Spp REPL, type enter to exit.
>>
好了,可以开始学习测试了.
>> Str -> 'abc'
["Str","'abc'"]
大家都看出来了,这似乎是 JSON, 是的,它是 JSON 的 一个子集,但没有 Object, true, false ...
>> Str -> "abc"
["String","\"abc\""]
>> Str -> :abc
["Kstr",":abc"]
是的,字符串有三种表达方式,主要是为了方便。
单引号包围的字符串中,不能出现单引号,如果出现,就要用就要用转义符号。
>> str -> 'abc\'\\'
["Str","'abc\\'\\\\'"]
同样双引号包围的字符串中,也不能出现双引号。
Char -> ' ["Char","\'"]
>> .
\l lowercase 小写字符 [a-z]
\u uppercase 大写字符 [A-Z]
\d digit 数字 [0-9]
\x xdigit 16进制数字 [\da-fA-F]
\s space 空白字符 [\t\n\r\b]
\v vspace 垂直空格 [\n\r]
\h hspace 水平空格 [\b\t]
\a alpha 普通字母 [a-zA-Z_]
\w words 单词字符 [\a\d-]
\t tab 制表符 chr(9)
\n Newline 换行 chr(10)
\r Creturn 回车 chr(13)
? 可有可无, 有一个或者是没有
+ 至少有一个条件匹配,无穷多也行
* 没有也行,但多多益善
(a b c)+
[abc]
[a-fA-F]
[^abc]
下面两种规则描述是相同的:
a -> b c
a -> b\s*c
blank 解析的效率非常高,不用担心效率的问题。 Branch 中的空格会被忽略,只是为了分隔不同的 Token.
三种命名规则:
捕获模式会对匹配成功的内容,以规则名为 Key, 加入到数据结构中:
Token = 'words'
# => ['Token','words']
小写字母开始的规则名,把捕获的文本,推送到之前生成的字符串序列之后, token 名称只是为了重用规则而命名:
Token -> name
name -> 'words'
# => ['Token','words']
下划线开始,会自动丢弃匹配的内容,通常处理注释:
_comment -> '#'~$
定义可选的匹配可能,每种可能都能匹配:
atom -> |Ntoken Mtoken Ctoken|
Ntoken -> \u\a*
Mtoken -> \l\a*
Ctoken -> '_'\a*
解析规则是由许多规则组合在一起,但总有一个规则的名字叫 door, 这个规则是所有规则的开始.
为何这样设计呢?
由于多条规则会被保存成 Hash, 而大部分语言的 Hash 都没有顺序,为保证能从指定 位置开始查找规则,所以对开始的规则进行了命名:
door -> 'string' rule door
rule -> "alsostr"
每条规则的回车表示规则结束, 除非在分支内 |...|。
规则的名字可以包含 '-', 但不能以 '-' 开始,以下的规则名都是合法的:
[\a\-]+ -a _a a-b A-B
在 Spp 中,字符和字符串不同,\n \r \t 的字符表示,是要用 \ 转义符前缀, 代码中用如下形式:
\n \r \t \\
但在捕获时,获取的是两个字符,内部 estr 保存时,还原成一个字符。 在 保存成 atom 时,也是原始状态,也就是 opt 时,变成原始字符。 在写成实际代码的时候,再恢复。
door -> |\s+ _comm Spec|+ $
_comm -> '#'~$$
Spec -> Token '->' rule
rule -> |Blank Branch atom|+|\v $|
Blank -> \h+
atom -> | Group Token Str String Kstr
Cclass Char Chclass Assert Any Rept Till |
Branch -> '|' | \s+ _comm atom |+ '|'
Group -> '{' | \s+ _comm Branch atom |+ '}'
Token -> [\a\-]+
Kstr -> ':'[\a\-]+
Str -> \'| [^\\']+ {\\.} |+\'
String -> \"| [^\\"]+ {\\.} |+\"
Cclass -> \\[adhlsuvwxADHLSUVWX]
Char -> \\.
Chclass -> \[ Flip?|\s Cclass Char Range Cchar|+ \]
Flip -> '^'
Range -> \w\-\w
Cchar -> [^ \s \] \# \\ ]
Assert -> | '^^' '$$' '^' '$' |
Any -> '.'
Rept -> [?*+]
Till -> '~'
(end)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型