从上下文无关文法(CFG)到语法分析树——LL(1)分析法

编译原理 语法分析与上下文无关文法 分析可以用来确定程序的结构。 程序使用的语法是上下文无关文法,是乔姆斯基分类法则中的第2类语法。 0 1 2 3 文法名称 非限制型文法 上下文有关文法 上下文无关文法 正则文法 对应机器 图灵机 线性(边界)自动机 下推自动机 有穷自动机 识别对象 自然语言 受限自然语言 程序语言 单词 上下文无关文法使用BNF文法表示。文法规则中有一个“推导”的行为,此行为在右... 阅读详情

回顾


在开始之前,我们需要知道自己在做什么。
之前,我们花了不少时间熟悉如何将RE转化为DFA,那么为什么要将RE转换为DFA?这个问题类似于现在为什么要将CFG(上下文无关文法)转换成Parser。在掌握具体的步骤之前,我们有必要说明一下这样做的目的。
首先看一下编译器的模型图:
compiler
为什么要将RE转换到DFA?
相信看过实验一之后这个问题已经非常清楚。实验一我们需要完成一个词法分析器。我们需要自己用正则表达式定义一个语言的成分,比如单词、数字、注释、引用等,分别写出他们对应的NFA,合并NFA并转换成DFA,在得到DFA之后我们可以知道所有的状态和每个状态遇到不同的输入应该如何跳转处理,从DFA生成词法分析的程序。在上一篇文章的一开始,我们也提到了如何从DFA生成程序。词法分析器最终的输出是一个Token序列,记录了lexeme(词)、catalog(种类,就是自己用RE定义的)以及InnnerCode(内部码)
为什么要将CFG转到Parser?
之前我们所做的是词法分析,现在我们需要考虑语法分析的问题,当我们已经定义出一个语言的上下文无关文法,并且拿到了已经分析好的单词序列,我们怎样解析这些单词序列之间的语法关系呢?这类似于如何从有序的单词序列中分析出主语、谓语、宾语。我们需要知道这个单词对应语法中的那种成分,或者这一系列单词究竟符不符合语法要求。

递归下降分析法


有一种很简单的方法可以用来解决这个问题,它叫做递归下降分析法( Recursive Descent Parsing)。
这个方法利用递归与回搠的方法解决问题,核心在于为每个非终结符构造一个函数。

Example: S=>ABC, A=>aA|ε, B=>bB|ε, C=>cC|ε

首先是main函数:

main() {
    i = S();
}

为非终止状态构造函数:

int S() {
    i = A();
    if (i == 1) {
        j = B();
        if (j==1) {
            return C();
        } else {
            error();
        }
    } else {
        error();
    }
}

int A() {
    ch = getChar();
    if (ch == 'a') return A();
    else return 1;
}

使用这种回搠的方法在面对复杂情况时效率很低,我们需要找出回搠的原因,最期待的情况是经过一定的预处理之后一遍就能判断对。这就需要使用另一种方法:预测分析法。

预测分析法


造成以上方法回搠,主要有两种原因:
- 公共子因子,如A=>aB|aC完全可以变成A=>aE,E=>B|C
- 左递归,如A=>Aa

需要对CFG预处理来消除这两种情况。

1、预处理

1)提取最大左因子(Extract Maximum Common Left Factor)

很简单,就和名字描述的那样,例如A=>aB|aC|bD转换成A=>aE|bD, E=>B|C。

2)消除左递归(Eliminating Left Recursion)

直接左递归

这种情况,只有一种套路。首先来看A=>Aα | β 这种情况,他代表的是以β开头,后面n个α的字符串,因此我们能得到结论:

A=>Aα|β =======> βαn ======> A=>βA’ , A’ => αA’ | ε

有这个结论,我们就可以转换所有左递归的情形。例如:E => E + T | T
把 “+T”看做α,把T看做β,上式就可以改写为 E => TE’ , E’ => +TE’| ε

间接左递归

类似 S=>Qc|c,Q=>Rb|b,R=>Sa|a这种构成了一个环,我们只要把换消除掉就好了,这里可以用到优先级的概念,比如规定S不可以推出Q和R,我们只能将S=Qc|c推倒成S=>Rbc|bc=>Sabc|abc这样就变成了直接递归,用上面的套路就可以解决了。

