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:基本工作流程和歧义处理方法相关推荐

  1. 【学习笔记】求解简单递归式的一般方法

    [学习笔记]求解简单递归式的一般方法 手动博客搬家: 本文发表于20180618 15:53:06, 原地址https://blog.csdn.net/suncongbo/article/detail ...

  2. Servlet和HTTP请求协议-学习笔记01【Servlet_快速入门-生命周期方法、Servlet_3.0注解配置、IDEA与tomcat相关配置】

    Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...

  3. oracle查询大小写敏感参数,【学习笔记】Oracle 11G密码大小写敏感的设置方法 sec_case_sensitive_logon参数...

    天萃荷净 分享一篇Oracle数据库密码大小写敏感设置案例,从11.1开始密码大小写敏感了,同时可以设置sec_case_sensitive_logon参数可以忽略大小写敏感(USER$.SPARE4 ...

  4. IMX6ULL学习笔记(四) —— uboot 启动流程

    IMX6ULL 学习笔记 version : v1.0 「2023.4.27」 author: Y.Z.T. 摘要: 随记, 记录 I.MX6ULL 系列 SOC 的uboot 启动流程 ⭐️ 目录 ...

  5. git serialtool_Git学习笔记---协作的一般流程

    一般的操作流程 1.pull 王小坤与另一个同事张大炮一起开发一个项目,张大炮昨天修改了数据库读写的api,优化了执行速度,并把read()函数改名成了Read(),下午下班之前把这些代码push到服 ...

  6. 一起来学习网站SEO优化工作流程到底怎么做?

    作者介绍:大家好!我是鱿年年★→ 个人主页:鱿年年的博客主页 系列专栏:网站SEO 目录 前言 一:行业网站概况分析 二:布局关键词 三:SEO优化 1:站内优化 2:站外优化 四:网站数据的监测工作 ...

  7. EJB3.0学习笔记---多接口的时,实现类处理方法:

    EJB学习笔记--- 1.胖客户端:指的是定义的接口太多了,接口做的工作太多; 胖接口: 2.EJB实现类型的定义,用注解的方式,当一个EJBbean,实现了多个接口的时候, 需要用注解的方式指明哪一 ...

  8. 深度学习笔记(三)计算图及其导数运算方法

    通过上文logistic regression的讲解知道,正向运算可以计算输出结果,而反向运算可以计算梯度或导数,从而调整参数. 通过简单的运算式引出计算图的组成,从而引出深度学习中前向传播和反向传播 ...

  9. gulp学习笔记,基本使用流程,基本函数,使用监听、插件

    学习gulp的简单笔记.原教学视频:https://www.bilibili.com/video/BV1NE411T7Z2?p=396. gulp基本使用流程 初始化项目目录: cnpm init / ...

最新文章

  1. java判断一个数是不是质数(素数)
  2. MockServer jar包安装
  3. windows系统下的python环境的搭建
  4. SAP ABAP实用技巧介绍系列之如何创建Maintenance view
  5. Laravel 中的环境与配置
  6. 字符串是单一字符的无序组合吗_Python学习笔记(八)组合数据类型
  7. 【转】C#实现SM3国密加密
  8. Replace Parameter with Methods(以函数取代参数)
  9. php curl curlopt_getfields,PHP中CURL的CURLOPT_POSTFIELDS参数使用细节
  10. html chart标签,用 Chart.js 画扇形图并显示标签
  11. 将软件添加到右键菜单 最简单的方法
  12. 非sudo用户引起同名字体故障一例
  13. c g位置服务器,C32/G34平台铺路 AMD为十二核CPU蓄势
  14. Python实现二维码生成器
  15. 如何通过软件编辑自己想要的点阵图片
  16. Overture五线谱打曲谱用得上的排版技巧
  17. 大数据时代,企业如何做好数据防泄漏?
  18. 古希腊神话故事:菲勒美拉
  19. 客户端登录阿里云mysql数据库_Mysql数据库之数据库术语和客户端登陆
  20. Linux网卡配置文件 参数详解

热门文章

  1. win7驱动程序未经签名可以使用吗_win7系统禁用驱动程序签名强制的详细操作
  2. php 随机播放音乐,听音乐时随机播放真的是随机的吗?
  3. 海外问卷调查怎么做?手把手教会你如何薅老外的羊毛
  4. 家用IC卡燃气智能表行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  5. oracle union详解,oracle union 及union all用法及差异
  6. 电脑版微信如何多开?5个方法轻松实现
  7. python算法之贪婪算法
  8. 每一个人都应该明白的ChatGPT所带来的意义
  9. 自定义View的三种实现方式及自定义属性使用介绍
  10. 学生动漫网页设计模板下载 摩尔庄园大学生HTML网页制作作品 简单漫画网页设计成品 dreamweaver学生网站模板