文章目录

  • 一、实验目的
  • 二、实验内容
  • 三、实验要求
  • 四、实验设计方案
  • 五、测试方案及测试结果
  • 结语
  • 附录

一、实验目的

根据文法编制预测分析法语法分析程序,以便对输入的符号串进行语法分析。通过编写预测分析法语法分析程序掌握预测分析法的基本原理、FIRST和FOLLOW集的计算、预测分析表的构造方法以及语法分析法主控程序的设计。

二、实验内容

对于给定的上下文无关文法,编程完成以下功能:
         (1)消除左递归
         (2)计算非终结符的FIRST和FOLLOW集
         (3)构造预测分析表
         (4)判断消除了左递归后的文法是否为LL(1)文法
         (5)编写预测分析法语法分析程序,要求对输入的任意符号串进行语法分析,输出推导过程或语法分析树。

三、实验要求

1、 输入/输出格式。文法的输入示例参考cfg1.txt以及cfg2.txt。例如文法以以下形式给出:

E::=E + T
E::=E - T
E::=T
T::=T * F
T::=T / F
T::=F
F::=( E )
F::=id

文法只给出产生式列表,每个产生式占一行,产生式右边的文法符号串每个符号之间有一个空格,末尾没有空格。第一个产生式左边的非终结符为开始符号。如果某非终结符A的候选式为ε,则产生式表示为“A::=”,即产生式的右部为空。(文法的输入格式也可以以你觉得合适的方式定义)
        输出的结果按照实验内容依次输出消除左递归后的文法,非终结符的FIRST和FOLLOW集,预测分析表、是否为LL(1)文法,以及输出测试字符串利用预测分析法进行语法分析。
        2、上述要求仅为基本要求,可以在此基础上扩充。例如能够处理间接左递归,增加错误处理,输出错误信息等。进一步可以指出出错的位置。
        3、编程语言不限。 本文使用C语言来实现。

四、实验设计方案

五、测试方案及测试结果

输入文法


消除左递归

计算非终结符的FIRST集

计算非终结符的FOLLOW

构造预测分析表


输入要进行分析的符号串


输出分析过程

结语

预测分析法语法分析器的设计的介绍就到这里啦,希望这篇文章能给予你一些帮助,感谢各位人才的:点赞、收藏和评论,我们下次见。

附录

以下提供测试代码
预测分析法语法分析器的设计