混合左递归

首先消除直接左递归,然后再消除间接左递归。
就是在出现圈中套圈的情况下要先把内部的圈消掉然后才能消去外部的圈。否则会永远都消不掉,陷入死循环。

2、制表

首先,我们需要再次明确我们的目的:在扫过字符串一遍后就能知道该字符的语法成分。第一步进行的预处理为这样的情况提供了可能。为了达成这一步骤,我们需要知道每个非终止符在遇到特定的字符时应该认定该字符为何种成分。为此,我们需要制定一张表格,描述了非终止符与终止符之间的关系,即如何理解输入的字符序列。

First和Follow

First和Follow都是为了达成上述目标自然形成的概念。
例如,若A=>aB, A=>bC, 那么在状态为A时扫描到a这个字符,我们则知道此时应该将A推导为aB,这个a对应的就是aB中的a。同样,若A=>BC, B=>bC,在遇到b这个字符时,我们仍然知道将A推导为BC,因为A 首先 推导出的终止符是b,这就是First的概念,描述了首先能推导出的终止符的集合。
我们这样定义First:
First
若α=>α1α1…αn,则:

First(α) = First(α1) , if ε not in First(α1)
First(α) = (First(α1) - {ε0})∪First(α2) ,if ε∈First(α1)

以此类推,这里提到了ε的情况,若A=>BC, B=>ε|bB, C=>cC,那么A推出的第一个终止符就变成了b,这就是上面定义说明的意思。
可是,若是S=>AD, A=>BC, B=>ε|bB, C=>ε|cC, D=>eD这种情况呢?当我们处于A时,我们对A求First,有b和c和ε,对于这里出现的ε又如何处理呢?当我们处于A,读取的字符是e,我们仍然需要让A推导为BC,让BC都为ε,然后让A后面的D推出eD来对应这个e。所以对于A,我们还需要考虑除了First以外其他有可能在该状态出现的字符。这就要引入Follow的概念。
Follow
即若B=>αAβ,则

Follow(A) = First(β) (β不会推出ε)
Follow(A) = (First(β)-{ε})∪Follow(B) (β推出ε)

若B=>αA,则

Follow(A) <= Follow(B)

