文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

golang怎么整合antlr语法校验

2023-07-05 07:12

关注

本篇内容介绍了“golang怎么整合antlr语法校验”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1. 背景

在项目中我们可能会遇到表达式检索的场景,例如,输入以下表达式检索,需要解析表达式并得到检索结果。

ip="192.168.1.3" && (port="80" || protocol="http")

此时,我们需要对语法进行校验、解析,应当如何做呢?

下面给大家推荐一种使用语法校验工具Antlr

Antlr是一个语法分析器,本身是用java实现的,然是Runtime的库也支持Golang、Java、Python等。

2. goland安装antlr插件

打开goland,File --> Settings --> Plugins, 搜索antlr,安装 antlr4

golang怎么整合antlr语法校验

插件安装完成后,可以看到ANTLR Preview窗口,一会我们可以在这个窗口进行简单的语法校验。

golang怎么整合antlr语法校验

3. 编写语法校验规则

创建工程,引入包

go get -u github.com/antlr/antlr4/runtime/Go/antlr/v4

在工程中新建一个antlr目录,创建一个后缀名为 .g4 的文件,作为规则文件。此处我们创建Rule.g4

// 定义语法名称,需要和文件名匹配grammar Rule;// DECIMAL, IDENTIFIER, COMMENTS, WS are set using regular expressions// key 为表达式中可支持的检索字段,可以是固定值(每个值中间用 | 隔开,是”或“的意思),也可以是正则表达式// value 使用正则表达式KEY : 'ip' | 'port' | 'protocol';//VALUE :'"' ( '""' | ~["\r\n] )* '"' ;//KEY : ('A' .. 'Z' | 'a' .. 'z' |  '_') + ;VALUE :'"' ( '\\"' | ~["] )* '"' ;// COMMENT and WS are stripped from the output token stream by sending// to a different channel 'skip'COMMENT : '//' .+? ('\n'|EOF) -> skip ;WS : [ \r\t\u000C\n]+ -> skip ;// 语法校验的入口start : logicalExpr* EOF;// 语法支持的结构logicalExpr    : comparisonExpr // 示例: key == value 表示支持 == 和 != 的表达式    | logicalExpr operator logicalExpr // 示例: key1 == value1 && key2 != value2 表示支持 && 和 || 运算符连接表达式    | lparen logicalExpr rparen // 示例: (key1 == value1 && key2 != value2) 表示支持 () 连接表达式    ;comparisonExpr    : KEY compare VALUE    ;compare    : '='    | '!='    ;operator    : '&&'    | '||'    ;lparen    :  '('    ;rparen    :  ')'    ;

初始化校验语法

选中Rule.g4 文件,鼠标右键,选择 Configure ANTLR Tool…

配置输出路径,和Rule.g4 同目录;配置语言,使用Go

golang怎么整合antlr语法校验

选中Rule.g4 文件,鼠标右键,选择 Generate ANTLR Recognizer,完成规则初始化

golang怎么整合antlr语法校验

树状图校验

golang怎么整合antlr语法校验

4. 语法校验

自定义listener

package parserimport ("github.com/antlr/antlr4/runtime/Go/antlr/v4""strings")type MyRuleListener struct {*BaseRuleListenerQueue    []interface{}QueueStr []string}// 注意:方法名必须是这个名字func (s *MyRuleListener) EnterComparisonExpr(ctx *ComparisonExprContext) {key := ctx.GetChild(0).(antlr.ParseTree).GetText()operator := ctx.GetChild(1).(antlr.ParseTree).GetText()value := ctx.GetChild(2).(antlr.ParseTree).GetText()if strings.HasPrefix(value, "\"") {value = value[1:]}if strings.HasSuffix(value, "\"") {value = value[:len(value)-1]}keyValue := map[string]string{}keyValue["key"] = keykeyValue["operator"] = operatorkeyValue["value"] = values.PushStr(ctx.GetText())s.Push(keyValue)}// EnterKeyValue is called when production KeyValue is entered.func (s *MyRuleListener) ExitOperator(ctx *OperatorContext) {s.Push(ctx.GetText())s.PushStr(ctx.GetText())}// EnterKeyValue is called when production KeyValue is entered.func (s *MyRuleListener) ExitLparen(ctx *LparenContext) {s.Push(ctx.GetText())s.PushStr(ctx.GetText())}// EnterKeyValue is called when production KeyValue is entered.func (s *MyRuleListener) ExitRparen(ctx *RparenContext) {s.Push(ctx.GetText())s.PushStr(ctx.GetText())}func (s *MyRuleListener) Push(i interface{}) {s.Queue = append(s.Queue, i)}func (s *MyRuleListener) PushStr(i string) {s.QueueStr = append(s.QueueStr, i)}

获取解析异常的错误信息

package parserimport "github.com/antlr/antlr4/runtime/Go/antlr/v4"type RuleErrorListener struct {antlr.ErrorListenerMsg string}func (l *RuleErrorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) {l.Msg = msg}

校验

package mainimport (parser "antlr-demo/antlr""errors""fmt""github.com/antlr/antlr4/runtime/Go/antlr/v4")func main() {expre := "ip=\"192.168.1.3\" && (port=\"80\" || protocol=\"http\")"err := checkExpre(expre)if err != nil {fmt.Println(err)}}func checkExpre(expre string) error {input := antlr.NewInputStream(expre)var lexerErr parser.RuleErrorListenerlexer := parser.NewRuleLexer(input)lexer.AddErrorListener(&lexerErr)stream := antlr.NewCommonTokenStream(lexer, 0)ruleParser := parser.NewRuleParser(stream)ruleParser.BuildParseTrees = truevar ruleErr parser.RuleErrorListenerruleParser.AddErrorListener(&ruleErr)tree := ruleParser.Start()listener := new(parser.MyRuleListener)antlr.ParseTreeWalkerDefault.Walk(listener, tree)if lexerErr.Msg != "" || ruleErr.Msg != "" {return errors.New("输入的语法不正确")}expreList := listener.QueueStrfmt.Println("expreList--->", expreList)expreMap := listener.Queuefmt.Println("expreMap--->", expreMap)return nil}

结果验证

正确表达式

golang怎么整合antlr语法校验

key不在支持的语法内

golang怎么整合antlr语法校验

缺少key

golang怎么整合antlr语法校验

运算符不在支持的语法内

golang怎么整合antlr语法校验

缺少括号

golang怎么整合antlr语法校验

“golang怎么整合antlr语法校验”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