3 Star 4 Fork 2

str / go-spp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

语言解析的意义

研究算法,要解析语言。而语言的解析,是从设计语法开始的。Spp 语言就是描述语法的语言。

Spp 安装 (以 go 为例)

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.               
>>                                                  

好了,可以开始学习测试了.

Spp 基本语法

字符串:有两种表示方法

>> Str -> 'abc'
["Str","'abc'"]

大家都看出来了,这似乎是 JSON, 是的,它是 JSON 的 一个子集,但没有 Object, true, false ...

>> Str -> "abc"
["String","\"abc\""]

>> Str -> :abc
["Kstr",":abc"]

是的,字符串有三种表达方式,主要是为了方便。

单引号包围的字符串中,不能出现单引号,如果出现,就要用就要用转义符号。

>> str -> 'abc\'\\'
["Str","'abc\\'\\\\'"]

同样双引号包围的字符串中,也不能出现双引号。

字符:表示不可见字符

Char -> ' ["Char","\'"]

任何字符(any 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)

重复 rept

? 可有可无, 有一个或者是没有
+ 至少有一个条件匹配,无穷多也行
* 没有也行,但多多益善

分组 group: 用于重新定义规则的优先级

(a b c)+

字符类 Char Class: 字符的分支

[abc]
[a-fA-F]
[^abc]

blank 可以存在的空格,在规则之间的空格代表:

下面两种规则描述是相同的:

a -> b c
a -> b\s*c

blank 解析的效率非常高,不用担心效率的问题。 Branch 中的空格会被忽略,只是为了分隔不同的 Token.

Token 命名规则

三种命名规则:

捕获规则 (capture Token) 大写字母开始的规则名,

捕获模式会对匹配成功的内容,以规则名为 Key, 加入到数据结构中:

Token = 'words' 
# => ['Token','words']

匹配规则 (match mode)

小写字母开始的规则名,把捕获的文本,推送到之前生成的字符串序列之后, token 名称只是为了重用规则而命名:

Token -> name
name  -> 'words'
# => ['Token','words']

丢弃模式 (reject mode)

下划线开始,会自动丢弃匹配的内容,通常处理注释:

_comment -> '#'~$

分支 branch:

定义可选的匹配可能,每种可能都能匹配:

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)

空文件

简介

Golang 实现的 Spp 展开 收起
Go
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Go
1
https://gitee.com/str/go-spp.git
git@gitee.com:str/go-spp.git
str
go-spp
go-spp
master

搜索帮助