boost spirit 的一些記錄

2021-04-13 12:37:04 字數 2241 閱讀 8544

最近的工作跟 boost::spirit

多一些,本來想整理乙個較為系統的筆記,不過感覺目前思路還比較凌亂,先隨便記錄一些。

spirit 是 boost 中的乙個 ll解析器框架,他完成實現乙個 ebnf 語法解析器的功能,但它的輸入為c++語言。(ll parser framework  represents parsers directly as ebnf grammars in inlined c++, from joel de guzman and team),它可以與 lex ,yacc 進行模擬。lex 是生成詞法解析器的一種工具,它將符合 lex 語法的原始碼生成相應的 c **,通常,lex產生乙個成為yylex的函式,該函式接受乙個字串,並按照預定的詞法規則將其分段成一系列的 token,而 yacc 通常則使用 lex 產生的結果,按照預定的語法規則(ebnf語法),生成乙個成為 yyparse 的函式,它可以用於語法的解析。lex 和 yacc 分別有其不同語法格式,所以,使用 lex 和 yacc 的主要工作就是編寫相應的 lex 原始碼和 yacc 原始碼。有關 lex 和 yacc 的介紹可以參考這裡的文章 yacc 與 lex 快速入門

。spirit 則更像 yacc,它的創新之處在於,它使用普通的 c++ 語法來表達 ebnf,而這樣的表達是直接可以由c++編譯器編譯的。當然,出於 c++ 語法的限制,在一些細微的書寫上,spirit 還是與 ebnf 寫法略有不同,如一些標記的順序,一些連線符的處理等,但總的來說,spirit 的語法描述對於熟悉 ebnf 描述的程式設計師來說,還是很像的。

考慮對於乙個字串的數字陣列,我們希望用 spirit 解析出這個陣列

1,2,3,4,5,6,7,8,9

那麼,第一步,我們要描述出這個字串的格式,用 spirit 描述的結果是 real_p >> *(ch_p(',') >> real_p),real_p 表示乙個數字,括號表示將一些東西組合成一組,* 表示重複0或多次,這個描述用自然語言來說就是 數字跟著由 , 和 數字的組合0次或多次。

第二步,我們假設希望將這個解析到乙個 std::vector型別的陣列容器中以備後用。通過以下的**完成這個功能

bool parse_numbers(char const* str, vector& v)

parse 函式是 spirit 的乙個 api,它用於按照指定的語法規則解析乙個字串(未必是字串,乙個能夠通過 iterator 操作的容器都可以),注意上述**中加粗的中括號,它被稱為語義動作(semantic actions),上述語法描述的自然語言就是說,解析那個字串,當解析到乙個數字時,就把它插入到陣列容器 v 的後端。push_back_a 是 spirit 自帶的乙個標準語法動作,可以編寫自定義的語法動作,它可以是乙個函式或是乙個函子,如

void print(double d)

或struct printor

};對應的實現分別是

bool parse_numbers(char const* str)

bool parse_numbers(char const* str)

這將一行乙個數字將其列印到 stdout 上。

簡單的說,使用 spirit 的過程就是,1.按照你的語法規則用 spirit 的格式編寫語法宣告,2.編寫處理解析到某個元素的動作,3. 用 parse 函式將他們組合在一起。

這樣,學習使用 spirit 的第一步就是了解 spirit 編寫語法規則。spirit 的語法由 原子(primitives)(某種字元), 操作符(operators) 構成,原子通過操作符組合得到規則(rule),有一些規則被特化成原子,如數字(numrics)。

操作符 包括連線操作符 >> ,組合操作符 (),或操作符 |等。

還有一些被稱為指令(directives)的東西也可以放置在語法規則中,他們的作用事實上是一些特定的解析屬性,如將某一部分忽略大小寫,盡可能長的解析等。

事實上,你會發現,語法規則的編寫類似於編寫正規表示式,其實,他們本身就是一回事。

然後,你需要編寫語義動作,這個,spirit 沒有提供任給你多少幫助,語義動作的程式設計類似於基於視窗的gui程式設計,你編寫一些響應函式,並跟你你感興趣的事件註冊到一起,這樣,當某個事件發生時(spirit為解析到某個元素時),你的處理函式就會被呼叫。

最後,spirit 提供了多種型別的 parse 實現,他們有的只是簡單的返回乙個狀態告訴你解析是否成功,有的則為你生成一顆二叉樹,特別的,spirit 也提供了將解析結果表達成標準 ast (抽象語法樹)的 parse 實現。

記一些linux命令

1 備份並刪除原始檔 sudo cp etc apt sources.list etc apt sources.list.bak rm etc apt sources.list 2 插入阿里源 echo deb focal main restricted universe multiverse et...

記一些筆試題

思路 每乙個元素去與後面的元素去比較,只要相等就退出,說明已經找到第乙個重複的字元了。該字串沒有重複字元 例如 輸入 1,4,3,4,null,undefined,nan,null 輸出 6思路 將每乙個元素全部轉成字串,避免了null和undefined的影響。null undefined為tru...

記一些spring的aop中一些常用獲取引數的方法

如果aspect切點切入的是controller在spring mvc 的配置中加入 獲取request 與response 獲取方法與方法上的注釋 這個我主要是用joinpoint來獲取,獲取方式如下 signature signature joinpoint.getsignature metho...