解析程式碼的利器 Spp 語法描述語言
MySpp 是什麼?
這是一個處理文字,尤其是處理計算機程式碼的工具,它能根據描述的語法,將文字轉換成指定的資料結構。
它比 Antlr 更高效,也更靈活:
> myspp grammar text.file > ast.json
Myspp 不需要生成中間程式碼,直接生成資料結構。
Myspp 有什麼用
設計 Myspp 是為了描述計算機語言的語法,所以 Myspp 最適合解析程式碼。
當程式碼可以被解析成資料結構的時候,程式碼本身就成了資料。可以用各種演算法修改,計算,擴充套件,改變這個資料結構,然後再寫成程式碼的時候,我們就完成了一件讓人興奮的事情:
我們可以寫能寫程式碼的程式碼
演算法可以被儲存,交換
計算機語言有非常複雜的語法形式,所以說,能夠解析程式碼的工具,能解析大部分的文字。即使是自然語言,有許多的根據上下文而改變的語法,也能用 Myspp 來處理。
Myspp 已經做過什麼專案
這個專案本身就是用 Myspp 完成的,所有的演算法,都是用一種叫做 MyLang 的語言書寫,然後使用 Myspp 解析演算法,生成語法樹,再生成執行程式碼。
工具的安裝
從網站上下載一個可執行檔案 spp,根據不同的可執行檔案
https://www.gitee.com:str/myspp.git
> spp
This is Spp (String Prepare Parser)
Copyright C 2018-2020 Songzhiquan
MySpp 包含兩種語言 Spp, MyLang.
Spp (String Prepare Parser) 字串前處理器
Spp 是一種用於描述文字的語法的語言,MySpp 會依據語法對文字進行解析,如果符合語法定義,就會輸出描述文字結構的 Json 資料格式。如果文字不符合語法,就會有一個匹配錯誤的提示。
匹配捕獲的可能資料格式
- Fail 匹配失敗
- Pass 匹配成功
- String 字串
Atom 命名捕獲單元
name + string | atom | atoms + at ["name", "value", "12"]
Atoms 命名捕獲單元序列
Spp 的語法是一種上下文無關的語法,適合對計算機語言進行解析,生成語法樹。
Spp 的基本格式,這也是 Spp 的自我描述:
top = +[ :s _comment spec ] ; _comment = '#' ~ :v ; spec = @define [':' '='] @rules [ ';' $ ] ; @define = token ? token ; token = +[ '@' :a ] ; @rules = +[ :s @rule ] ; @rule = [ @order @group cclass not till str more many maybe token any eof ] ; @order = '[' +[ :s @rule ] ']' ; @group = '(' +[ :s @rule ] ')' ; str = [ ( "'" ~ "'") ( '"' ~ '"' ) ] ; cclass = ':' :a ; not = '!' @rule ; till = '~' @rule ; more = '+' @rule ; many = '*' @rule ; maybe = '?' @rule ; keyword = '<' token ':' token '>' any = '.' ; eof = '$' ;
Spp 語言描述的語法 ( grammar ) 由許多規則 ( specification ) 組成。
spec-one = rules-one ;
spec-two = rukes-two ;
規則包括規則名稱 (spec-name) 和規則描述 (rules):
規則名稱由一個可選的修飾符和規則名稱組成:
下面的組合是等價的:
a = :a ;
ntoken a = :a ;
_a = :a ;
rtoken _a = :a ;
@a = :a ;
gtoken @a = :a ;
Spp 語言的基本單元
Spp 語言的規則是由以下基本單元組成的:
rules 規則串
rule1 rule2 rule3
一個以上規則的串聯,逐一全部匹配才算匹配,規則之間忽略空白。
group 分組
(rule1 rule2 rule3)
和 rules 相同, 用於在 rules 改變規則的優先順序。
branch 分支
[case1 case2 case3]
一個以上的規則,按照先後順序,只要匹配之中的任何一個,就算匹配。
string 字串
"abc" 'abc'
token 規則名稱
token @token _token
gtoken (group token) 以 @開始的 token
@gtoken
如果匹配到的不是 atoms (atom 的序列), 就會直接返回匹配結果。
- rtoken (reject token)
如果匹配成功,不管匹配到的是什麼,都會丟棄匹配結果,返回匹配成功或失敗的標誌。常用來處理註釋。
迴圈匹配 rept match
more 要至少匹配 1 次,儘可能多。
+rule
many 不匹配也算匹配,儘可能多
*rule
maybe 不匹配也算匹配,只能匹配一次
?rule
匹配否定 not
! rule
如果匹配成功,則返回失敗標誌。因為所有的規則都是非回溯的,所以 not 可以針對任何規則,包括 not 本身
對字元組的否定,就是正規表示式中常見的一種結構 [^...]
![ :a :b :c ]
any 任意字元 用點表示
any = '.'
說是任意字元,其實它並不會匹配文字的末尾,只有 eof 可以匹配文字的末尾。除此之外,它會匹配任何文字內的字元。
eof 檔案結束標記 用美元符號表示
$
開始設計語法
> spp spp
>> Spp <top> Repl, type 'exit' to exit!
>>>
這個專案定義了一種名字叫做 Spp 的語言,用來描述計算機語言的語法:
door = +[ _s spec ] ;
_s = [ +:s _comm ] ;
_comm = '#' ~ :v ;
spec = name ':' rules ;
Spp 可以描述任何計算機語言,包括描述語法的語言,例如 Antl 的 g4, EBNF 等。
Spp 語言的基本單元
Spp 語言定義了一系列規則,用以描述文字。
rules 規則串
rule1 rule2 rule3
許多規則的串聯,逐一匹配才算匹配,規則之間忽略空白。
group 分組
(rule1 rule2 rule3)
和 rules 相同,不過 rule 之間不會自動忽略空白,也能改變規則的優先順序。
branch 分支
[ case1 case2 case3 ]
規則的分支,只要匹配之中的任何一個,就算匹配,沒有順序之分,因為可能會用並行演算法,同時對所有分支進行測試,最先返回的分支不一定是最前面的。
string 字串
"abc" 'abc '
cclass 字元類
:a [ :l :u '_' ]
:b ' '
:c '`'
:d '0' - '9'
:e '\'
:h [ ' ' '\t' ]
:l 'a' - 'z'
:n char \n
:r char \r
:s [ :b :n :r :t ]
:t char \t
:u 'A' - 'Z'
:v [ :n :r ]
:w [ :a :d '-' ]
:x [ :d 'a' - 'f' 'A' - 'F' ]
range 區間
標記一段字元的範圍是一種常見的字元規則定義方式。
digit = '0' - '9'
lower = 'a' - 'z'
token 規則變數
token @token _token Token
因著變數,讓語法描述能處理巢狀的和遞迴的結構,規則變數指向另外一個規則:
.. ntoken 命名token 字母開頭的 token
ntoken Ntoken
token 會對捕獲的內容進行命名,成為一種叫做 atom 的資料結構,它是用字串實現的。以為結構不能移植到許多動態語言上。
如果匹配成功,那麼就會返回:
[name match at] # at 是字串當前的位移
..gtoken (group token) 以 @開始的 token
@gtoken
如果匹配到的不是 atoms (atom 的陣列), 就會不命名直接返回。這種規則通常作為臨時規則,對其他規則的組合進行命名。但不會影響輸入的資料結構。
..rtoken (reject token)
如果匹配成功,不管匹配到的是什麼,都只會返回匹配成功的標誌。這種結構常用來處理註釋。
迴圈匹配 rept match
.. more 要至少匹配1次,儘可能多。
+ rule
.. many 不匹配也算匹配,儘可能多
* rule
.. maybe 不匹配也算匹配,只能匹配一次
匹配否定 not
! rule
如果匹配成功,則返回失敗標誌。因為所有的規則都是非回溯的,所以 not 可以針對任何規則,包括 not 本身
對字元組的否定,就是正規表示式中常見的一種結構 [^...]
![abc] == [^abc]
對字元類的否定: ! %w == %W
any 任意字元 用點表示
any = '.'
說是任意字元,其實它並不會匹配文字的末尾,只有 eof 會匹配。除此之外,它會匹配所以文字內的字元。
eof 檔案結束標記 用美元符號表示
$
eof 檔案結束標記,在匹配檔案的結尾。這樣就表示整個檔案都匹配完了。
相關文章
- Go 語言的詞法分析和語法分析(2)—Import宣告的解析Go詞法分析語法分析Import
- C 語言程式設計利器之 CLion程式設計
- gRPC 的介面描述語言 ProtoBuffer(二)RPC
- 程式語言語法:`=`表示賦值,`:`表示型別。賦值型別
- 1.7.1. ORAPWD 命令的語法和描述
- HTML語法大全_html語言語法大全(必看)HTML
- 計算機程式語言的分類,解釋型語言、編譯型語言、指令碼語言的關係計算機編譯指令碼
- 可用於解析 Excel 檔案的程式語言Excel
- 為什麼自制指令碼語言是程式語言的最高境界?指令碼
- 【譯】Go語言宣告語法Go
- Go 語言的詞法分析和語法分析(1)Go詞法分析語法分析
- C語言簡單程式碼程式C語言
- 題解1196:去掉空格 (C語言描述)C語言
- C 語言程式碼總結
- 用一句話描述Go語言的命令Go
- hanlp自然語言處理包的人名識別程式碼解析HanLP自然語言處理
- CSS語法檢查利器之csslintCSS
- 語法解析器續:case..when..語法解析計算
- 函數語言程式設計瞭解一下(JavaScript描述)函數程式設計JavaScript
- Smali 語法解析 —— 類
- Xpath解析及其語法
- c語言if語句是如何變成彙編程式碼的?C語言
- 聊聊C語言/C++—程式和程式語言C語言C++
- 現代編譯原理C語言描述pdf編譯原理C語言
- 如何只靠語言描述整個遊戲?遊戲
- React原始碼解析(1):jsx語法是如何解析React原始碼JS
- C語言:一種高效、易學的程式語言C語言
- Dart語言詳解(二)——基本語法Dart
- Go語言基礎語法總結Go
- Python語言的常用語法都有哪些?快來看!Python
- 六十行程式碼完成 四則運算 語法解析器行程
- PLSQL程式語言SQL
- sql程式語言SQL
- 高階程式設計師——java語言深度解析程式設計師Java
- 那些主流程式語言的知識,C語言(Ⅰ)C語言
- 程式語言的變遷
- 題解1197:發工資咯 (C語言描述)C語言
- 多語言網站利器 rel=”alternate” hreflang=”x”網站
- Nginx Location 指令語法解析Nginx