亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

go?Antlr重構腳本解釋器如何實現

發布時間:2022-08-08 17:45:32 來源:億速云 閱讀:131 作者:iii 欄目:開發技術

這篇文章主要介紹“go Antlr重構腳本解釋器如何實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“go Antlr重構腳本解釋器如何實現”文章能幫助大家解決問題。

Antlr

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

下面以 GScript 的示例來看看 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 會自動將我們的表達式解析為 token,遍歷 token 時還能拿到該 token 所在的代碼行數、位置等信息,在編譯期間做語法檢查非常有用。

要實現這些我們只需要編寫詞法、語法規則文件即可。

剛才的示例所對應的詞法、語法規則如下:

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]?;

完整規則:github.com/crossoverJi…

運行:

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

而我們要實現具體的語法邏輯時只需要實現相關的接口,Antlr 會自動遍歷 AST(當然也可以手動控制),同時在訪問不同的 AST 節點時會回調我們自己實現的接口,這樣我們就能編寫自己的語法規則了。

以這里的新增的取模運算為例:

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

Antlr 回調 VisitModExpr 方法時,便能獲取到 % 符號左右兩側的數據,這時只需要做相關運算即可。

基于這個模式這次新增了一個 statement,具體語法如下:

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 還有其他各種優勢,比如可以解決:

  • 左遞歸。

  • 二義性。

  • 優先級。

等問題。

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

go?Antlr重構腳本解釋器如何實現

go?Antlr重構腳本解釋器如何實現

升級 xjson

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

go?Antlr重構腳本解釋器如何實現

因為 xjson 的四則運算語法沒有使用 Antlr 生成,所以為了能支持 GScript 提供的 statement 需要手寫許多詞法代碼。

go?Antlr重構腳本解釋器如何實現

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

關于“go Antlr重構腳本解釋器如何實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

韶关市| 尚志市| 新巴尔虎左旗| 德江县| 永仁县| 顺平县| 岱山县| 运城市| 邢台县| 弥渡县| 巧家县| 城口县| 安仁县| 西安市| 石景山区| 平果县| 商洛市| 肇州县| 瓦房店市| 松江区| 安福县| 周口市| 石阡县| 龙川县| 松溪县| 涟源市| 樟树市| 虹口区| 淳安县| 迁安市| 南丹县| 东丰县| 昌吉市| 上林县| 嘉祥县| 穆棱市| 镇安县| 平阳县| 九寨沟县| 黑山县| 南充市|