news 2026/8/17 19:45:53

antlr4使用心得

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
antlr4使用心得

antlr4总结

算符优先级问题

同一条规则内,运算符分支在前的,优先级越高,比如:

expr : expr op=('+'|'-') expr #AddSub | expr op=('*'|'/') expr #MulDiv

会认为加减运算符优先于乘除运算符,这样在计算1+2*3时,就会得到错误的结果9。正确的写法是乘除分支在前:

expr : expr op=('*'|'/') expr #MulDiv | expr op=('+'|'-') expr #AddSub

算符右结合问题

antlr默认是算符左结合,像幂运算这样的算符一般要求右结合,可以这么写:

expr : <assoc=right> expr '**' expr #power | expr op=('*'|'/'|'%') expr #MulDiv | expr op=('+'|'-') expr #AddSub | '(' expr ')' #Parens

注意:<assoc=right>要写在分支的最左边,写在其它位置会有warning。

多分支下的标签不可省略

多分支规则里,要么所有分支给标签(否则无法为每个分支自动生成visit函数),要么所有分支都不给标签。

上例中,#AddSub就是一个分支标签,这条规则里的每个分支都要有一个标签,这样antlr会自动为每个分支生成一个visit函数,方便使用者来处理。比如:

@OverridepublicTvisitMulDiv(LumenParser.MulDivContextctx)...@OverridepublicTvisitAddSub(LumenParser.AddSubContextctx)

单分支规则自然无需手写标签,antlr会自动生成visit函数。

字面量

字面量可以是一个字符,也可以是字符串。必须用单引号括起来。下面是例子:

STRING : '"' (~["\r\n])* '"' ; BOOL : 'true' | 'false' ;

上例中,true和false都是字符串字面量。

错误处理

两种方式,一个是定制自己的BaseErrorListener:

publicclassSyntaxErrorListenerextendsBaseErrorListener{privateSourcesource;publicSyntaxErrorListener(Sourcesource){this.source=source;}@OverridepublicvoidsyntaxError(Recognizer<?,?>recognizer,ObjectoffendingSymbol,intline,intcharPositionInLine,Stringmsg,RecognitionExceptione){// line 和 charPositionInLine 就是错误的行列号StringsourceName=source.getName();if(!sourceName.isEmpty()){sourceName=String.format("%s:%d:%d: ",sourceName,line,charPositionInLine);}System.err.println(sourceName+msg);}}

然后设置这个Listener:

parser.addErrorListener(newSyntaxErrorListener(request.getSource()));

parser就是antlr自动为我们生成的语法解析器。

antlr框架会在出现语法错误时调用BaseErrorListener,然后恢复错误,继续解析。

若有运行时错误,可在每个grammar node里塞入行列号信息,从antlr的ParserRuleContext里即可获得,比如:

publicNodesupplySourceSection(Sourcesource,ParserRuleContextctx){Tokenstart=ctx.getStart();Tokenstop=ctx.getStop();// 可能为 null(EOF)intstartLine=start.getLine();intstartCol=start.getCharPositionInLine()+1;intendLine=(stop!=null?stop.getLine():startLine);intendCol=(stop!=null?stop.getCharPositionInLine()+1:startCol);this.sourceSection=source.createSection(startLine,startCol,endLine,endCol);returnthis;}

我这里使用的是graal vm的truffle框架,所以把行列号信息设置为每个语法节点的SourceSection。这样,当执行到特定节点出错时,就可以报出详细的行列号信息。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/31 5:51:16

LLM Fine-Tuning|七阶段微调【工程系列】1.总览

七阶段微调(7-Stage Fine-Tuning)流程的本质不是“训练步骤”&#xff0c;而是&#xff1a; 一套覆盖模型从“通用能力→领域专家→生产系统→持续演进”的完整工程生命周期 解决的不是"能不能训"&#xff0c;而是能不能 稳定训上线长期用持续改而不翻车 1.LLM生命周…

作者头像 李华
网站建设 2026/8/4 19:23:50

让大模型更“懂”外部知识:RAG技术及未来发展综述

&#xff5c;引言 如何更好地结合外部数据&#xff0c;如何提升模型处理专业领域问题的可靠性&#xff0c;是大语言模型应用开发中值得不断思考的问题。针对此&#xff0c;微软亚洲研究院的研究员们提出了一种基于查询需求分层的 RAG 任务分类法&#xff0c;从显式事实、隐式事…

作者头像 李华
网站建设 2026/8/16 6:33:49

从单智能体到多智能体:九种模式教你搭建高效AI应用

想要构建一个智能体应用&#xff0c;最重要的是什么&#xff1f;可能很多人首先会想到要选择一个性能强大的大模型。这个回答没错&#xff0c;毕竟当前的LLM Based Agent哪能缺少LLM的支撑。但事实却是&#xff0c;很多基于先进大模型构建的智能体没能体现出应用效果&#xff0…

作者头像 李华
网站建设 2026/8/16 10:42:58

降重去 AI 双 buff 拉满!虎贲等考 AI 解锁论文 “隐形优化” 新姿势

当论文查重率飘红的焦虑&#xff0c;遇上 AIGC 检测的 “生死大考”&#xff0c;多少毕业生陷入 “改了又改&#xff0c;还是过不了关” 的死循环&#xff1f;市面上的降重工具要么是简单同义词替换&#xff0c;改完逻辑混乱&#xff1b;要么只能降重复率&#xff0c;AI 痕迹依…

作者头像 李华
网站建设 2026/8/16 7:24:43

【Java毕设源码分享】基于springboot+vue的智慧物业服务系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华