当前位置:网站首页>go Antlr重构脚本解释器如何实现
go Antlr重构脚本解释器如何实现
2022-08-09 08:52:00 【亿速云】
go Antlr重构脚本解释器如何实现
这篇文章主要介绍“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: ("(") 0DECIMAL_LITERAL ("2") 1PLUS ("+") 2DECIMAL_LITERAL ("3") 3 (")") 4MULT ("*") 6DECIMAL_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 语法树,可以帮我们更好的调试代码。
升级 xjson
借助 GScript
提供的 statement
,xjson
也提供了有些有意思的写法:
因为 xjson
的四则运算语法没有使用 Antlr
生成,所以为了能支持 GScript
提供的 statement
需要手写许多词法代码。
这也体现了 Antlr
这类前端工具的重要性,效率提升是非常明显的。
关于“go Antlr重构脚本解释器如何实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。
边栏推荐
- The embedded serial port interrupt can only receive one byte
- leetcode 34. 在排序数组中查找元素的第一个和最后一个位置(二分经典题)
- 6000 字+,帮你搞懂互联网架构演变历程!
- [V&N2020 Open] Memory Forensics
- 【Harmony OS】【ARK UI】公共事件模块
- DeFi 项目中的治理Token
- 第五届蓝帽杯初赛 misc 赛后复现
- UE4 RTS 框选功能实现
- Operator Overloading in Inheritance: A Legend of Input and Output
- 小程序调用百度api实现图像识别
猜你喜欢
Object detection app based on appinventor and EasyDL object detection API
【场景化解决方案】搭建数据桥梁,Dslink打通泛微系统连接流
Introduction to Network Layer Protocols
Dark Horse 2022 latest redis course notes and knowledge points (for interview)
A watch - article HongMeng development practical experience
XCTF College War "Epidemic" Network Security Sharing Competition Misc wp
【redis】使用redis实现简单的分布式锁,秒杀并发场景可用
【redis】redis之过期监听
leetcode 35. 搜索插入位置(二分法+找性质也很关键)
一篇文章带你熟悉 TCP/IP 协议(网络协议篇二)
随机推荐
这下你知道为什么程序员要和产品干架了吧?
网络层协议介绍
epoll LT和ET 问题总结
hdu2191 多重背包(2016xynu暑期集训检测 -----B题)
BUUCTF MISC Writing Notes (1)
sizeof 结构体问题
The principle and configuration of VLAN
加密技术和电子竞技如何促进彼此的发展
[V&N2020 公开赛]内存取证
第五届蓝帽杯初赛 misc 赛后复现
uniapp编译到小程序后丢失static文件夹问题
长辈相亲
[漏洞复现]CVE-2018-7490(路径遍历)
【GNN】2022 G-Mixup: Graph Data Augmentation for Graph Classification
【CNN】白话迁移学习中域适应
解决iframe跳转时父页面仍然存在的问题
The 5th Blue Cap Cup preliminary misc reappears after the game
【Harmony OS】【ARK UI】公共事件模块
【场景化解决方案】OA审批与用友U9数据集成
VoLTE基础自学系列 | IMS的业务触发机制