您好,登錄后才能下訂單哦!
這篇文章主要介紹“go Antlr重構腳本解釋器如何實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“go 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 語法樹,可以幫我們更好的調試代碼。
借助 GScript
提供的 statement
,xjson
也提供了有些有意思的寫法:
因為 xjson
的四則運算語法沒有使用 Antlr
生成,所以為了能支持 GScript
提供的 statement
需要手寫許多詞法代碼。
這也體現了 Antlr
這類前端工具的重要性,效率提升是非常明顯的。
關于“go Antlr重構腳本解釋器如何實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。