但是要是右边什么都没有了呢?如上,我们在最右边加上终止符$,它也可以是Follow的一部分。
最后,我们对经过预处理的CFG的右边求First(如果有ε则求Follow)。
示例:
Example
可以用上面的方法生成表格:
table
比如说,对于E->TE’,我们对TE’求First得到{i,(},因此i列和(列填上E->TE’。

处理

在获得这张表格之后,剩余的工作就非常简单了。
stack
首先将$和开始符E压栈(字符序列后需要加上$),若输入的第一个字符为i,查看上面的表格,E和i对应的是E=>TE’,我们就把E出栈,把E’压栈,把T压栈(注意因为是左推导,左边的需要优先处理,所以左边的要最后压栈),并记下第一步:E=>TE’,重复上面的步骤,若匹配到终止字符,则将输入的字符序列的指针后移,直到匹配到最后的终止符号为止。
之前我们记下每一步的推导式:

  1. E=>TE’
  2. T=>FT’
  3. F=>i
  4. T’=>ε
  5. E’=>+TE’
  6. T=>FT’
  7. F=>i
  8. T’=>ε
  9. E’=>ε

根据每一步的推导式可以生成上面的例子中“i+i”的语法分析树:
Tree

LL(1)语法

定义:

A grammar whose parsing table has no multiply-defined entries is said to be LL(1).

LL(1)方法是基于推导的自顶向下的方法。
- The first “L” stands for scanning the input from left to right.从左向右扫描字符串
- The second “L” stands for producing a leftmost derivation.最左推导
- “1” means using one input symbol of look-ahead s.t each step to make parsing action decisions.一步只扫描一个字符

本文的两种方法都只适用于LL(1)语法(在预处理之后符合LL(1))。

半导体光刻工艺中的黄光区原理与应用 光刻作为半导体制造的核心工艺,其精度直接影响芯片性能。黄光区是光刻工艺的特殊工作环境,采用特定波长的黄色照明以避免光刻胶意外曝光。光刻胶根据感光特性分为正性和负性两种,均对蓝紫光敏感,而黄光作为其互补色可提供安全照明。现代半导体工厂通过钠灯或LED光源实现严格的光谱控制,确保黄光环境符合工艺要求。黄光区不仅保障了光刻工艺的稳定性,也成为半导体行业的文化符号。随着EUV光刻等新技术发展,黄光区仍保持其重要地位,体现了半导体制造工艺的传承与创新。 阅读详情

相关推荐

【编译原理】LL(1)文法

编译原理课程笔记,自上而下的语法分析,LL(1)分析法,FIRST集和FOLLOW集的求法

m0_61819793的博客 6063

从上下文无关文法(CFG)到语法分析树——SLR(1)分析法

LR方法LR parsing是一种相对于LL更通用的方法,LR parser是高效的、自底向上的用于上下文无关文法的语法分析技术。 LR(k)方法中的L、R、K分别代表: L: left-to-right scan从左向右扫描 R:construct a rightmost derivation in reverse最右推导 k:the number of input symbols of loo

cuiods的博客 7798

《编译原理》完整笔记

《编译原理》完整笔记

修行的凡人的博客 2120

neo4j安装_知识图谱专题之——Neo4j入门教程

一、安装参考:Neo4j 第一篇:在Windows环境中安装Neo4j安装照这篇教程走就可以了,注意环境路径的配置和JAVA-Neo4j版本的适配。二、入门2.1 Neo4j浏览器Neo4j服务器具有一个集成的浏览器,在启动neo4j服务之后,可以使用neo4j集成的浏览器管理图数据库。在一个运行neo4j服务器主机上访问 “http://localhost:7474/”,显示以下的界面:默认的h...

weixin_39646831的博客 348

用Java构建LL(1)语法分析器的实战教程

在现代软件开发中,编译器扮演着至关重要的角色。从最早的Fortran到如今的JavaScript,它们使得复杂语言的高效解析成为可能。语法分析器是编译器的一部分,主要负责解析源代码,将其转化为更易于计算机理解的中间形式。而理解语法分析器的工作原理,对于提升编程效率、优化编译过程都至关重要。在本文的第一章,我们将简要介绍语法分析器的基本概念、它的工作流程以及为什么它在编程语言设计与实现中不可或缺。

weixin_31315007的博客 788

编译原理实验四LL(1)文法【C语言实现】

AIIT 编译原理实验四LL(1)文法

计算机语言学笔记(八)基于上下文无关文法的句法分析

8 基于上下文无关文法的句法分析 句法分析导引 以词为单位的分析技术:词语切分、形态分析、词类标注。 以句为单位的分析技术:句法分析。 以篇为单位的分析技术:指代分析。 句法分析关心句子的组成规律。 句子成分分析 句子是词的线性序列,但词和词之间结合的松紧程度并不一样。 句子在构造上具有层次性,较小的成分还可以进一步组成较大的成分。 不同性质的成分可以有不同的句法功能和分布,可以区分成不同的类型。...

tianyouououou的博客 1650

EBOM转MBOM实战:华为云数字工厂如何5步搞定BOM自动转换(含避坑指南)

本文详细解析了华为云数字工厂平台如何通过五步自动化流程实现EBOM到MBOM的高效转换,涵盖模型预配置、逻辑流编排、工艺属性注入等关键步骤,并提供了多工厂差异化配置、历史数据迁移等典型场景的避坑指南。该方案显著提升转换效率,降低差错率,助力企业实现数字化转型。

weixin_29215391的博客 270

三、语法分析(1)自顶向下:First集、Follow集、Select集、LL(1)文法、表驱动LL(1)分析表、消除左递归、提取左公因子

左递归:文法中一个非终结符号A使得对某个串α,存在一个推导 A Aα,则称这个文法是左递归的。匹配成功的终结符号不会再被考虑,因此只需要记住句型的余下部分,以及尚未匹配的输入终结符号串。在实际的语法分析过程中并不一定会构造出相应的分析树,但是用分析树的概念可以方便解。从叶子 (输入串中的终结符号,将位于分析树的底端) 开始,向上到达根结点。自顶向下的语法分析技术不能处理左递归的情况,因此需要消除左递归,但是。b、从开始符号出发,不断进行上面的替换,就可以得到文法的不同句型。

m0_74161592的博客 1264

【数据分享】中国371个城市的坡度矢量数据和excel数据

在城市发展的进程中,地形地貌始终是影响规划决策的关键因素,而坡度作为表征地表倾斜程度的核心指标,更是贯穿于城市建设、生态保护等诸多环节。本文将全面解读中国 371 个城市坡度数据的相关情况,包括数据概况、生成流程、应用场景等内容,为读者呈现一份详尽的坡度数据指南。

qq_39719713的博客 1844

CAB单片机开发指南

CAB单片机开发使用指南,IDE安装及烧录注意事项

Zoebuxiangtian的博客 1558

自顶向下语法分析(top-down parsing)

介绍自顶向下语法分析,包括有回溯的算法、无回溯算法、FIRST 集合、FOLLOW 集合、消除左递归、提取左公因子、LL(1)文法、下推自动机

Dong_HFUT的博客 7230

如何在多 GPU 配置上运行 Unsloth:数据并行或模型并行

当工作负载受限于内存(模型或批次无法放入单张显卡)、或受限于计算且计算与通信比率较高时(即每块 GPU 的额外计算量超过同步参数的开销,如在 DDP 中,或超过传递激活值的开销,如在模型并行中),多 GPU 配置才开始显现优势。在松散连接的显卡上(尤其是 PCIe 版本的 H100 或 A100),额外的设备间数据传输会导致性能显著低于单 GPU 运行。让我们厘清概念,明确说明如何通过模型并行(将模型拆分到多个 GPU)或数据并行(在每个 GPU 上复制模型)来跨多 GPU 运行 Unsloth。

人工智能领域专家 647

编译原理笔记(哈工大视频总结)

编译原理笔记--哈工大教学视频第一章 绪论一、什么是编译二、编译系统的结构三、词法分析概述四、语法分析概述五、语义分析概述六、中 间 代 码 生 成 及编 译 器 后 端 概 述![在这里插入图片描述](https://img-blog.csdnimg.cn/1320bf7555e84ab3b85bd16a300dd0c2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Z2Z6Z2Z562J6Iqx

qq_45351128的博客 7474

一条时间轴上的商品供给:商品供给域事件全景、八大子域事件清单与事件契约规范的工程推演

本文以虚构连锁零售企业“青禾鲜市”为例,用事件风暴重新梳理商品供给域:先剖析同词异义、状态模糊、隐式依赖与被动兜底四类冲突,再以时间轴、八条子域泳道与关键事件铺出全景地图,确立一个事件只有一个户口;随后为总店商品、门店商品、价格、库存、质量、标签、变更通知与操作日志列出聚合、事件、命令与策略,并统一命名、信封结构、版本与幂等规范。程序体检把初稿14个问题清零,仿真显示按聚合版本号更新可售视图可将误判从两位数百分比降到0.019%。文末给出四轮工作坊节奏与新品引入、全国调价、批次召回走查剧本。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 5万+

学Simulink——基于Simulink的输入-输出线性化精确转矩控制

本文详细介绍了基于Simulink的永磁同步电机(PMSM)输入-输出线性化(IOL)精确转矩控制方法。针对传统解耦控制在非线性转矩特性下的局限性,提出通过精确反馈线性化实现转矩指令与实际转矩的严格线性关系。文章系统阐述了IOL原理、PMSM控制器推导过程,并提供了完整的Simulink建模步骤,包括电机模型搭建、IOL控制器实现和闭环系统构建。通过仿真对比验证了IOL方法在转矩跟踪精度、动态响应和参数鲁棒性方面的显著优势,最后讨论了工程实现要点和扩展应用方向。该方法为高性能伺服系统开发提供了有效解决方案。

amy_mhd的博客 61

【编译原理】第四章 语法分析

引言 语法分析的主要任务:根据给定的文法,识别输入句子的各个成分,从而构造出句子的分析树 大部分程序设计语言的语法构造可以用CFG来描述,CFG以token作为终结符 大部分语法分析器都期望文法是无二义性的,否则,就不能为一个句子构造唯一的语法分析树 语法分析的种类 自顶向下分析:从分析树的顶部(根节点)向底部(叶节点)构造分析树;从文法开始符号S推导出串w 自底向上的分析:从分析树的底部(叶节...

无极阁 3645

液滴碰撞壁面的过程背景论文——bouncing反弹,spreading扩展,splashing飞溅。铺展过程介绍。还存在很多未解之谜。

【1993-德国-Phenomena of liquid drop impact on solid and liquid surfaces】液滴碰撞壁面的过程背景——bouncing反弹,spreading扩展,splashing飞溅。还存在很多未解之谜。还存在很多未解之谜。不同液滴形状碰撞过程。

qq_15963745的博客 200

哈工大编译原理期末复习(完整版)

哈工大编译原理期末复习(完整版)

CCCCheckRep 5683

NAS新玩法!豆瓣与迅雷结合,轻松实现自动下载电影自动追剧功能

NAS新玩法!豆瓣与迅雷结合,轻松实现自动下载电影自动追剧功能

XiaoqiangClub的博客 6392

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【编译原理】复习总结

第一章 编译:将高级语言翻译成汇编语言或机器语言的过程 语句可以分为:声明语句和执行语句 ——字符流 词法分析:从左向右逐行扫描源程序,确定单词类型,将识别出来的单词转换成token token:<种别码,属性值> ——token流 语法分析:从词法分析器输出的token序列中识别出各类短语,构造语法分析树。 ——语法分析树 语义分析:字符表(标识符的属性信息),语义检查(变量或过程未声明就使用或重复声明,操作符与操作数类型不匹配、数组下标不是整数、函数返回类型不对等等) ——语法分析树 中间代

qq_44850725的博客 4713

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

编译原理——笔记

计算机语言由底层到高层为机器语言、汇编语言、高级语言;机器语言是 CPU 可直接执行的二进制代码,汇编用助记符简化二进制、和硬件高度绑定,高级语言语法贴近人类自然语言;将汇编语言翻译成机器语言叫汇编;将高级语言整体翻译成汇编 / 机器码的过程是编译,另有解释型语言无需完整编译,且编译生成机器码后还需链接才能得到可运行程序。编译器的位置处于经过了预处理后的源程序到输出到汇编器之间,输入的是预处理后的源代码,输出的则是汇编器可以理解的汇编语言。

lastXuanGod的博客 222

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

学习经验 | 编译原理第三版学习资料包

编译原理(第三版)》由张素琴、王生原、董渊等编著,由清华大学出版社出版,是计算机科学、软件工程及通信工程等专业的经典教材。作为一本理论与实践相结合的教材,它对于有意从事软件开发、系统设计等工作的学生,提供了坚实的理论基础和实践指导,是编译技术学习的必备参考书。内容包括编译器的基本功能、编译过程的阶段划分(词法、语法、语义分析等),以及编译器在语言处理系统中的作用。,需熟悉中间代码表示、流图与基本块的构建,优化方法如公共子表达式消除、代码移动、强度削弱等,以及目标代码生成中的指令选择和寄存器分配。

Baoyan_cs的博客 1195

编译原理学习(三)--语法分析树

语法分析树用图形方式展现了从文法的开始符号推导出相应语言中的符号串的过程。在具体理解语法分析树之前需要先理清楚一些基本概念: ①.产生式 用变量expr来表示表达式,用变量stmt表示语句,那么这个构造规则可以表示为:stmt--->if(expr)stmtelse stmt 其中的箭头(--->)可以读作“可以具有以下形式”,这样的规则称为产生式。 ②.文法定义 关于文法定义中的终

Leo-软件开发 4万+

语法分析(1)---上下文无关的文法(context-free grammars)

 文法(syntax)是一种描述编程语言结构的规则,比如,程序由语句块(block)组成,语句块又是由语句构成,语句又由表达构成,表达又是由词法记号(token)构成文法可以使用上下文无关的文法(context-free grammars)或者BNF(Backus - Naur Form)范式来描述  分析器(parser):从图中可以看出,parser获取词法记号流(

Jenhy的专栏 7933
上一篇: 词法分析:从RE(正则表达式)到DFA(确定的有限状态机)
下一篇: 从上下文无关文法(CFG)到语法分析树——SLR(1)分析法
cuiods
博客等级 码龄12年 41粉丝 15原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值