日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

扩展iQuery使其支持多种编程语言(二) – 兼编译器的语法分析简介

發(fā)布時間:2024/4/11 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 扩展iQuery使其支持多种编程语言(二) – 兼编译器的语法分析简介 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

iQuery是一個開源的自動化測試框架項目,有興趣的朋友可以在這里下載:https://github.com/vowei/iQuery/downloads

源碼位置:https://github.com/vowei/iQuery

在上一篇文章中,簡單介紹了iQuery解析器的詞法分析部分,本文接著將語法分析部分解釋完畢,閱讀完本文后,應該可以將iQuery擴展到其他編程語言上。

下面是iQuery的完整語法(其實可以把它當作一個廣義的正則表達式對待):
https://github.com/vowei/iQuery/blob/master/iQuery.g

antlr支持EBNF語法,也就是說它支持可選和重復的元素,如:

1: selectors 2: : multi_selectors multi_selectors* 3: ; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

上面的語法表示selectors由一到多個multi_selectors組成,因為在EBNF語法里,沒有類似正則表達式的“+”號操作符,所以使用“multi_selectors multi_selectors*”這種形式描述。

而:

1: selector 2: : selector_expression 3: ( 4: ('+' selector_expression) 5: | 6: ('~' selector_expression) 7: )? 8: ; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
這個語法表示selector這個元素的組成部分,是selector_expression后面要么跟有“('+' selector_expression)”,要么跟有“('~' selector_expression)”,要么后面什么也不跟 -“?”號的作用。

在antlr里,語法定義的規(guī)則一般是,小寫字母組成的單詞是語法的組成部份,而標記(Token)都是由大寫字母組成,如:

1: selector_expression 2: : atom 3: | ':' indexop '(' INTEGER ')' 4: | ':' NOT '(' selectors ')' 5: | ':' HAS '(' selectors ')' 6: | ':' CONTAINS '(' QUOTED_STRING ')' 7: …. 8: ; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

上面的語法里,大寫的字母例如“INTEGER”、“NOT”、“HAS”、“CONTAINS”和“QUOTED_STRING”都是標記(Token),這些標記都是從詞法分析器解析完輸入字符串之后產(chǎn)生的標記流中得到。而小寫字母組成的單詞例如“selector_expression”、“atom”、“indexop”和“selectors”都是語法的組成部份,這些元素的定義都可以在語法定義源文件中找到。

Antlr生成的語法解析器是一個LL(*)的編譯器,LL類型的編譯器是一個自頂向下進行語法分析的編譯器,這種編譯方式跟手寫編譯器進行語法解析的方式很像,因此相對于yacc等LR類型(自底向上)的編譯器更容易理解。

比如說,以“#ABC”這個iQuery查詢語句為例,antlr生成的解析器,也就是iQuery解釋器碰到這個字符串以后,它依照一個自頂向下的順序進行語法匹配:

1.??? 首先從“query”這個語法元素開始,由于“query”元素的兩個子元素只有第一個“selectors NEWLINE* EOF”成功匹配(這是因為第二個元素的開頭就是換行符,跟“#ABC”無法匹配),所以解析器再接著進入“selectors”的定義嘗試匹配。
2.??? “selectors”的定義里“multi_selectors”也僅僅是一個語法元素,里面沒有任何詞法標記(Token),因此解析器遞歸向下匹配語法元素,匹配順序如下:

query -> selectors -> multi_selectors -> selector -> selector_expression
3.??? 當匹配到selector_expression時,因為其可選的語法子句里有詞法標記,而且“# ELEMENT”可以完全匹配“#ABC”這個輸入字符串,這樣在selector_expression處就成功匹配了輸入字符串,并且“selector_expression”沒有更多的語法規(guī)則需要輸入字符串匹配,因此解析器退出“selector_expression”這個語法規(guī)則,發(fā)現(xiàn)上一層規(guī)則“selector”也沒有更多的語法規(guī)則需要匹配,遞歸上溯,直到“query”規(guī)則。
4.??? 在“query”規(guī)則里,匹配完“selector”子規(guī)則后,后一個是可選的換行符 - “NEWLINE*”,由于輸入字符串中沒有換行符,所以跳過這個規(guī)則,碰到最后一個規(guī)則“EOF”-表示字符串或者文件的結尾。因為在“selector_expression”里已經(jīng)由“’#’ ELEMENT”匹配完整個字符串了,沒有更多的字符留下。到這里,語法解析器就認為執(zhí)行了一次成功的匹配,而輸入字符串“#ABC”是一個合法的輸入。


比如說,針對“> :first [‘value’]”這個查詢,iQuery解析器依照自頂向下的方式進行匹配:

1.??? 首先匹配字符“>”,匹配順序是“query”-> “selectors” -> “multi_selectors”-> “'>’ selector”。
2.??? 匹配到“'>’ selector”這個規(guī)則時,因為“'>’”后面必須跟一個滿足“selector”規(guī)則的字符串。
3.??? 解析器繼續(xù)用“:first [‘value’]”試圖匹配“selector”這個規(guī)則,這時的匹配順序是“selector” -> “selector_expression”-> “’:’ FIRST”。
4.??? “’:’ FIRST”這個規(guī)則消化掉“:first”字符串,由于輸入的iQuery字符串還剩下“[‘value’]”,而“selector_expression”規(guī)則已經(jīng)沒有多余的子規(guī)則了,解析器上溯,上溯的順序是:“selector_expression” -> “'>' selector”-> “multi_selectors”-> “selectors”。
5.??? 在“selectors”這個語法規(guī)則里,前面的匹配步驟只消化掉“multi_selectors multi_selectors*”里的第一個規(guī)則“multi_selectors”,還剩下第二個規(guī)則“multi_selectors*”沒有匹配,因此解析器使用輸入字符串剩下的字符匹配第二個規(guī)則。
6.??? 匹配的順序是:“multi_selectors” -> “selector” -> “multi_attributes” -> “'['”。
7.??? 在這次匹配過程中,由于剩下的字符串是“[‘value’]”(注意value周邊的單引號),沒有任何一個“multi_attributes”的子規(guī)則匹配這段字符串,而且也無法回溯,因此一個語法錯誤發(fā)生了,解析器會拋出一個語法錯誤的異常信息,這個異常信息有點晦澀,需要做二次處理才能讓iQuery使用者明白語法錯誤原因 – 語法錯誤的處理在后文會講到。

從上面關于語法匹配的描述可以看出,這個過程跟一個函數(shù)遞歸調用非常類似,實際上,對于語法定義文件中的每一個語法規(guī)則(例如“query”、“multi_selectors”等規(guī)則),antlr都會為其生成一個函數(shù)調用(例如函數(shù)query()、multi_selectors()等,而且antlr還提供了給生成的函數(shù)傳入?yún)?shù),設置和獲取函數(shù)返回值的手段,參數(shù)的聲明語法跟指定語言的語法是一致的。

好了,語法方面的解釋就暫時寫到這里,下文講解Java版和JavaScript版的iQuery解析器的具體實現(xiàn)。

本文由知平軟件 施懿民編寫,請關注我們的微博。

轉載于:https://blog.51cto.com/4977661/980406

總結

以上是生活随笔為你收集整理的扩展iQuery使其支持多种编程语言(二) – 兼编译器的语法分析简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。