最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go Antlr重構(gòu)腳本解釋器實(shí)現(xiàn)示例

 更新時(shí)間:2022年08月08日 15:54:32   作者:crossoverJie  
這篇文章主要為大家介紹了go Antlr重構(gòu)腳本解釋器實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

在上一個(gè)版本實(shí)現(xiàn)的腳本解釋器 GScript 中實(shí)現(xiàn)了基本的四則運(yùn)算以及 AST 的生成。

當(dāng)我準(zhǔn)備再新增一個(gè) % 取模的運(yùn)算符時(shí),會(huì)發(fā)現(xiàn)工作很繁瑣而且?guī)缀醵际侵貜?fù)的;主要是兩步:

  • 需要在詞法解析器中新增對(duì) % 符號(hào)的支持。
  • 在語(yǔ)法解析器遍歷 AST 時(shí)對(duì) % token 實(shí)現(xiàn)具體邏輯。

其中的詞法解析和遍歷 AST 完全是重復(fù)工作,所以我們可否能夠簡(jiǎn)化這兩步呢?

Antlr

Antlr 就是做幫我們解決這些問(wèn)題的常用工具,利用它我們只需要編寫(xiě)詞法文件,然后就可以自動(dòng)生成詞法、語(yǔ)法解析器,并且可以生成不同語(yǔ)言的代碼。

下面以 GScript 的示例來(lái)看看 antlr 是如何幫我們生成詞法分析器的。

func TestGScriptVisitor_Visit_Lexer(t *testing.T) {
	expression := "(2+3) * 2"
	input := antlr.NewInputStream(expression)
	lexer := parser.NewGScriptLexer(input)
	for {
		t := lexer.NextToken()
		if t.GetTokenType() == antlr.TokenEOF {
			break
		}
		fmt.Printf("%s (%q) %d\n",
			lexer.SymbolicNames[t.GetTokenType()], t.GetText(),t.GetColumn())
	}
}
//output:
 ("(") 0
DECIMAL_LITERAL ("2") 1
PLUS ("+") 2
DECIMAL_LITERAL ("3") 3
 (")") 4
MULT ("*") 6
DECIMAL_LITERAL ("2") 8

Antlr 會(huì)自動(dòng)將我們的表達(dá)式解析為 token,遍歷 token 時(shí)還能拿到該 token 所在的代碼行數(shù)、位置等信息,在編譯期間做語(yǔ)法檢查非常有用。

要實(shí)現(xiàn)這些我們只需要編寫(xiě)詞法、語(yǔ)法規(guī)則文件即可。

剛才的示例所對(duì)應(yīng)的詞法、語(yǔ)法規(guī)則如下:

expr
    : '(' expr ')'                        #NestedExpr
    | liter=literal #Liter
    | lhs=expr bop=( MULT | DIV ) rhs=expr #MultDivExpr
    | lhs=expr bop=MOD rhs=expr            #ModExpr
    | lhs=expr bop=( PLUS | SUB ) rhs=expr #PlusSubExpr
    | expr bop=(LE | GE | GT | LT ) expr # GLe
    | expr bop=(EQUAL | NOTEQUAL) expr # EqualOrNot
    ;
DECIMAL_LITERAL:    ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?;    

完整規(guī)則:github.com/crossoverJi…

運(yùn)行:

antlr -Dlanguage=Go -o parser -visitor -no-listener GScript.g4

而我們要實(shí)現(xiàn)具體的語(yǔ)法邏輯時(shí)只需要實(shí)現(xiàn)相關(guān)的接口,Antlr 會(huì)自動(dòng)遍歷 AST(當(dāng)然也可以手動(dòng)控制),同時(shí)在訪問(wèn)不同的 AST 節(jié)點(diǎn)時(shí)會(huì)回調(diào)我們自己實(shí)現(xiàn)的接口,這樣我們就能編寫(xiě)自己的語(yǔ)法規(guī)則了。

以這里的新增的取模運(yùn)算為例:

func (v *GScriptVisitor) VisitModExpr(ctx *parser.ModExprContext) interface{} {
	lhs := v.Visit(ctx.GetLhs())
	rhs := v.Visit(ctx.GetRhs())
	return lhs.(int) % rhs.(int)
}

當(dāng) Antlr 回調(diào) VisitModExpr 方法時(shí),便能獲取到 % 符號(hào)左右兩側(cè)的數(shù)據(jù),這時(shí)只需要做相關(guān)運(yùn)算即可。

基于這個(gè)模式這次新增了一個(gè) statement,具體語(yǔ)法如下:

func TestGScriptVisitor_VisitIfElse8(t *testing.T) {
	expression := `
if(3!=(1+2)){
	return 1+3
} else {
	return false
}`
	input := antlr.NewInputStream(expression)
	lexer := parser.NewGScriptLexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	parser := parser.NewGScriptParser(stream)
	parser.BuildParseTrees = true
	tree := parser.Prog()
	visitor := GScriptVisitor{}
	var result = visitor.Visit(tree)
	fmt.Println(expression, " result:", result)
	assert.Equal(t, result, false)
}

Antlr 還有其他各種優(yōu)勢(shì),比如可以解決:

  • 左遞歸。
  • 二義性。
  • 優(yōu)先級(jí)。

等問(wèn)題。

這里也推薦在 IDE 中安裝 Antlr 的插件,這樣就可以直觀的查看 AST 語(yǔ)法樹(shù),可以幫我們更好的調(diào)試代碼。

