LL(1)文法:从文法的开始符,向下推导,推出句子。

对文法G的句子进行确定的自顶向下语法分析的充分必要条件是,G的任意两个具有相同左部的
产生式A—>α|β 满足下列条件:
(1)如果α、β均不能推导出ε,则 FIRST(α) ∩ FIRST(β) = ∅。
(2)α 和 β 至多有一个能推导出 ε。
(3)如果 β *═> ε,则 FIRST(α) ∩ FOLLOW(A) = ∅。
将满足上述条件的文法称为LL(1)文法。
 
一、消除左递归
由于自上而下的分析方法不允许文法含有左递归。
因此对于包含直接左递归和间接左递归的文法都要消除左递归。
直接消除左递归比较容易。
例如:
  P->Pa | b
直接消除左递归
  P->bP'
  P'->aP' | ε
 
二、提左因子
如果不提左因子,当面临两个相同的前缀,不知道选择哪条,必然会产生回溯。为了消除回溯,我们需要提左因子。
例如
 
 
三、实验

已知算术表达式文法 G[E]:

E → T E'

E' → + T E'|ε

T → F T'

T' → * F T'|ε

F → ( E )|i

判断该文法是否为 LL(1)文法,计算 FIRST 集合和 FOLLOW 集合

SELECT(E→T E')= FIRST(T)= {(, i}

SELECT(E'→+ T E')= {+}

SELECT(E'→ε)= FOLLOW(E')= {), #}

SELECT(T→F T')= FIRST(F)= {(, i}

SELECT(T' →* F T')= {*}

SELECT(T'→ε)= FOLLOW(T')= {+, ), #}

SELECT(F → ( E ))= {(}

SELECT(F → i)= {i}

具有相同左部产生式的 SELECT 集合交集为空

SELECT(E'→+ T E')∩SELECT(E'→ε)= {+}∩{), #}=Φ

SELECT(T' →* F T')∩SELECT(T'→ε) = {*}∩{+, ), #}=Φ

SELECT(F → ( E ))∩SELECT(F → i) = {(}∩{i}=Φ

所以,转换后的文法是 LL(1)文法。

此外,我们构造LL(1)分析表

表1-1 LL(1)分析表

i

+

*

#

E

E->TE’

E->TE’

E’

E’->+TE’

E’->ε

E’->ε

T

T->FT’

T->FT’

T’

T’->ε

T’->*FT’

T’->ε

T’->ε

F

F->i

F->(E)

 
程序如下:
 1 #include<bits/stdc++.h>
2 #define ROW 6
3 #define COLUMN 9
4 using namespace std;
5 string table[ROW][COLUMN]={
6 {"","(",")","*","+","-","/","i","#"},
7 {"E","Te","","","","","","Te",""},
8 {"e","","ε","","+Te","-Te","","","ε"},
9 {"T","Ft","","","","","","Ft",""},
10 {"t","","ε","*Ft","ε","ε","/Ft","","ε"},
11 {"F","(E)","","","","","","i",""}};
12 string Get_table(string x,string a){
13 string ans="";
14 for(int i=0;i<ROW;i++){
15 for(int j=0;j<COLUMN;j++){
16 if(x==table[i][0]&&a==table[0][j]){
17 ans=table[i][j];
18 return ans;
19 }
20 }
21 }
22 return ans;
23 }
24 bool check_LL1(string input){
25 bool flag=true;
26 stack < string > s;
27 s.push("#");
28 s.push("E");
29 int i=0;
30 string a=input.substr(i,1);
31 string x;
32 while(flag){
33 string RS;
34 x=s.top();
35 if(x==a && a=="#"){
36 break;
37 }else if(x==a && a!="#"){
38 s.pop();
39 i++;
40 a=input.substr(i,1);
41 }else if((RS=Get_table(x,a))!=""){
42 if(RS!="ε"){
43 s.pop();
44 for(int j=RS.length()-1;j>=0;j--){
45 string tmp=RS.substr(j,1);
46 s.push(tmp);
47 }
48 }else{
49 s.pop();
50 }
51 }else{
52 flag=false;
53 break;
54 }
55 }
56 return flag;
57 }
58 int main(){
59 string input;
60 while(cin>>input){
61 input=input+"#";
62 if(check_LL1(input)){
63 cout<<"correct"<<endl;
64 }else{
65 cout<<"error"<<endl;
66 }
67 }
68 return 0;
69 }

实验截图:

 
 

自上而下的LL(1)语法分析法的更多相关文章

  1. 《编译原理》-用例题理解-自底向上的语法分析,FIRSTVT,LASTVT集

    <编译原理>-用例题理解-自底向上的语法分析,FIRSTVT,LASTVT集 上一篇:编译原理-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 本 ...

  2. 《程序设计语言——实践之路》【PDF】下载

    程序设计语言--实践之路>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382240 内容简介 本书在美国大学已有使用了十余年,目前被欧 ...

  3. 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

    近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIR ...

  4. 编译原理学习笔记·语法分析(LL(1)分析法/算符优先分析法OPG)及例子详解

    语法分析(自顶向下/自底向上) 自顶向下 递归下降分析法 这种带回溯的自顶向下的分析方法实际上是一种穷举的不断试探的过程,分析效率极低,在实际的编译程序中极少使用. LL(1)分析法 又称预测分析法, ...

  5. TINY语言采用递归下降分析法编写语法分析程序

    目录 自顶向下分析方法 TINY文法 消左提左.构造first follow 基本思想 python构造源码 运行结果 参考来源:聊聊编译原理(二) - 语法分析 自顶向下分析方法 自顶向下分析方法: ...

  6. 编译原理实习(应用预测分析法LL(1)实现语法分析)

    #include<iostream> #include<fstream> #include<iomanip> #include<cstdio> #inc ...

  7. Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法

    Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法 于是我们可以把上面的语法改写成如下形式:1 合并前缀1 语法分析有自上而下和自下而上两种分析 ...

  8. 语法设计——基于LL(1)文法的预测分析表法

    实验二.语法设计--基于LL(1)文法的预测分析表法 一.实验目的 通过实验教学,加深学生对所学的关于编译的理论知识的理解,增强学生对所学知识的综合应用能力,并通过实践达到对所学的知识进行验证.通过对 ...

  9. 语法分析~LL1的实现

    语法分析之 LL1分析法实现 一.设计目的 根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析.本次实验的目的主要是加深对预测分析LL(1)分析法的理解. 二.设计要求 程序输入/ ...

  10. K近邻法(KNN)原理小结

    K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出 ...

随机推荐

  1. Python连接Neo4j工具比较 Neo4j Driver、py2neo

    Python有许多可以连接Neo4j的库和工具,以下是一些常用的: Neo4j Driver for Python 这是官方提供的Python驱动程序,它使用Cypher查询语言与Neo4j数据库进行 ...

  2. codeforces600E. Lomsat gelral(dsu on tree笔记)

    知识前驱:树链剖分 codeforces600E. Lomsat gelral 题意:给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和 分析:递归求解,对于一棵树,求出他的所有子树的颜色编号 ...

  3. ContentPresenter使用DataTemplate

    在使用自定义样式内容时,有时也需要在自定义样式中绑定一下数据模板 可以使用ContentPresenter的ContentTemplate绑定定义好的资源 DateTemplate 用法代码如下 &l ...

  4. 「Tricks」整体DP

    不太了解这个东西的具体定义是什么,总之应该是一个用数据结构维护 DP 状态的某几个维度的 trick 吧. 事实上你可以把这篇 post 理解为三个题的解集. 先直接来看 noi2020 - Dest ...

  5. Record - Nov. 27st, 2020 - Exam. REC & SOL

    Problem. 1 Junior - Thinking Desc. & Link. 注意到值域乘范围刚好能过. 然后就存两个桶即可...(数组开小飞了半天才调出来...) Problem. ...

  6. DHCP是什么

    DHCP 1. DHCP是什么 协议,一种应用层的网络协议,他可以动态地分配网络中的IP地址和其他网络配置的参数以及网络设备,通俗一点讲,每台设备的IP地址,子网掩码,网关等网络参数信息都是由他来完成 ...

  7. 基于TOTP算法的Github两步验证2FA(双因子)机制Python3.10实现

    从今年(2023)三月份开始,Github开始强制用户开启两步验证2FA(双因子)登录验证,毫无疑问,是出于安全层面的考虑,毕竟Github账号一旦被盗,所有代码仓库都会毁于一旦,关于双因子登录的必要 ...

  8. Python比较字符串格式类型时间大小

    已知的格式是 06/24/2021 15:47:01.491 时间比较的思路是,把数据转换成时间戳比较: 第一步是把 06/24/2021 15:47:01.491 格式转换称 2021-06-24 ...

  9. ai绘画提示词

    (Drunken with Lights and Swords: 1.8), (Outdoor: 1.8), (Bust Close-up: 2.9), (solo: 3.8), 1 ancient ...

  10. 14. 从零开始编写一个wmproxy(代理,内网穿透等), HTTP文件服务器的实现过程及参数

    用Rust手把手编写一个wmproxy(代理,内网穿透等), HTTP中的压缩gzip,deflate,brotli算法 项目 ++wmproxy++ gite: https://gitee.com/ ...