#include <stdio.h>
#include <stdlib.h>
#define MaxRuleNum 10
#define MaxVnNum 10
#define MaxVtNum 10
#define MaxStackDepth 20
#define MaxPLength 20
#define MaxStLength 50
#include <conio.h>struct pRNode { //产生式右部的结构int rCursor;//指向字符表的指针表示产生式右部字符struct pRNode *next;//链表的组织结构
};
struct pNode {int lCursor; //指向产生式左边字符int rLength; //产生式右部分的长度struct pRNode *rHead; //产生式右部分头指针
};char Vn[MaxVnNum + 1]; //非终结符集
int vnNum;char Vt[MaxVtNum + 1]; // 终结符集
int vtNum;struct pNode P[MaxRuleNum];//产生式集
int PNum;char buffer[MaxPLength + 1];//缓冲串集合
char ch;char st[MaxStLength]; //要分析的符号串struct collectNode { //定义first和follow集int nVt;//字符struct collectNode *next;
};struct collectNode* first[MaxVnNum + 1]; //first 集每个元素是个指向链表的指针
struct collectNode* follow[MaxVnNum + 1]; //follow 集int analyseTable[MaxVnNum + 1][MaxVtNum + 1 + 1];//分析表
int analyseStack[MaxStackDepth + 1]; //分析栈
int topAnalyse; /* 分析栈顶 */
void Init();/* 初始化 */
int IndexCh(char ch);
void InputVt(); /* 输入终结符 */
void InputVn();/* 输入非终结符 */
void ShowChArray(char* collect, int num);/* 输出 Vn 或 Vt 的内容 */
void InputP();/* 产生式输入 */
bool CheckP(char * st);/* 判断产生式正确性 */
void First(int U);
void AddFirst(int U, int nCh); /* 加入 first 集*/
bool HaveEmpty(int nVn);
void Follow(int V);/* 计算 follow 集*/
void AddFollow(int V, int nCh, int kind);
void ShowCollect(struct collectNode **collect);/* 输出 first 或 follow集*/
void FirstFollow();/* 计算 first 和 follow*/
void CreateAT();/* 构造预测分析表 */
void ShowAT();/* 输出分析表 */
void Identify(char *st);
void InitStack();
void ShowStack();
void Pop();
void Push(int r);
void printp();//输出所有产生式
void isdturn();//消除直接左递归
void isjturn();//消除间接左递归
void length();//更新长度int main() {char todo, ch;Init();InputVn();InputVt();InputP();getchar();//吃掉换行isjturn();isdturn();length();printf(" 所得不含左递归的产生式为:\n");printp();FirstFollow();printf(" 所得 first 集为: ");ShowCollect(first);printf(" 所得 follow 集为: ");ShowCollect(follow);CreateAT();ShowAT();todo = 'y';while ('y' == todo) {printf("\n 是否继续进行句型分析? (y / n):");todo = getchar();while ('y' != todo && 'n' != todo) {printf("\n(y / n)? ");todo = getchar();}if ('y' == todo) {int i;InitStack();printf(" 请输入符号串 ( 以#结束 ) : ");ch = getchar();i = 0;while ('#' != ch && i < MaxStLength) {if (' ' != ch && '\n' != ch) {st[i++] = ch;}ch = getchar();}if ('#' == ch && i < MaxStLength) {st[i] = ch;Identify(st);}elseprintf(" 输入出错! \n");}}getchar();
}
void Init() {int i, j;vnNum = 0;vtNum = 0;PNum = 0;for (i = 0; i <= MaxVnNum; i++)Vn[i] = '\0';//非终初始化for (i = 0; i <= MaxVtNum; i++)Vt[i] = '\0';//终初始化for (i = 0; i < MaxRuleNum; i++) {//产生式初始化P[i].lCursor = NULL;P[i].rHead = NULL;P[i].rLength = 0;}for (i = 0; i <= MaxPLength; i++)buffer[i] = '\0';//字符集初始化for (i = 0; i < MaxVnNum; i++) {first[i] = NULL;//first初始化follow[i] = NULL;//follow初始化}for (i = 0; i <= MaxVnNum; i++) {for (j = 0; j <= MaxVnNum + 1; j++)analyseTable[i][j] = -1;//分析表的初始化}
}
int IndexCh(char ch) {int n;n = 0; /*is Vn?*/while (ch != Vn[n] && '\0' != Vn[n])n++;if ('\0' != Vn[n])return 100 + n;//非终的值是大于100的n = 0; /*is Vt?*/while (ch != Vt[n] && '\0' != Vt[n])n++;if ('\0' != Vt[n])return n;return -1;//空返回-1
}void ShowChArray(char* collect) {int k = 0;while ('\0' != collect[k]) {printf(" %c ", collect[k++]);}printf("\n");
}void InputVn() {int inErr = 1;int n, k;char ch;while (inErr) {printf(" 请输入所有的非终结符,注意: ");printf(" 请将开始符放在第一位,并以 #号结束 :\n");ch = ' ';n = 0;/* 初始化数组 */while (n < MaxVnNum) {Vn[n++] = '\0';}n = 0;while (('#' != ch) && (n < MaxVnNum)) {if (' ' != ch && '\n' != ch && -1 == IndexCh(ch)) {//排除空格,换行,已经输入的字符Vn[n++] = ch;vnNum++;}ch = getchar();}Vn[n] = '#'; /* 以"#" 标志结束用于判断长度是否合法 */k = n;if ('#' != ch) {if ('#' != (ch = getchar())) {while ('#' != (ch = getchar()));//清除缓冲区,一会重新输入不能在读进去了printf("\n 符号数目超过限制! \n");inErr = 1;continue;}}/* 正确性确认,正确则,执行下下面,否则重新输入 */Vn[k] = '\0';ShowChArray(Vn);ch = ' ';while ('y' != ch && 'n' != ch) {if ('\n' != ch) {printf(" 输入正确确认 ?(y/n):");}scanf("%c", &ch);}if ('n' == ch) {printf(" 录入错误重新输入! \n");inErr = 1;}else {inErr = 0;}}
}
/* 输入终结符 */
void InputVt() {int inErr = 1;int n, k;char ch;while (inErr) {printf("\n 请输入所有的终结符,注意: ");printf(" 以#号结束 :\n");ch = ' ';n = 0;/* 初始化数组 */while (n < MaxVtNum) {Vt[n++] = '\0';}n = 0;while (('#' != ch) && (n < MaxVtNum)) {if (' ' != ch && '\n' != ch && -1 == IndexCh(ch)) {Vt[n++] = ch;vtNum++;}ch = getchar();}Vt[n] = '#';//默认最后一个是#k = n;if ('#' != ch) {if ('#' != (ch = getchar())) {while ('#' != (ch = getchar()));printf("\n 符号数目超过限制! \n");inErr = 1;continue;}}Vt[k] = '\0';ShowChArray(Vt);ch = ' ';while ('y' != ch && 'n' != ch) {if ('\n' != ch) {printf(" 输入正确确认 ?(y/n):");}scanf("%c", &ch);}if ('n' == ch) {printf(" 录入错误重新输入! \n");inErr = 1;}else {inErr = 0;}}
}
/* 产生式输入 */
void InputP() {char ch;int i = 0, n, num;printf(" 请输入文法产生式的个数: ");scanf("%d", &num);PNum = num;getchar(); //删除回车printf("\n 请输入文法的 %d个产生式 , 并以回车分隔每个产生式: ", num);printf("\n");while (i < num) {printf(" 第%d 个: ", i);/* 初始化 */for (n = 0; n < MaxPLength; n++)buffer[n] = '\0';/* 输入产生式串 */ch = ' ';n = 0;while ('\n' != (ch = getchar()) && n < MaxPLength) {if (' ' != ch)//除去空格换行buffer[n++] = ch;}buffer[n] = '\0';if (CheckP(buffer)) {pRNode *pt, *qt;P[i].lCursor = IndexCh(buffer[0]);//产生式左边赋值pt = (pRNode*)malloc(sizeof(pRNode));//构造产生式右部pt->rCursor = IndexCh(buffer[3]);pt->next = NULL;P[i].rHead = pt;//构造头结点n = 4;while ('\0' != buffer[n]) {//构造链表qt = (pRNode*)malloc(sizeof(pRNode));qt->rCursor = IndexCh(buffer[n]);qt->next = NULL;pt->next = qt;pt = qt;//pt跟着qtn++;}P[i].rLength = n - 3;//产生式右部长度i++;}elseprintf(" 输入符号含非法在成分,请重新输入! \n");}
}
/* 判断产生式正确性 */
bool CheckP(char * st) {int n;if (100 > IndexCh(st[0]))//如果第一个字符是终结符return false;if ('-' != st[1])//终结符后面不是->则报错return false;if ('>' != st[2])return false;for (n = 3; '\0' != st[n]; n++) {if (-1 == IndexCh(st[n]))//输入了不存在的报错return false;}return true;
}
//消除间接左递归
void isjturn()
{for (int j = 0; j<vnNum; j++){for (int i = 0; i < PNum; i++){if (j == (P[i].lCursor - 100) && P[i].rHead->rCursor >= 100 && P[i].rHead->rCursor<P[i].lCursor){for (int k = 0; k<i; k++){if (P[k].lCursor == P[i].rHead->rCursor){pRNode * p = P[k].rHead;pRNode * qt = (pRNode*)malloc(sizeof(pRNode));pRNode * head = qt;while (p != NULL){pRNode * pt = (pRNode*)malloc(sizeof(pRNode));pt->rCursor = p->rCursor;qt->next = pt;qt = pt;p = p->next;}qt->next = P[i].rHead->next;P[i].rHead = head->next;}}}}}
}
//消除直接左递归
void isdturn()
{int flag2 = 0;struct collectNode *pa[10];//作为a的数组struct collectNode *pb[10];for (int i = 0; i<10; i++){pa[i] = pb[i] = NULL;}int n = 0, m = 0;pRNode * p = NULL;for (int j = 0; j<vnNum; j++){int flag1 = 0;for (int i = 0; i < PNum; i++){if (j == P[i].lCursor - 100 && j == P[i].rHead->rCursor - 100){flag1 = 1; break;}}if (flag1 == 1){for (int i = 0; i < PNum; i++){if (j == (P[i].lCursor - 100) && j == (P[i].rHead->rCursor - 100)){n++;P[i].lCursor = vnNum + 100;p = P[i].rHead = P[i].rHead->next;pRNode* pt = (pRNode*)malloc(sizeof(pRNode));//构造产生式右部pt->rCursor = vnNum + 100;pt->next = NULL;while (p->next != NULL) p = p->next;p->next = pt;}if (j == (P[i].lCursor - 100) && j != (P[i].rHead->rCursor - 100) && -1 != P[i].rHead->rCursor){p = P[i].rHead = P[i].rHead;pRNode* pt = (pRNode*)malloc(sizeof(pRNode));//构造产生式右部pt->rCursor = vnNum + 100;pt->next = NULL;while (p->next != NULL) p = p->next;p->next = pt;}}P[PNum++].lCursor = vnNum + 100;pRNode* pt = (pRNode*)malloc(sizeof(pRNode));//构造产生式右部pt->rCursor = -1; pt->next = NULL;P[PNum - 1].rHead = pt;Vn[vnNum++] = Vn[j] + 32;}}
}void First(int U) {int i, j;for (i = 0; i < PNum; i++) {//对于每一个产生式if (P[i].lCursor == U) {//如果产生式的左边是该非struct pRNode* pt;pt = P[i].rHead;//找到右部产生式j = 0;while (j < P[i].rLength) {if (100 > pt->rCursor) {//如果是终结符AddFirst(U, pt->rCursor);//加到它的first集合就不在往后看了break;}else {if (NULL == first[pt->rCursor - 100]) {//非终结符如果它first集合空First(pt->rCursor);//求他的first集合}AddFirst(U, pt->rCursor);//把它的first集合加入,非空if (!HaveEmpty(pt->rCursor)) {break;}else {pt = pt->next;//如果该非终的first有空找下一个}}j++;}if (j >= P[i].rLength) // 当产生式右部都能推出空时 才把空加进去AddFirst(U, -1);}}
}/* 加入 first 集*/
void AddFirst(int U, int nCh) {//把nch加到终结符U的first集struct collectNode *pt, *qt;int ch; /* 用于处理 Vn*/pt = NULL;qt = NULL;if (nCh < 100) {//对于终结符pt = first[U - 100];//找到它的first集合的链表while (NULL != pt) {if (pt->nVt == nCh)break;else {qt = pt;pt = pt->next;//qt记录前一,pt一直到空}}if (NULL == pt) {pt = (struct collectNode *)malloc(sizeof(struct collectNode));pt->nVt = nCh;pt->next = NULL;if (NULL == first[U - 100]) {//如果本来就没有,则直接将他作为头结点first[U - 100] = pt;}else {qt->next = pt; //新加入到first集合的字符连到链表上}pt = pt->next;}}else {//终结符pt = first[nCh - 100];while (NULL != pt) {ch = pt->nVt;if (-1 != ch) {AddFirst(U, ch);//将它first集合非空部分加入。}pt = pt->next;}}
}
bool HaveEmpty(int nVn) {//非终且能推出空则trueif (nVn < 100)return false;struct collectNode *pt;pt = first[nVn - 100];while (NULL != pt) {if (-1 == pt->nVt)return true;pt = pt->next;}return false;
}
void Follow(int V) {int i;struct pRNode *pt;if (100 == V) // 当为字符是初始字符的时候AddFollow(V, -1, 0);//直接把结束符加进去for (i = 0; i < PNum; i++) {pt = P[i].rHead;while (NULL != pt && pt->rCursor != V)pt = pt->next;//产生式的有部找Vif (NULL != pt) {//找到了pt = pt->next;if (NULL == pt) {//是最后一个字符if (NULL == follow[P[i].lCursor - 100] && P[i].lCursor != V) {//把左侧非V且有follow的非的集合加进去(含空)Follow(P[i].lCursor);}AddFollow(V, P[i].lCursor, 0);}else {while (NULL != pt && HaveEmpty(pt->rCursor)) {//因为没有判断fellow集合是否不变的机制,所以需要一直看到头AddFollow(V, pt->rCursor, 1);//如果后面是非终有空pt = pt->next;//每一个非终的first}if (NULL == pt) {//如果后面没有了if (NULL == follow[P[i].lCursor - 100] && P[i].lCursor != V) {Follow(P[i].lCursor);//那么说明这个非终是最后一个,那么把产生式左边的fello加进去}AddFollow(V, P[i].lCursor, 0);}else {AddFollow(V, pt->rCursor, 1);//否则最后一个姚明是终要么是不含空非终first加入}}}}
}
void AddFollow(int V, int nCh, int kind) {struct collectNode *pt, *qt;int ch;pt = NULL;qt = NULL;if (nCh < 100) { /* 为终结符时直接加入链表尾部 */pt = follow[V - 100];while (NULL != pt) {if (pt->nVt == nCh)break;else {qt = pt;pt = pt->next;}}if (NULL == pt) {pt = (struct collectNode *)malloc(sizeof(struct collectNode));pt->nVt = nCh;pt->next = NULL;if (NULL == follow[V - 100]) {follow[V - 100] = pt;}else {qt->next = pt;}pt = pt->next;}}else {//非终结符的时候if (0 == kind) {//直接把follow加进去pt = follow[nCh - 100];while (NULL != pt) {ch = pt->nVt;AddFollow(V, ch, 0);pt = pt->next;}}else {//把不含空的first加进去pt = first[nCh - 100];while (NULL != pt) {ch = pt->nVt;if (-1 != ch) {AddFollow(V, ch, 1);}pt = pt->next;}}}
}
/* 输出 first 或 follow 集*/
void ShowCollect(struct collectNode **collect) {int i;struct collectNode *pt;i = 0;while (NULL != collect[i]) {pt = collect[i];printf("\n%c:\t", Vn[i]);while (NULL != pt) {if (-1 != pt->nVt) {printf(" %c", Vt[pt->nVt]);}elseprintf(" #");//把空转化成"#"pt = pt->next;}i++;}printf("\n");
}
/* 计算 first 和 follow*/
void FirstFollow() {int i;i = 0;while ('\0' != Vn[i]) {if (NULL == first[i])First(100 + i);//非终结符对应的序号在100外i++;}i = 0;while ('\0' != Vn[i]) {if (NULL == follow[i])Follow(100 + i);i++;}
}
/* 构造预测分析表 */
void CreateAT() {int i;struct pRNode *pt;struct collectNode *ct;for (i = 0; i < PNum; i++) {//对每个产生式pt = P[i].rHead;while (NULL != pt && HaveEmpty(pt->rCursor)) {//非终且能推出空ct = first[pt->rCursor - 100];while (NULL != ct) {if (-1 != ct->nVt)analyseTable[P[i].lCursor - 100][ct->nVt] = i;//产生式左侧遇到它的右侧第一个非终的first集合ct = ct->next;}pt = pt->next;}if (NULL == pt) {//后面都可以推出空ct = follow[P[i].lCursor - 100];while (NULL != ct) {if (-1 != ct->nVt)analyseTable[P[i].lCursor - 100][ct->nVt] = i;else//follow空其实就是遇到了#analyseTable[P[i].lCursor - 100][vtNum] = i;//最后一列是#ct = ct->next;}}else {//最后一个不能推出空if (100 <= pt->rCursor) { /* 不含空的非终结符 */ct = first[pt->rCursor - 100];while (NULL != ct) {analyseTable[P[i].lCursor - 100][ct->nVt] = i;ct = ct->next;}}else { /* 非空的终结符或者空 */if (-1 == pt->rCursor) {//相当于是推出了空ct = follow[P[i].lCursor - 100];while (NULL != ct) {if (-1 != ct->nVt)//if(analyseTable[P[i].lCursor - 100][ct->nVt] ==-1 )analyseTable[P[i].lCursor - 100][ct->nVt] = i;else /* 当含有 # 号时 */analyseTable[P[i].lCursor - 100][vtNum] = i;ct = ct->next;}}else { /* 为终结符 */analyseTable[P[i].lCursor - 100][pt->rCursor] = i;}}}}
}
/* 输出分析表 */
void ShowAT() {int i, j;printf(" 构造预测分析表如下: \n");printf("\t|\t");for (i = 0; i < vtNum; i++) {printf("%c\t", Vt[i]);//行头是所有终}printf("#\t\n");//#单独输出printf("- - -\t|- - -\t");for (i = 0; i <= vtNum; i++)printf("- - -\t");printf("\n");for (i = 0; i < vnNum; i++) {printf("%c\t|\t", Vn[i]);//列头是终结符for (j = 0; j <= vtNum; j++) {if (-1 != analyseTable[i][j])printf("R(%d)\t", analyseTable[i][j]);elseprintf("     \t");}printf("\n");}
}void Identify(char *st) {//构造栈int current, step, r; /*r 表使用的产生式的序号 */printf("\n%s 的分析过程: \n", st);printf(" 步骤 \t 分析符号栈 \t 当前指示字符 \t 使用产生式序号 \n");step = 0;//第几步current = 0;//输入串指针printf("%d\t", step);ShowStack();//栈你初始就有#和开始符号printf("\t\t%c\t\t- -\n", st[current]);while ('#' != st[current]) {//当输入串剩下#结束if (100 > analyseStack[topAnalyse]) {if (analyseStack[topAnalyse] == IndexCh(st[current])) {Pop();//终结符匹配,则出栈current++;step++;printf("%d\t", step);ShowStack();printf("\t\t%c\t\t 出栈、后移 \n", st[current]);}else {printf("%c-%c 不匹配! ", analyseStack[topAnalyse], st[current]);printf(" 此串不是此文法的句子! \n");return;}}else { /* 当为非终结符时 */r = analyseTable[analyseStack[topAnalyse] -100][IndexCh(st[current])];if (-1 != r) {Push(r);//push里有popstep++;printf("%d\t", step);ShowStack();printf("\t\t%c\t\t%d\n", st[current], r);}else {printf(" 此串不是此文法的句子! \n");return;}}}if ('#' == st[current]) {if (0 == topAnalyse && '#' == st[current]) {step++;printf("%d\t", step);ShowStack();printf("\t\t%c\t\t 分析成功! \n", st[current]);printf("%s 是给定文法的句子! \n", st);}else {while (topAnalyse > 0) {if (100 > analyseStack[topAnalyse]) {//终结符肯定不是printf(" 此串不是此文法的句子! \n");return;}else {//虽然输入串此时是#当站内是非终是,只有遇到推出空才行r = analyseTable[analyseStack[topAnalyse] - 100][vtNum];if (-1 != r) {Push(r);step++;printf("%d\t", step);ShowStack();if (0 == topAnalyse && '#' == st[current]) {//可能有多个符号条件的非printf("\t\t%c\t\t 分析成功! \n", st[current]);printf("%s 是给定文法的句子! \n", st);}elseprintf("\t\t%c\t\t%d\n", st[current], r);}else {printf(" 此串不是此文法的句子! \n");return;}}}}}
}
/* 初始化栈及符号串 */
void InitStack() {int i;/* 分析栈的初始化 */for (i = 0; i < MaxStLength; i++)st[i] = '\0';analyseStack[0] = -1; /*#(-1) 入栈 */analyseStack[1] = 100; /* 初始符入栈 */topAnalyse = 1;//栈顶指针,指向栈顶元素
}
/* 显示符号栈中内容 */
void ShowStack() {int i;for (i = 0; i <= topAnalyse; i++) {if (100 <= analyseStack[i])printf("%c", Vn[analyseStack[i] - 100]);else {if (-1 != analyseStack[i])printf("%c", Vt[analyseStack[i]]);elseprintf("#");}}
}
/* 栈顶出栈 */
void Pop() {topAnalyse--;
}
void Push(int r) {int i;struct pRNode *pt;Pop();//pt = P[r].rHead;if (-1 == pt->rCursor)return;//产生式右部是空不进栈topAnalyse += P[r].rLength;for (i = 0; i < P[r].rLength; i++) {analyseStack[topAnalyse - i] = pt->rCursor;/* 逆序入栈 */pt = pt->next;}
}
//输出所有产生式
void printp()
{for (int i = 0; i < PNum; i++){putchar(Vn[P[i].lCursor - 100]);printf("->");pRNode* pt = P[i].rHead;while (pt != NULL){if (pt->rCursor >= 100)putchar(Vn[pt->rCursor - 100]);else putchar(Vt[pt->rCursor]);pt = pt->next;}printf("\n");}
}void length()//更新有部产生式的长度
{for (int i = 0; i < PNum; i++){int count = 0;pRNode* pt = P[i].rHead;while (pt != NULL){pt = pt->next;count++;}P[i].rLength = count;}}

文法的输入示例

cfg1.txt

E::=E + T
E::=E - T
E::=T
T::=T * F
T::=T / F
T::=F
F::=( E )
F::=idE->E + T
E->E - T
E->T
T->T * F
T->T / F
T->F
F->( E )
F->i

cfg2.txt

S::=( L )
S::=a
L::=L , S
L::=S

预测分析法语法分析器的设计相关推荐

  1. lr1分析器c语言实验报告怎么写,编译原理课程的设计构造LR分析法语法分析器.doc...

    编译原理课程的设计构造LR分析法语法分析器 太 原 学 院 课程设计报告书 课程名称 设计题目 构造LR(0)分析法语法分析器 专业班级 学 号 姓 名 指导教师 2016年 12 月 15日 目 录 ...

  2. 编译原理预测分析法c语言,编译原理预测分析法C语言的实验报告.doc

    题目:编写识别由下列文法所定义的表达式的预测分析程序. EàE+T | E-T | T TàT*F | T/F |F Fà(E) | i 输入:每行含一个表达式的文本文件. 输出:分析成功或不成功信息 ...

  3. 【编译原理】LR语法分析器的设计与实现

    LR语法分析器的设计与实现 本文为当时编译原理实验作业,要求用设计的思想完成,小题大做,仅供参考 文章目录 LR语法分析器的设计与实现 实验要求 实现功能 输入输出 样例 一.LR语法分析器问题定义 ...

  4. 【编译原理笔记05】语法分析:FIRST集和FOLLOW集的计算,[非]递归的预测分析法,预测分析中的错误处理

    本次笔记内容: 4-4 FIRST集和FOLLOW集 4-5 递归的预测分析法 4-6 非递归的预测分析法 4-7 预测分析法中的错误处理 本节课幻灯片,见于我的 GitHub 仓库:第5讲 语法分析 ...

  5. 南华大学编译原理----词法分析器的设计与实现、语法分析器的设计与实现

    下载链接:(各位同学不需要充钱哈,这种我也没有收益,去淘宝上面找个代下,大概0.5元就能下载实验报告,用来给同学们参考,下载积分不是我设置的,是网站自己默认的) ------------------- ...

  6. 编译原理 LL(1)语法分析器的设计与实现

    实验内容 针对SysY语言中简单算术表达式文法G[E]: E→TE' E'→ATE'|ε T→FT' T'→MFT' |ε F→(E) | i A → + | - M → * | / 求解相应的FIR ...

  7. 4.2.5 预测分析法与预测分析表的构造

    4.2.5 预测分析法与预测分析表的构造 预测分析法也称为 LL ( 1 )分析法.这种分析法是确定的自上而下分析的另一种方法,采用这种方法进行语法分析要求描述语言的文法是 LL ( 1 )文法. 一 ...

  8. 语法分析:自上而下分析(递归下降分析法+预测分析法)

    语法分析:自上而下分析 目录 语法分析:自上而下分析 知识背景 递归下降分析法 内容一:根据文法生成子程序 内容二:调用文法开始符号所对应的子程序 预测分析法 内容一:构造预测分析表 内容二:预测分析 ...

  9. 编译原理之语法分析(预测分析法)

    编译器之语法分析 自顶向下 上下文无关文法 语法树 NFA→CFG 预测分析法 改写CFG 原因 消除二义性 消除左递归 消除左公因子 消除空产生式 消除回路 自顶向下 上下文无关文法 CFG本质上就 ...

最新文章

  1. ADSL的PPPOE拨号客户端上的ppp authentication pap “callin”的正确理解
  2. Android 实现图片的单点缩放、拖动、旋转
  3. 将字符串转换为日期时间
  4. 13.2System类中的常用方法
  5. 餐饮供应链公司“鲜沐农场”获千万级Pre-A轮融资,未来要打造一站式采购平台...
  6. 用python正确的获取文件最后被修改的时间
  7. SAP UI5 的初始化过程
  8. .Net之微信小程序获取用户UnionID
  9. Solr-5.3.1安装配置
  10. 计算机是一种在什么控制下 自动高速,计算机是一种能对数字化信息进行自动高速运算的通用处....ppt...
  11. JS/jQuery获取input的值和清空input的value值
  12. golang dlv 远程调试
  13. 这篇文章,专治MQ中间件各种疑难杂症
  14. 二十二 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy模拟登陆和知乎倒立文字验证码识别...
  15. DevExpress 破解方式
  16. JavaScript项目中锁定npm依赖包版本
  17. php smarty 语法,5. Smarty基本语法
  18. html dd标签隐藏,HTML dl dt dd 标签
  19. 快来试试用 Python 将你的照片转化为“速写”
  20. Affine-Transformation Parameters Regression for Face Alignment

热门文章

  1. Loop Energy为中国南京市公交车队提供燃料电池,创下超过7.5万公里的运营里程记录
  2. 【c++】入门5 输入语句
  3. redis高可用几种方案
  4. 谋求独立上市,保时捷加速大众化
  5. html中给li赋值,原生js拖拽ul里面的li给input赋值
  6. java中pre是什么意思_HTML标签PRE在代码中是什么意思
  7. 感谢张家界钟家兄弟的服务
  8. 易优cms searchform 搜索标签使用方法
  9. 64-bit版本的Windows7完美安装USB下载驱动
  10. Butler-Volmer 方程与Nernst 方程的关系