升級(jí) xjson

借助 GScript 提供的 statementxjson 也提供了有些有意思的寫(xiě)法:

因?yàn)?xjson 的四則運(yùn)算語(yǔ)法沒(méi)有使用 Antlr 生成,所以為了能支持 GScript 提供的 statement 需要手寫(xiě)許多詞法代碼。

這也體現(xiàn)了 Antlr 這類前端工具的重要性,效率提升是非常明顯的。

總結(jié)

借助于 Antlr 后續(xù) GScript 會(huì)繼續(xù)支持函數(shù)調(diào)用、更完善的類型系統(tǒng)、面向?qū)ο蟮忍匦?;感興趣的朋友請(qǐng)持續(xù)關(guān)注。

源碼地址:

github.com/crossoverJi…

github.com/crossoverJi…

以上就是go Antlr重構(gòu)腳本解釋器實(shí)現(xiàn)示例的詳細(xì)內(nèi)容,更多關(guān)于go Antlr腳本解釋器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決Golang time.Parse和time.Format的時(shí)區(qū)問(wèn)題

    解決Golang time.Parse和time.Format的時(shí)區(qū)問(wèn)題

    這篇文章主要介紹了解決Golang time.Parse和time.Format的時(shí)區(qū)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • golang簡(jiǎn)單tls協(xié)議用法完整示例

    golang簡(jiǎn)單tls協(xié)議用法完整示例

    這篇文章主要介紹了golang簡(jiǎn)單tls用法,分析了tls協(xié)議的使用步驟及客戶端與服務(wù)器端的相關(guān)實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2016-07-07
  • golang快速實(shí)現(xiàn)網(wǎng)頁(yè)截圖的方法

    golang快速實(shí)現(xiàn)網(wǎng)頁(yè)截圖的方法

    這篇文章主要介紹了golang快速實(shí)現(xiàn)網(wǎng)頁(yè)截圖的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Go編寫(xiě)定時(shí)器與定時(shí)任務(wù)詳解(附第三方庫(kù)gocron用法)

    Go編寫(xiě)定時(shí)器與定時(shí)任務(wù)詳解(附第三方庫(kù)gocron用法)

    當(dāng)需要每天執(zhí)行定時(shí)任務(wù)的時(shí)候就需要定時(shí)器來(lái)處理了,周期任務(wù),倒計(jì)時(shí)任務(wù),定點(diǎn)任務(wù)等,下面這篇文章主要給大家介紹了關(guān)于Go編寫(xiě)定時(shí)器與定時(shí)任務(wù)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 使用go net實(shí)現(xiàn)簡(jiǎn)單的redis通信協(xié)議

    使用go net實(shí)現(xiàn)簡(jiǎn)單的redis通信協(xié)議

    本文主要介紹了go net實(shí)現(xiàn)簡(jiǎn)單的redis通信協(xié)議,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 詳解Go語(yǔ)言中的結(jié)構(gòu)體的特性

    詳解Go語(yǔ)言中的結(jié)構(gòu)體的特性

    結(jié)構(gòu)體是Go語(yǔ)言中重要且靈活的概念之一,本文旨在深入介紹Go語(yǔ)言中的結(jié)構(gòu)體,揭示其重要性和靈活性,并向讀者展示結(jié)構(gòu)體支持的眾多特性,需要的可以參考一下
    2023-06-06
  • golang設(shè)置http response響應(yīng)頭與填坑記錄

    golang設(shè)置http response響應(yīng)頭與填坑記錄

    這篇文章主要給大家介紹了關(guān)于golang設(shè)置http response響應(yīng)頭與填坑記錄的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • go語(yǔ)言base64加密解密的方法

    go語(yǔ)言base64加密解密的方法

    這篇文章主要介紹了go語(yǔ)言base64加密解密的方法,實(shí)例分析了Go語(yǔ)言base64加密解密的技巧,需要的朋友可以參考下
    2015-03-03
  • 詳解Go語(yǔ)言的context包從放棄到入門(mén)

    詳解Go語(yǔ)言的context包從放棄到入門(mén)

    這篇文章主要介紹了Go語(yǔ)言的context包從放棄到入門(mén),本文通過(guò)實(shí)例演示給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Go語(yǔ)言中的map擴(kuò)容機(jī)制

    Go語(yǔ)言中的map擴(kuò)容機(jī)制

    Go語(yǔ)言中的map是一種高效的數(shù)據(jù)結(jié)構(gòu),其擴(kuò)容機(jī)制確保了在大數(shù)據(jù)量情況下的性能,本文介紹了包括擴(kuò)容觸發(fā)條件、擴(kuò)容過(guò)程和漸進(jìn)式擴(kuò)容,感興趣的可以了解一下
    2024-12-12

最新評(píng)論

延边| 六盘水市| 阳城县| 宝山区| 杭锦旗| 郧西县| 霸州市| 旅游| 吉水县| 高雄市| 永丰县| 香河县| 浠水县| 丹棱县| 库尔勒市| 子洲县| 芜湖县| 兴仁县| 石家庄市| 尉氏县| 随州市| 江西省| 廉江市| 仪陇县| 从江县| 舞钢市| 木兰县| 鹤壁市| 舞阳县| 肥城市| 蕉岭县| 平潭县| 宝兴县| 尤溪县| 延安市| 胶州市| 图片| 诸暨市| 道孚县| 陇川县| 江达县|