【ANTLR学习笔记】2:基本工作流程和歧义处理方法
1 解析的整体流程
首先是词法分析器处理字符序列(对应CharStream
类),生成Token流(对应TokenStream
类,这是连接词法分析和语法分析过程的桥梁)传给语法分析器,语法分析器再用它检查语法正确性,然后解析得到语法树(叶子结点对应TerminalNode
类,非叶子结点对应RuleNode
类)。
在词法分析之后,不仅要标记一个个Token,还需要记录这些Token对应的具体内容(比如知道是一个变量,也要记录变量名是什么)。ANTLR的做法是不去记录这个字符串,而是像上图一样,首先为字符流记录一个个位置号,然后在TokenStream
里记录这个Token对应的字符开始和结束的索引。
在生成的语法树中,叶子结点TerminalNode
就是要记录这些Token的具体值(的起止索引)了,而对于非叶子结点RuleNode
,则会根据不同的语法规则生成不同的子类,即上篇说到的形如*Context
的类,*
处是.g4
文件中语法规则的名字首字母大写。
例如,下图是上面的赋值语句解析出的语法分析树上各个结点的类。根节点是stat
语法规则(表示语句)生成的StatContxt
类,它的子结点是assign
语法规则(表示赋值)生成的AssignContext
类,它的四个孩子对应了assign
所匹配的四个词法符号:
a s s i g n : I D = e x p r ; assign \ : \ ID \ \ \ = \ \ \ expr \ \ \ ; assign : ID = expr ;
对于标识符ID
和具体符号=
和;
都无法继续展开,因此会作为树的叶子,并使用TerminalNode
记录。表达式expr
可以再展开,在这里为了解析100
,它选择了其中一个与之匹配的分支(整形数值),因此它生成唯一孩子TerminalNode
记录这个100
。
这些生成的*Context
类(作为生成的语法Parser的静态内部类)可以访问它所对应的词组中的所有元素(图中它的子树)。例如,上图的AssignContext
类就可以通过ID()
方法访问标识符子结点(返回值是TerminalNode
类型),通过expr()
方法访问表达式子树(返回值是ExprContext
类型)。
2 语法分析器的工作过程
ANTLR根据给出的语法规则,生成一个递归下降的语法分析器,当待解析的语法规则有多条分支时,语法分析器会去前瞻词法符号(不必是LL(1),可以前瞻若干个词法符号),这个过程和手写的Parser是类似的,对于:
stat: assign| ifstat| whilestat...;
这表示语句(stat
)可以是赋值语句(assign
),可以是IF语句(ifstat
),可以是WHILE语句(whilestat
)或者其它语句。仅就这三条而言,它们的第一个词法符号分别是标识符、IF关键字、WHILE关键字,因此可以前瞻一个词法符号解决,解析stat
的逻辑是:
void stat() {switch(/*当前输入的词法符号*/) {case ID : assign(); break;case IF : ifstat(); break;case WHILE : whilestat(); break;...default: /*全都匹配不上,抛出异常*/}
}
3 歧义处理方法
如果可以通过多条分支解析输入的文本,那么就说明输入文本是有歧义的,可以有多种语义去解释。用户提供的.g4
文件中不论是Token的匹配还是语法的描述都可能存在歧义。
3.1 语法描述上的歧义
例如:
stat : expr ';' // 表达式语句| ID '(' ')' ';' // 函数调用语句;
expr : ID '(' ')'| INT;
对于输入f();
,可以走stat
的第一条分支,将f()
当作一个表达式expr
来解析,此时f();
被认为是一个表达式语句。也可以走stat
的第二条分支,此时f();
被认为是一个函数调用语句,其中标识符f
被视为函数名。
ANTLR解决语法歧义的方法是,匹配所有可匹配分支的第一条。因此对于刚刚的例子,会将f();
作为表达式解析。
3.2 Token匹配时的歧义
最常见的是语法关键字和标识符之间的歧义,例如:
BEGIN : 'begin';
ID : [a-z]+;
这表示BEGIN
关键字匹配begin
序列,标识符匹配一个至多个小写字母序列。ANTLR解决Token歧义的方法是,匹配定义最靠前的语法规则。利用这一点可以自然的保证begin
不能作为标识符的问题,因为BEGIN
的声明就在ID
的前面。
词法分析器在匹配Token时是贪婪模式的,即会尽可能匹配一个最长的字符串来生成Token,因此beginner
会匹配为ID
,而不是BEGIN
后面接名为ner
的标识符。
3.3 语言语法本身的歧义
这里书中举了两个例子。其一是表达式优先级的歧义,如
1 + 2 ∗ 3 1+2*3 1+2∗3
在Smalltalk里就是自左向右处理(因此计算出来是9),在其它语言里*
优先级高于+
(因此计算出来是7)。因此如何隐式指定表达式运算符优先级是一个问题。
另一种是C语言里的,如i*j;
中*
是乘号还是指针符号,取决于i
的Token是一个表达式还是一个类型(比如int*j;
就是定义指针变量,8*j;
则是一个表达式语句)。也就是说这类歧义要通过检查上下文信息解决。
【ANTLR学习笔记】2:基本工作流程和歧义处理方法相关推荐
- 【学习笔记】求解简单递归式的一般方法
[学习笔记]求解简单递归式的一般方法 手动博客搬家: 本文发表于20180618 15:53:06, 原地址https://blog.csdn.net/suncongbo/article/detail ...
- Servlet和HTTP请求协议-学习笔记01【Servlet_快速入门-生命周期方法、Servlet_3.0注解配置、IDEA与tomcat相关配置】
Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...
- oracle查询大小写敏感参数,【学习笔记】Oracle 11G密码大小写敏感的设置方法 sec_case_sensitive_logon参数...
天萃荷净 分享一篇Oracle数据库密码大小写敏感设置案例,从11.1开始密码大小写敏感了,同时可以设置sec_case_sensitive_logon参数可以忽略大小写敏感(USER$.SPARE4 ...
- IMX6ULL学习笔记(四) —— uboot 启动流程
IMX6ULL 学习笔记 version : v1.0 「2023.4.27」 author: Y.Z.T. 摘要: 随记, 记录 I.MX6ULL 系列 SOC 的uboot 启动流程 ⭐️ 目录 ...
- git serialtool_Git学习笔记---协作的一般流程
一般的操作流程 1.pull 王小坤与另一个同事张大炮一起开发一个项目,张大炮昨天修改了数据库读写的api,优化了执行速度,并把read()函数改名成了Read(),下午下班之前把这些代码push到服 ...
- 一起来学习网站SEO优化工作流程到底怎么做?
作者介绍:大家好!我是鱿年年★→ 个人主页:鱿年年的博客主页 系列专栏:网站SEO 目录 前言 一:行业网站概况分析 二:布局关键词 三:SEO优化 1:站内优化 2:站外优化 四:网站数据的监测工作 ...
- EJB3.0学习笔记---多接口的时,实现类处理方法:
EJB学习笔记--- 1.胖客户端:指的是定义的接口太多了,接口做的工作太多; 胖接口: 2.EJB实现类型的定义,用注解的方式,当一个EJBbean,实现了多个接口的时候, 需要用注解的方式指明哪一 ...
- 深度学习笔记(三)计算图及其导数运算方法
通过上文logistic regression的讲解知道,正向运算可以计算输出结果,而反向运算可以计算梯度或导数,从而调整参数. 通过简单的运算式引出计算图的组成,从而引出深度学习中前向传播和反向传播 ...
- gulp学习笔记,基本使用流程,基本函数,使用监听、插件
学习gulp的简单笔记.原教学视频:https://www.bilibili.com/video/BV1NE411T7Z2?p=396. gulp基本使用流程 初始化项目目录: cnpm init / ...
最新文章
- java判断一个数是不是质数(素数)
- MockServer jar包安装
- windows系统下的python环境的搭建
- SAP ABAP实用技巧介绍系列之如何创建Maintenance view
- Laravel 中的环境与配置
- 字符串是单一字符的无序组合吗_Python学习笔记(八)组合数据类型
- 【转】C#实现SM3国密加密
- Replace Parameter with Methods(以函数取代参数)
- php curl curlopt_getfields,PHP中CURL的CURLOPT_POSTFIELDS参数使用细节
- html chart标签,用 Chart.js 画扇形图并显示标签
- 将软件添加到右键菜单 最简单的方法
- 非sudo用户引起同名字体故障一例
- c g位置服务器,C32/G34平台铺路 AMD为十二核CPU蓄势
- Python实现二维码生成器
- 如何通过软件编辑自己想要的点阵图片
- Overture五线谱打曲谱用得上的排版技巧
- 大数据时代,企业如何做好数据防泄漏?
- 古希腊神话故事:菲勒美拉
- 客户端登录阿里云mysql数据库_Mysql数据库之数据库术语和客户端登陆
- Linux网卡配置文件 参数详解
热门文章
- win7驱动程序未经签名可以使用吗_win7系统禁用驱动程序签名强制的详细操作
- php 随机播放音乐,听音乐时随机播放真的是随机的吗?
- 海外问卷调查怎么做?手把手教会你如何薅老外的羊毛
- 家用IC卡燃气智能表行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- oracle union详解,oracle union 及union all用法及差异
- 电脑版微信如何多开?5个方法轻松实现
- python算法之贪婪算法
- 每一个人都应该明白的ChatGPT所带来的意义
- 自定义View的三种实现方式及自定义属性使用介绍
- 学生动漫网页设计模板下载 摩尔庄园大学生HTML网页制作作品 简单漫画网页设计成品 dreamweaver学生网站模板