算符优先分析算法(c语言).(优选)
算符优先分析编译原理演示文稿
(优选)算符优先分析编译原 理
6.3 算符优先分析法
算符优先文法的定义 算符优先关系表的构造 算符优先分析算法 算符优先分析法的局限性
6.3.1 算符优先分析
• 自下而上分析算法模型----移进归约 • 算符优先分析不是规范归约
算符优先分析的可归约 串是句型的最左素短语 定义: cfg(上下文无关文法) G 的句型的素短
2)’<‘关系
– 求出每个非终结符B的FIRSTVT(B)
– 若A→…aB…,则b∈FIRSTVT(B),则a<b
3)’>’关系
– 求出每个非终结符B的LASTVT(B)
– 若A→…Bb…,则a∈LASTVT(B),则a>b
计算算符优先关系
例文法G’[E’]: (0) E’→#E# (1) E→E+T (2) E→T (3) T→T*F (4) T→F (5) F→PF|P (6) P→(E) (7) P→i
例 G’[E]:
算符优先关表
E→E+T|T
T→T*F|F F→P↑F|P
P→(E)|i
+ * ( ) i#
+>< << >< >
*> > < < > < >
> > < < > < >
( < < < <=<
)>>>
>
>
i >>>
>
>
#< < < <
<=
算符优先分析方法
目录1.课程设计的目的与原理...........................................................错误!未定义书签。
1.1设计目的............................................................................. 错误!未定义书签。
1.2设计原理............................................................................. 错误!未定义书签。
2.课程设计环境...........................................................................错误!未定义书签。
3.课程设计内容...........................................................................错误!未定义书签。
3.1算符优先分析流程图......................................................... 错误!未定义书签。
3.2算符优先总流程图............................................................. 错误!未定义书签。
3.3算符优先文法..................................................................... 错误!未定义书签。
3.4 程序调试 (5)4.总结 (6)附录 (6)算符优先分析方法1.课程设计目的与原理1.1设计目的1.了解利用算符优先算法进行移进规约分析的方法。
2. 锻炼和提高自己的编程能力。
算符优先实验报告
算符优先实验报告《算符优先实验报告》引言算符优先是一种用于解决算术表达式中运算符优先级的算法,它可以帮助我们在计算表达式时确定运算符的优先级,从而得到正确的计算结果。
本实验旨在通过编写算符优先算法的程序,来深入理解算符优先的原理和应用。
实验目的1. 了解算符优先算法的原理和应用。
2. 掌握算符优先算法的程序设计方法。
3. 实现一个能够正确解析算术表达式并计算结果的程序。
实验内容1. 算符优先算法的原理和应用算符优先算法是一种基于文法的算法,它通过分析运算符之间的优先级和结合性来确定表达式的计算顺序。
在算符优先算法中,每个运算符都有一个优先级,高优先级的运算符先进行计算,低优先级的运算符后进行计算。
此外,算符优先算法还要考虑到运算符的结合性,即左结合或右结合。
2. 算符优先算法的程序设计方法为了实现算符优先算法,我们需要首先定义运算符的优先级和结合性,然后编写程序来解析表达式并按照算符优先规则进行计算。
在程序设计中,我们可以使用栈来辅助进行运算符的优先级判断和计算顺序的确定。
3. 实现一个能够正确解析算术表达式并计算结果的程序在本实验中,我们将编写一个简单的算符优先算法程序,该程序能够正确解析算术表达式并按照算符优先规则进行计算,最终得到正确的计算结果。
实验结果通过本次实验,我们成功实现了一个能够正确解析算术表达式并计算结果的程序。
该程序能够正确地处理不同优先级和结合性的运算符,并得到正确的计算结果。
这表明算符优先算法是一种有效的算法,能够帮助我们正确地处理算术表达式中的运算符优先级问题。
结论通过本次实验,我们深入理解了算符优先算法的原理和应用,并掌握了算符优先算法的程序设计方法。
算符优先算法是一种重要的算法,它在计算表达式时能够帮助我们确定运算符的优先级,从而得到正确的计算结果。
在今后的学习和工作中,我们将继续深入研究算符优先算法,并将其应用到更多的实际问题中。
c语言算符优先级
c语言算符优先级(原创版)目录1.算符优先级概述2.C 语言中的算符分类3.算符优先级的规则4.运算符的结合性和结合顺序5.算符优先级的应用实例正文【1.算符优先级概述】在 C 语言编程中,算符优先级是指在表达式中,各个运算符执行的先后顺序。
了解算符优先级有助于编写清晰、高效的代码,避免由于运算顺序不明确导致的错误。
【2.C 语言中的算符分类】C 语言中的运算符可以分为以下几类:(1)一级运算符:包括加(+)、减(-)、乘(*)、除(/)、取模(%)等。
(2)二级运算符:包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(=)、不等于(<>)等。
(3)三级运算符:包括括号(()、[]、{})、逗号(,)等。
【3.算符优先级的规则】C 语言中,算符优先级遵循以下规则:(1)同一级运算符按照从左到右的顺序执行。
(2)不同级运算符中,一级运算符的优先级最高,二级运算符次之,三级运算符优先级最低。
(3)有括号的表达式中,先计算括号内的运算。
【4.运算符的结合性和结合顺序】运算符的结合性是指运算符在表达式中能否结合在一起进行运算。
结合顺序是指运算符在表达式中从左到右进行结合的顺序。
在 C 语言中,运算符的结合性遵循“从左到右”的原则,即先结合左边的运算符,再结合右边的运算符。
【5.算符优先级的应用实例】了解算符优先级有助于解决复杂的表达式运算问题。
例如,对于表达式 a + b * c,根据算符优先级,我们首先进行乘法运算,然后进行加法运算,得到的结果为 (a + b) * c。
5.2-算符优先分析-简单介绍
结论: 对于二义性的表达式文法,我们可以直 结论: 对于二义性的表达式文法,
观地给出运算符之间的优先关系, 观地给出运算符之间的优先关系,使得输入串 的归约过程可以唯一确定. i1+i2*i3的归约过程可以唯一确定. 对任意给定的一个文法, 对任意给定的一个文法, 如何计算算符之间的优先关系? 如何计算算符之间的优先关系?
算符优先分析 语法树的框架 N N i + N i
规范归约过程
步骤 符号栈 1 2 3 4 5 6 7 8 9 10 # #i #F #T #E #E+ #E+i #E+F #E+T #E 剩余 动作 输入串 i+i# 移进 +i# +i# +i# +i# i# # # 归约 归约 归约 移进 移进 归约 归约 F→i F→i T→F T→F E→T E→T
; ; ( ) a + # ( ) a + #
课后思考: 课后思考:
1.给出输入串#(a+a)#的算符优先分析过程 1.给出输入串#(a+a)#的算符优先分析过程 给出输入串#(a+a)# 2.#(a+a)# 是文法的句子吗? 2.#(a& 语法分析 5.1 自下而上分析基本问题 5.2 算符优先分析 5.3 LR分析 分析 5.4 YACC
5.2 算符优先分析
5.2.1 算符优先文法及优先表构造 5.2.2 算符优先分析算法
优先分析法
• 根据某种优先关系确定 “可归约串 . 根据某种优先关系 优先关系确定 可归约串 可归约串” • 简单优先分析法 *
• 算符文法的两个限制
• 上下文无关文法 • 不含空产生式
补充例: 补充例:表达式文法
实验四算符优先分析算法
实验四:算符优先分析算法1.实验目的:掌握算符优先分析析程序的分析、设计与实现的基本技术与一般方法。
2.实验题目:编写并上机调试完成识别由下列文法所定义的表达式的算符优先分析程序。
E→E+T | E-T | TT→T*F | T/F |FF→(E) | i3.实验步骤(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, - , * , / , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , / , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }(3)程序参考源码/****************************************/ /* 程序名称:算符优先分析程序*/ /* 程序用途:编译原理实验(四) */ /* 编写日期:2005年11月15日*/ /* 实验题目:对下列文法*/ /* E->E+T|E-T|T */ /* T->T*F|T/F|F */ /* F->(E)|i */ /* 编写算符优先分析程序*/ /* 程序版本: 1.0 Final */ /* 程序作者:黄记瑶B0226047 */ /* 作者邮箱:****************/ /****************************************//****************************************//* 程序相关说明*//* 0=+ 1=- 2=* 3=/ 4=( 5=) 6=i 7=# *//* *//* 算符优先关系表*//* ------------------------------------------------------*//* + - * / ( ) i # *//* + > > < < < > < > *//* - > > < < < > < > *//* * > > > > < > < > *//* / > > > > < > < > *//* ( < < < < < = < ? *//* ) > > > > ? > ? > *//* i > > > > ? > ? > *//* # < < < < < ? < = *//* ------------------------------------------------- *//****************************************/#include "stdio.h"#include "malloc.h"struct Lchar{char char_ch;struct Lchar *next;}Lchar,*p,*h,*temp,*top,*base;int table[8][8]={{1,1,-1,-1,-1,1,-1,1},{1,1,-1,-1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{-1,-1,-1,-1,-1,-1,-1,0},{1,1,1,1,0,1,0,1},{1,1,1,1,0,1,0,1},{-1,-1,-1,-1,-1,0,-1,-1}};/*存储算符优先关系表,大于为1,小于或等于为-1,其它为0表示出错*/char curchar;char curcmp;int right;/*设置开关项,当出错时为0*/int i,j;int k;/*比较字符在栈的位置*/void push(char pchar)/*入栈函数*/{temp=malloc(sizeof(Lchar));temp->char_ch=pchar;temp->next=top;top=temp;}void pop(void)/*出栈函数*/{if(top->char_ch!='#')top=top->next;}int changchartoint(char ch)/*将字符转为数字,以得到算符优先值*/ {int t;switch(ch){case '+':t=0;break;case '-':t=1;break;case '*':t=2;break;case '/':t=3;break;case '(':t=4;break;case ')':t=5;break;case 'i':t=6;break;case '#':t=7;}return t;}void dosome(void){k=1;for(;;){curchar=h->char_ch;temp=top;for(;;){if(temp->char_ch=='N'){temp=temp->next;k++;}else{curcmp=temp->char_ch;break;}}printf("\n%d\t%d\t",table[i][j],k);temp=top;for(;;)/*打印栈*/{printf("%c",temp->char_ch);if(temp->char_ch=='#')break;elsetemp=temp->next;}printf("\t");temp=h;for(;;)/*打印待比较的字符*/{printf("%c",temp->char_ch);if(temp->char_ch=='#')break;elsetemp=temp->next;}i=changchartoint(curcmp);j=changchartoint(curchar);if(table[i][j]==0)/*算符优先值为空*/{printf("\n%d\t%d\t%c\t%c\terror1",table[i][j],k,curcmp,curchar);right=0;break;}else/*算符优先值不为空*/{if(table[i][j]<0)/*算符优先值为-1,移进*/{if(curchar=='#')/*待比较字符为空*/{if(k==2)/*当前比较字符在栈的位置为两个元素*/break;else{printf("\n%d\t%d\t%c\t%c\terror2",table[i][j],k,curcmp,curchar);right=0;break;}}push(curchar);h=h->next;}else/*算符优先值为1,归约*/{if(curcmp=='i')/*当前比较为i,出栈一次*/pop();else/*当前比较不为i,出栈三次*/{pop();pop();pop();}push('N');/*归约到N*/k=1;}}}}void main(void){char ch;right=1;base=malloc(sizeof(Lchar));base->next=NULL;base->char_ch='#';top=base;h=malloc(sizeof(Lchar));h->next=NULL;p=h;do{ /*输入待比较字符串,以'#'结束*/ch=getch();putch(ch);if(ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#'){temp=malloc(sizeof(Lchar));temp->next=NULL;temp->char_ch=ch;h->next=temp;h=h->next;}else{temp=p->next;printf("\nInput a wrong char!Input again:\n");for(;;){if (temp!=NULL)printf("%c",temp->char_ch);elsebreak;temp=temp->next;}}}while(ch!='#');/*输入待比较字符串,以'#'结束*/p=p->next;h=p;dosome();/*开始识别*/if(right)printf("\nOK!\n");elseprintf("\nError!\n");getch();}。
二语法分析程序(算符优先分析法)
实验二语法分析程序(算符优先分析法)一、实验目的通过设计调试算符优先分析程序,加深对课堂教学的理解,深刻理解自底向上语法分析方法的归约过程,提高语法分析方法的实践能力。
二、实验要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)实验要求独立完成,不允许有抄袭现象。
(4)实验完成后,要求提交源程序和上交实验报告(包括源程序清单)。
(附:实验报告格式)三、实验内容(1)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(2)分析的句子为:(i+i)*i和i+i)*i(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, * , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }FirstVT(E’)={ #} LastVT(E’)={ #}3,根据FirstVT和LastVT集构造算符优先表(2)程序参考源码#include <iostream>#include <string>using namespace std;#define max 100char b[max]; //存放终结符char precedence[max][max];//存放优先关系struct opg{int step;string stack;char privior;char presentsignal;string leftstr;string explain;}temp;//存放一步int search(char ch){int i=0;while(ch!=b[i])i++;return i;}void anolyze(){//struct opg temp;temp.step=0;char s[max],c,a;string sentence;int m=0,q=0,flag=0,i=0; //flag标记着当前读到那个字符cout<<"输入要分析的句子:";cin>>sentence;int k=0;//s[k]='#';s[k]=sentence[flag++];s[k+1]='\0';int j=k;a=sentence[flag++]; //读入一个给a;temp.leftstr=sentence;while(temp.leftstr[i]!=a){ //while循环获得第一次的剩余字符串temp.leftstr[i]=' ';i++;}temp.leftstr[i]=' ';//把已经读过的字符赋空则就找到了剩余的串cout<<"步骤 "<<" 栈 "<<" 优先关系 "<<"当前符号"<<" 剩余字符串 "<<"移进或归约"<<endl;while(!(s[j]=='#'&&a=='#')){//栈顶和当前字符都是#if(!isupper(s[k]))j=k;//s[k]是终结符else j=k-1;m=search(s[j]);//获取要比较终结符所在行号q=search(a);//获取要比较终结符所在列号temp.step=temp.step+1;temp.stack=s;temp.privior=precedence[m][q];temp.presentsignal=a;cout<<temp.step<<'\t'<<temp.stack<<'\t'<<temp.privior<<'\t'<<temp.presentsignal <<temp.leftstr<<'\t';if(precedence[m][q]=='<'||precedence[m][q]=='=')//优先关系为<或={temp.explain="移进";cout<<temp.explain<<endl;k=k+1;s[k]=a;s[k+1]='\0';//赋上字符串的终结标准,相当于一个栈a=sentence[flag++];//读入一个给a;temp.leftstr[++i]=' ';//每读入一个句子中一个字符把此位置赋空,作为剩余串}else if(precedence[m][q]=='>')//优先关系为>{temp.explain="归约";cout<<temp.explain<<endl;//cout<<s[j]<<s[k]<<a;do{c=s[j];if (!isupper(s[j-1]))//s[j-1]是终结符(即不是大写字母)j=j-1;elsej=j-2;m=search(s[j]);q=search(c);}while(precedence[m][q]=='=');k=j+1;s[k]='N';s[k+1]='\0';}//出错else {cout<<"不是该文法可以识别的句子";break;}//出错}cout<<++temp.step<<'\t'<<"#N"<<'\t'<<"="<<'\t'<<"#"<<' '<<'\t'<<"接受";}void main(){int n,i,j; //终结符的个数cout<<"输入终结符的个数:";cin>>n;cout<<endl;cout<<n<<'\n';cout<<"输入终结符";for(i=0;i<n;i++)cin>>b[i];b[n]='#';for(i=0;i<n+1;i++)for(j=0;j<n+1;j++){cout<<b[i]<<"与"<<b[j]<<"的优先关系:";cin>>precedence[i][j];while(!(precedence[i][j]=='>'||precedence[i][j]=='<'||precedence[i][j]=='=' ||precedence[i][j]=='/')){ cout<<"没有此优先关系,请重新输入";cin>>precedence[i][j];}}cout<<"算术优先关系表\n"<<"===============================================\n";for(i=0;i<n+2;i++)for(j=0;j<n+2;j++){if(i==0){if(j==0)cout<<' ';else cout<<b[j-1]<<' ';}else {if(j==0)cout<<b[i-1];else cout<<precedence[i-1][j-1]<<' ';}if(j==n+1)cout<<endl;}cout<<"===============================================\n";anolyze();}。
编译原理算符优先分析程序设计
编译原理算符优先分析程序设计算符优先分析(Operator Precedence Parsing)是一种基于文法的自下而上的语法分析方法,用于构造一个将输入串转化为语法分析树的分析器。
它通过根据每一个终结符号和非终结符号之间的优先级关系,来判断是否可以进行规约操作。
算符优先分析的基本思想是,为每一个终结符和非终结符分配一个优先级,然后根据这些优先级来决定如何进行规约操作。
一般来说,基本的终结符都有一个固定的优先级,而非终结符的优先级则由其所对应的产生式右部中的终结符优先级来决定。
算符优先分析的核心在于构造一个优先级关系表,用于指导规约过程。
这个表一般由产生式构造得到,每个终结符和非终结符对应一行和一列,表中的每个元素表示两个符号之间的优先级关系。
算符优先分析的步骤如下:1.根据给定的文法,确定每个终结符号和非终结符号的优先级。
2.构造优先关系表,填入每两个符号之间的优先关系。
3.初始化分析栈和输入栈,将栈底符号设为文法开始符号,并将输入串入栈。
4.重复以下步骤,直到分析完成:a.查找栈顶和当前输入符号之间的优先关系。
b.如果栈顶符号的优先级较低或相等,则进行规约操作,将栈顶的符号替换为相应的非终结符号。
c.如果栈顶符号的优先级较高,则进行移进操作,将当前输入符号移入栈中。
d.如果找不到优先关系,则出现错误,分析失败。
算符优先分析的优点是简单明了,且规约过程中不需要回溯,效率较高。
然而,由于它只适用于算符优先文法,而不是所有的上下文无关文法,因此适用范围有限。
在实际编程中,我们可以通过编写算符优先分析程序来对给定的文法进行分析。
程序可以根据文法自动生成优先关系表,然后根据输入串和优先关系表进行分析。
下面是一个简单的算符优先分析程序设计:```python#定义终结符和非终结符的优先级priority = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 0, ')': 0}#构造优先关系表def build_table(:table = {}for symbol1 in priority.keys(:row = {}for symbol2 in priority.keys(:if symbol1 == '(' and symbol2 == ')':row[symbol2] = 'r'elif symbol1 == ')' and symbol2 == '(':row[symbol2] = 'e'elif priority[symbol1] > priority[symbol2]:row[symbol2] = '>'elif priority[symbol1] < priority[symbol2]:row[symbol2] = '<'else:row[symbol2] = 'e'table[symbol1] = rowreturn table#算符优先分析程序def operator_precedence_parsing(table, input_str): input_stack = list(input_str)input_stack.append('#')analysis_stack = ['#']while len(analysis_stack) > 0:top = analysis_stack[-1]if top in priority.keys( and input_stack[0] in priority.keys(:relation = table[top][input_stack[0]]if relation == '>':analysis_stack.popprint('Reduce by', top)elif relation == '<':analysis_stack.append(input_stack.pop(0)) print('Shift', analysis_stack[-1])elif relation == 'e':analysis_stack.popinput_stack.pop(0)print('Error')returnelse:print('Error')returnelse:print('Error')return#测试代码table = build_tableinput_str = input('Please enter a valid expression: ')operator_precedence_parsing(table, input_str)```以上是一个简单的算符优先分析程序设计,实现了根据输入串和优先关系表进行分析的过程。
算符优先分析算法(c语言)
编译原理实验一实验目的设计、编制并调试一个算符优先分析算法,加深对此分析法的理解二实验过程先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
2.2 各种单词符号对应的种别码2.3 算符优先程序的功能完成一个交互式面向对象的算符优先分析程序,而一个交互式面向对象的算符优先分析程序基本功能是:(1)输入文法规则(2)对文法进行转换(3)生成每个非终结符的FirstVT和LastVT(4)生成算符优先分析表(5)再输入文法符号(6)生成移进规约步骤三设计源码算符优先分析器#include "stdio.h"#include "stdlib.h"#include "iostream.h"char data[20][20]; //算符优先关系char s[100]; //模拟符号栈schar lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1;int m,n,N; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集void table(); //创建文法优先关系表void main(){int i,j,k=0;printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]); //存储文法规则,初始化FIRSTVT集和LASTVT集*/first[i][0]=0; /*first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数*/ last[i][0]=0;}for(i=0;i<r;i++) //判断文法是否合法{for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");exit(-1);}}}}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='| ')lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';table();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++)printf("\t%c",lable[i]);printf("\n");for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}printf("请输入文法输入符号串以#结束:");scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf("转化后的文法为:\n");for(i=0;i<x;i++) //输出转化后的文法规则串{printf("%s\n",text[i]);}for(i=0;i<x;i++) /*求每个终结符的推导结果(去掉"->"后的转化文法,用于最后的规约)*/ {string[i][0]=text[i][0];for(j=3,l=1;text[i][j]!='\0';j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c) //求FIRSTVT集{int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++)int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c) //求LASTVT集{int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z; //输入串的长度k=1;s[k]='#'; //栈置初值for(i=0;input[i]!='\0';i++); //计算输入串的长度z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1;m<=k;m++){for(N=0;N<r1;N++)for(n=1;string[N][n]!='\0';n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])){if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}elseif(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("结束\n");printf("输入串符合文法的定义!\n");return 1; //输入串符合文法的定义}}elseif(data[x][y]=='<'||data[x][y]=='='){ //移进out(1,k,s);printf("%c",a);out(i+1,z,input);printf("移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c) //判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}四实验结果。
实验3 算符优先分析算法的设计与实现(优.选)
实验三算符优先分析算法的设计与实现(8学时)一、实验目的根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。
通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。
二、实验要求1、输入文法。
可以是如下算术表达式的文法(你可以根据需要适当改变):E→E+T|E-T|TT→T*F|T/F|FF→(E)|i2、对给定表达式进行分析,输出表达式正确与否的判断。
程序输入/输出示例:输入:1+2;输出:正确输入:(1+2)/3+4-(5+6/7);输出:正确输入:((1-2)/3+4输出:错误输入:1+2-3+(*4/5)输出:错误三、实验步骤1、参考数据结构char *VN=0,*VT=0;//非终结符和终结符数组char firstvt[N][N],lastvt[N][N],table[N][N];typedef struct //符号对(P,a){char Vn;char Vt;} VN_VT;typedef struct //栈{VN_VT *top;VN_VT *bollow;int size;}stack;2、根据文法求FIRSTVT集和LASTVT集给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。
算符描述如下:/*求 FirstVT 集的算法*/PROCEDURE insert(P,a);IF not F[P,a] thenbeginF[P,a] = true; //(P,a)进栈end;Procedure FirstVT;Beginfor 对每个非终结符 P和终结符 a doF[P,a] = falsefor 对每个形如 P a…或 P→Qa…的产生式 doInsert(P,a)while stack 非空begin栈顶项出栈,记为(Q,a)for 对每条形如 P→Q…的产生式 doinsert(P,a)end;end.同理,可构造计算LASTVT的算法。
算符优先分析方法
目录1.课程设计的目的与原理 (1)1.1设计目的 (1)1.2设计原理 (1)2.课程设计环境 (1)3.课程设计内容 (2)3.1算符优先分析流程图 (2)3.2算符优先总流程图 (3)3.3算符优先文法 (4)3.4 程序调试 (5)4.总结 (6)附录 (6)算符优先分析方法1.课程设计目的与原理1.1设计目的1.了解利用算符优先算法进行移进规约分析的方法。
2. 锻炼和提高自己的编程能力。
3. 熟悉编译原理语法分析的方法,加深对算符优先基本方法的了解。
4. 进一步理解编译原理,更好的的学习它的思路,掌握编译原理的理论基础。
5. 了解算符优先分析和规范规约的不同以及优缺点。
1.2设计原理算符优先分析方法是根据算符之间的优先关系而设计的一种自底向上的语法分析方法。
算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。
由于算符优先分析不考虑非终结符之间的优先关系,在归约过程中只要找到可归约串就归约,并不考虑归约到哪个非终结符,因而算符优先归约不是规范归约。
2.课程设计环境1.硬件运行环境:Windows XP2.软件运行环境:VC++ 6.0版本3.课程设计内容3.1算符优先分析流程图流程图说明:k:表示的是符号栈S的使用深度S:用来存放终结符和非终结符的符号栈Vt:存放该文法中的所有终结符3.2算符优先总流程图3.3算符优先文法例已知表达式文法为:E->E+TE->TT->T*FT->FF->(E)F->i⑴计算FIRSTVE和LASTVT集合FirstVT(E)={+,*,(,i} LastVT(E)={+,*,),i} FirstVT(T)={*,(,i} LastVT(T)={*,),i} FirstVT(F)={(,i} LastVT(F)={),i} FirstVT(Q)={#} LastVT(Q)={#}见附录3.4程序调试例:1、输入产生式的个数:2、输入文法:3、判断文法4、生成非终结符的FIRSTVT集和LASTVT集:5、生成算符优先分析表:5、输入字符串进行分析:输出结果与自己做的结果一模一样,说明设计成功。
算符优先分析法
G[E]: E→E+E|E-E|E*E|E/E|EE|(E)|-E|id
由于该文法是一个二义文法,它的句子往往有不同的规范推导和 归约,实际运算会得到不同结果,但按传统的习惯规定优先级和 结合律进行归约,优先级从高到低为:乘幂运算符,乘、除运算符, 加、减运算符;同级运算符服从左结合原则;有括号时,先括号 内后括号外。 则文法的句子id+id-id*(id+id)的归约过程为:
N1…Ni-1<· Ni …… Nj · >Nj+1…Nn
2.
句型中Ni„„Nj是句柄,语法分析程序可以通过寻找 Ni-1<· Ni和Nj· >Nj+1这两个关系来确定句柄的头尾,从 而确定句柄进行归约。
帮助理解 abce # 控制程序 # ce # b a #
G[S]: S→aBe B→bc bce # 控制程序 e #
知识点
算符优先分析法的算法简单、直观、易于理解,所以通常作为学 习其它自下而上语法分析的基础。 需复习有关语法分析的知识有:什么是语言、文法、句子、句型、 短语、简单短语、句柄、最右推导、规范归约基本概念。 本章重难点 算符文法的形式。 对一个给定的算符文法能构造算符优先关系分析表,并能判别所 给文法是否为 算符优先文法。 分清规范句型的句柄和最左素短语的区别,进而分清算符优先归 约和规范归约的区别。(在分析过程中如何寻找可归约串) 对一个给定的输入串能应用算符优先关系分析表给出分析(归约) 步骤,并最终判断所给输入串是否为该文法的句子。
输出带
2
2,3
2,3,4
2,3,4,1
S
a
A A b b
c
B e d
算符优先算法
算符优先算法1. 算符优先算法简介算符优先算法(Operator Precedence Parsing)是一种用于解析和计算表达式的方法。
它通过定义运算符之间的优先级和结合性来确定表达式的计算顺序,从而实现对表达式的准确解析和计算。
在算符优先算法中,每个运算符都被赋予一个优先级,表示其与其他运算符之间的优先关系。
根据这些优先级规则,可以将一个表达式转化为一个操作符和操作数构成的序列,并按照一定的顺序进行计算。
2. 算符优先文法在使用算符优先算法进行解析时,需要定义一个文法来描述运算符之间的关系。
这个文法称为算符优先文法。
一个典型的算符优先文法由以下三部分组成:1.终结符:表示可以出现在表达式中的基本元素,例如数字、变量名等。
2.非终结符:表示可以出现在表达式中但不能作为最终结果输出的元素,例如运算符。
3.产生式:描述了如何将非终结符转化为终结符或其他非终结符。
通过定义合适的产生式规则,可以建立起非终结符之间的优先关系。
这些优先关系决定了表达式中运算符的计算顺序。
3. 算符优先表算符优先表(Operator Precedence Table)是算符优先算法的核心数据结构之一。
它用于存储运算符之间的优先级和结合性信息。
一个典型的算符优先表由以下几部分组成:1.终结符集合:包含所有可能出现在表达式中的终结符。
2.非终结符集合:包含所有可能出现在表达式中的非终结符。
3.优先关系矩阵:用于存储运算符之间的优先关系。
矩阵中每个元素表示两个运算符之间的关系,例如“<”表示左运算符优先级低于右运算符,“>”表示左运算符优先级高于右运算符。
“=”表示两个运算符具有相同的优先级。
通过使用算符优先表,可以根据当前输入字符和栈顶字符来确定下一步应该进行的操作,例如移进、规约等。
4. 算法流程下面是一个简化版的算法流程:1.初始化输入串、操作数栈和操作符栈。
2.从输入串中读取一个字符作为当前输入字符。
3.如果当前输入字符为终结符,则进行移进操作,将其压入操作数栈,并读取下一个输入字符。
算符优先算法
while(i < len){if( ch[i] >= '0' && ch[i] <= '9' )//判断位数{int value = 0;while( ch[i] >= '0' && ch[i] <= '9' )//字符数字串转换为十进制数{value = value * 10;value = value + (ch[i]-48);i++;}Push( value );//将最终的数字压入栈cout << "Stack1: " << value << "进栈!" << endl;}else{if( F(Stack2[n-1]) <= G(ch[i]) )//当前字符优先级小于下一字符优先级则把下一字符压进栈{jmp: Push( ch[i] );cout << "Stack2: " << Stack2[n-1] << "进栈!" << endl;}else//当前字符优先级小于下一字符优先级{int j;for(j = n-1;j >= 1;j--)//循环处理栈Stack2字符{if(Stack2[j] == '+')//栈顶运算符为'+'则执行加法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t1 + t2;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '-')//栈顶运算符为'-'则执行减法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t2 - t1;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '*')//栈顶运算符为'*'则执行乘法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t1 * t2;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '/')//栈顶运算符为'/'则执行除法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t2 / t1;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '^')//栈顶运算符为'^'则执行幂运算{int t1,t2,t3 = 1;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );for( int t = 0;t < t1;t++)//根据运算符栈顶的运算符运算t3 = t3 * t2;Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else{cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );}}Push( ch[i] );//将字符串最后的字符压进栈cout << "Stack2: " << ch[i] << "进栈!" << endl;}i++;//读下一字符继续循环}}cout << "///////////////////" << endl;if(Stack2[0] == Stack2[1])//若栈尾的最后两个字符都为#则分析成功cout << "算符优先分析成功!" << endl;cout << "///////////////////" << endl;cout << "运算结果:" << Stack1[m-1] << endl;//根据算符优先将结果输出cout << "///////////////////" << endl;}elsecout << "算符优先分析失败!" << endl;}}int F( char ch )//进栈优先函数{if( ch == ')' )return 9;else if( ch == '^' )return 7;else if( ch == '*' || ch == '/' )return 5;else if( ch == '+' || ch == '-' )return 3;else if( ch == '(' )return 1;elsereturn 0;}int G( char ch )//比较优先函数{if( ch == ')' )return 1;else if( ch == '^' )return 6;else if( ch == '*' || ch == '/' )return 4;else if( ch == '+' || ch == '-' )return 2;else if( ch == '(' )return 8;elsereturn 0;}void Push( int num ){if( m >= MAX )//m大于MAX时栈满cout << "栈满!" << endl;elseStack1[m++] = num;//压栈后栈序号加1void Push( char ch ){if( n >= MAX )//n大于MAX时栈满cout << "栈满!" << endl;elseStack2[n++] = ch;//压栈后栈序号加1}int Pop( int num ){if( m <= 0 )//m小于零时栈空cout << "栈空!" << endl;elsenum = Stack1[--m];//出栈后栈序号减1return num;}void Pop( char ch ){if( n <= 0 )//n小于零时栈空cout << "栈空!" << endl;elsech = Stack2[--n];//出栈后栈序号减1}////////////////////////////////////算符优先分析////////////////////////////// #include <iostream>#include <string>using namespace std;#define MAX 30//栈容量#define INPUTMAX 60//键盘接收字符允许的最大个数int F( char );//进栈优先函数int G( char );//比较优先函数//函数重载Push、Popvoid Push( int );//Stack1进栈函数void Push( char );//Stack2进栈函数int Pop( int );//Stack1出栈函数void Pop( char );//Stack2出栈函数int Stack1[MAX];//操作数栈int m;//栈Stack1指针char Stack2[MAX];//运算符栈int n;//栈Stack2指针void main(){int i = 1;//键盘接收字符定位m = 0;//栈指针初始化n = 0;//栈指针初始化char ch[INPUTMAX];//定义接收字符数组cout << "请输入符号串(括在两个#之间):" << endl;cin >> ch;int len = strlen( ch );//统计字符长度if( ch[0] != '#' || ch[len-1] != '#' )cout << "符号串必须在两个#之间!" << endl;else{cout << "///////////////////" << endl;cout << "Stack1为操作数栈!" << endl;cout << "Stack2为运算符栈!" << endl;cout << "///////////////////" << endl;cout << "栈操作如下:" << endl;cout << "///////////////////" << endl;Push( ch[0] );//将字符串首字符压进栈cout << "Stack2: " << Stack2[0] << "进栈!" << endl;while(i < len){if( ch[i] >= '0' && ch[i] <= '9' )//判断位数{int value = 0;while( ch[i] >= '0' && ch[i] <= '9' )//字符数字串转换为十进制数{value = value * 10;value = value + (ch[i]-48);i++;}Push( value );//将最终的数字压入栈cout << "Stack1: " << value << "进栈!" << endl;}else{if( F(Stack2[n-1]) <= G(ch[i]) )//当前字符优先级小于下一字符优先级则把下一字符压进栈{jmp: Push( ch[i] );cout << "Stack2: " << Stack2[n-1] << "进栈!" << endl;}else//当前字符优先级小于下一字符优先级{int j;for(j = n-1;j >= 1;j--)//循环处理栈Stack2字符{if(Stack2[j] == '+')//栈顶运算符为'+'则执行加法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t1 + t2;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '-')//栈顶运算符为'-'则执行减法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t2 - t1;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '*')//栈顶运算符为'*'则执行乘法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t1 * t2;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '/')//栈顶运算符为'/'则执行除法运算{int t1,t2,t3;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );t3 = t2 / t1;//根据运算符栈顶的运算符运算Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else if(Stack2[j] == '^')//栈顶运算符为'^'则执行幂运算{int t1,t2,t3 = 1;cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;//将操作数栈顶上的两个操作数做出栈处理t1 = Pop( Stack1[m-1] );cout << "Stack1: " << Stack1[m-1] << "出栈!" << endl;t2 = Pop( Stack1[m-1] );for( int t = 0;t < t1;t++)//根据运算符栈顶的运算符运算t3 = t3 * t2;Push( t3 );//将运算结果压进操作数栈cout << "Stack1: " << Stack1[m-1] << "进栈!" << endl;cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );//将运算符栈顶的运算符做出栈处理if( F(Stack2[j-1]) <= G(ch[i]) )//若栈内下一字符优先级小于字符串字符优先级则跳至jmp将其压栈同时跳出此循环否则出错goto jmp;}else{cout << "Stack2: " << Stack2[j] << "出栈!" << endl;Pop( Stack2[j] );}}Push( ch[i] );//将字符串最后的字符压进栈cout << "Stack2: " << ch[i] << "进栈!" << endl;}i++;//读下一字符继续循环}}cout << "///////////////////" << endl;if(Stack2[0] == Stack2[1])//若栈尾的最后两个字符都为#则分析成功{cout << "算符优先分析成功!" << endl;cout << "///////////////////" << endl;cout << "运算结果:" << Stack1[m-1] << endl;//根据算符优先将结果输出cout << "///////////////////" << endl;}elsecout << "算符优先分析失败!" << endl;}}int F( char ch )//进栈优先函数{if( ch == ')' )return 9;else if( ch == '^' )return 7;else if( ch == '*' || ch == '/' )return 5;else if( ch == '+' || ch == '-' )return 3;else if( ch == '(' )return 1;elsereturn 0;}int G( char ch )//比较优先函数{if( ch == ')' )return 1;else if( ch == '^' )return 6;else if( ch == '*' || ch == '/' )return 4;else if( ch == '+' || ch == '-' )return 2;else if( ch == '(' )return 8;elsereturn 0;}void Push( int num ){if( m >= MAX )//m大于MAX时栈满cout << "栈满!" << endl;elseStack1[m++] = num;//压栈后栈序号加1 }void Push( char ch ){if( n >= MAX )//n大于MAX时栈满cout << "栈满!" << endl;elseStack2[n++] = ch;//压栈后栈序号加1 }int Pop( int num ){if( m <= 0 )//m小于零时栈空cout << "栈空!" << endl;elsenum = Stack1[--m];//出栈后栈序号减1 return num;}void Pop( char ch ){if( n <= 0 )//n小于零时栈空cout << "栈空!" << endl;elsech = Stack2[--n];//出栈后栈序号减1 }。
算符优先分析程序的设计与实现
实验2:算符优先分析程序的设计与实现【实验目的和要求】设计、编制、调试一个典型的算符优先语法分析程序,实现对如下文法的算符优先语法分析,进一步掌握常用的语法分析方法。
算符优先分析法是Floyd在1963年首先提出来的,是一种古典而又实用的方法,用这种方法在分析程序语言中的各类表达式时尤为有效。
不少编译程序中都使用这种方法分析表达式。
算符优先分析法就是仿照算术表达式的运算过程而提出的一种自底向上的语法分析方法。
其基本思想是:首先规定算符,这里是文法的终极符之间的优先关系,然后根据这种优先关系,通过比较相邻算符的优先次序来确定句型中的“句柄”,然后进行归约。
算符优先分析法的关键:算符优先分析法的关键就是寻找当前句型中的最左素短语,并归约它。
【实验内容】从键盘输入表达式串,利用算符优先法求出其值,如输入表达式有错,则给出报错提示。
表达式以“#”结尾。
构造算符优先关系表的算法用程序来实现对文法的算符优先关系表的构造。
例如:输入字符串“2*(3+4)+5#”,字符串以#结尾,通过运算输出“2*(3+4)+5=19”【实验环境】Windows PC机,任何版本的C语言。
【提交内容】提交实验报告,报告内容可以在如下两种方式中任选一个:1、能够读懂程序代码,正常输入输出(截图),画出核心功能的数据流图,对数据流图进行文字描述。
2、按照所讲的思路,用C语言编写程序,程序输入输出正常(提供程序代码、输入输出截图)。
【程序代码说明(java程序)】1、构造算法优先关系表:PriorityTable.java,table数组2、切分运算符import java.util.Vector;public class StringUtil {public static String[] splitExp(String str) {Vector<String> v = new Vector<String>();int beginIndex = 0;for (int i = 0; i < str.trim().length(); i++) {if ((str.charAt(i) > 32 && str.charAt(i) < 48 && str.charAt(i) != 46)|| str.charAt(i) == 94) {if (beginIndex != i)v.add(str.substring(beginIndex, i));v.add(String.valueOf(str.charAt(i)));beginIndex = i + 1;}}if (beginIndex != str.length())v.add(str.substring(beginIndex, str.length()));String result[] = new String[v.size()];for (int i = 0; i < v.size(); i++) {result[i] = v.get(i);}return result;}}3、核心程序:OperatorPriority.java的scanner方法1)分割字符String[] exp = StringUtil.splitExp(input);2)程序处理过程2 * (3 + 4)依次进栈,数值进入opndStack,运算符进入optrStack# < ** < (( < +optrStackopndStack* ( + ,exp 数组中的字符均比optrStack 栈中的第一个运算符优先规则小 “)”的优先级比栈中的第一个运算符“+”优先规则小,则将opndStack 栈中的前两个数值按照optrStack 栈中的第一个运算符进行计算,计算完成后,将opndStack 栈中的前两个数值出栈,并将结果7进栈,同时将optrStack 栈中的第一个运算符“+”出栈得到如下结果。
二语法分析程序(算符优先分析法)
实验二语法分析程序(算符优先分析法)一、实验目的通过设计调试算符优先分析程序,加深对课堂教学的理解,深刻理解自底向上语法分析方法的归约过程,提高语法分析方法的实践能力。
二、实验要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)实验要求独立完成,不允许有抄袭现象。
(4)实验完成后,要求提交源程序和上交实验报告(包括源程序清单)。
(附:实验报告格式)三、实验内容(1)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(2)分析的句子为:(i+i)*i和i+i)*i(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, * , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }FirstVT(E’)={ #} LastVT(E’)={ #}3,根据FirstVT和LastVT集构造算符优先表(2)程序参考源码#include <iostream>#include <string>using namespace std;#define max 100char b[max]; //存放终结符char precedence[max][max];//存放优先关系struct opg{int step;string stack;char privior;char presentsignal;string leftstr;string explain;}temp;//存放一步int search(char ch){int i=0;while(ch!=b[i])i++;return i;}void anolyze(){//struct opg temp;temp.step=0;char s[max],c,a;string sentence;int m=0,q=0,flag=0,i=0; //flag标记着当前读到那个字符cout<<"输入要分析的句子:";cin>>sentence;int k=0;//s[k]='#';s[k]=sentence[flag++];s[k+1]='\0';int j=k;a=sentence[flag++]; //读入一个给a;temp.leftstr=sentence;while(temp.leftstr[i]!=a){ //while循环获得第一次的剩余字符串temp.leftstr[i]=' ';i++;}temp.leftstr[i]=' ';//把已经读过的字符赋空则就找到了剩余的串cout<<"步骤 "<<" 栈 "<<" 优先关系 "<<"当前符号"<<" 剩余字符串 "<<"移进或归约"<<endl;while(!(s[j]=='#'&&a=='#')){//栈顶和当前字符都是#if(!isupper(s[k]))j=k;//s[k]是终结符else j=k-1;m=search(s[j]);//获取要比较终结符所在行号q=search(a);//获取要比较终结符所在列号temp.step=temp.step+1;temp.stack=s;temp.privior=precedence[m][q];temp.presentsignal=a;cout<<temp.step<<'\t'<<temp.stack<<'\t'<<temp.privior<<'\t'<<temp.presentsignal <<temp.leftstr<<'\t';if(precedence[m][q]=='<'||precedence[m][q]=='=')//优先关系为<或={temp.explain="移进";cout<<temp.explain<<endl;k=k+1;s[k]=a;s[k+1]='\0';//赋上字符串的终结标准,相当于一个栈a=sentence[flag++];//读入一个给a;temp.leftstr[++i]=' ';//每读入一个句子中一个字符把此位置赋空,作为剩余串}else if(precedence[m][q]=='>')//优先关系为>{temp.explain="归约";cout<<temp.explain<<endl;//cout<<s[j]<<s[k]<<a;do{c=s[j];if (!isupper(s[j-1]))//s[j-1]是终结符(即不是大写字母)j=j-1;elsej=j-2;m=search(s[j]);q=search(c);}while(precedence[m][q]=='=');k=j+1;s[k]='N';s[k+1]='\0';}//出错else {cout<<"不是该文法可以识别的句子";break;}//出错}cout<<++temp.step<<'\t'<<"#N"<<'\t'<<"="<<'\t'<<"#"<<' '<<'\t'<<"接受";}void main(){int n,i,j; //终结符的个数cout<<"输入终结符的个数:";cin>>n;cout<<endl;cout<<n<<'\n';cout<<"输入终结符";for(i=0;i<n;i++)cin>>b[i];b[n]='#';for(i=0;i<n+1;i++)for(j=0;j<n+1;j++){cout<<b[i]<<"与"<<b[j]<<"的优先关系:";cin>>precedence[i][j];while(!(precedence[i][j]=='>'||precedence[i][j]=='<'||precedence[i][j]=='=' ||precedence[i][j]=='/')){ cout<<"没有此优先关系,请重新输入";cin>>precedence[i][j];}}cout<<"算术优先关系表\n"<<"===============================================\n";for(i=0;i<n+2;i++)for(j=0;j<n+2;j++){if(i==0){if(j==0)cout<<' ';else cout<<b[j-1]<<' ';}else {if(j==0)cout<<b[i-1];else cout<<precedence[i-1][j-1]<<' ';}if(j==n+1)cout<<endl;}cout<<"===============================================\n";anolyze();}。
算符优先分析法详解
四川大学计算机学院 金军
12
2
优先表构造算法
FOR 每一条产生式P→X1X2…Xn FOR i:=1 TO n-1 DO BEGIN IF Xi 和 Xi+1 均为终结符 THEN 置 Xi=Xi+1 IF I<=n-2且Xi和Xi+2都为终结符,而Xi+1 为非终结符, THEN置Xi=Xi+2 IF Xi为终结符而Xi+1为非终结符 THEN FOR FISTVT(Xi+1)中的每个a DO 置 Xi< a IF Xi为非终结符而Xi+1为终结符THEN FOR LASTVT(Xi)中的每个a DO 置 Xi >a END
四川大学计算机学院 金军
1
算符优先文法
现在按照算符优先分析法的设计思路,构 造一种文法,通过它可以自动产生终结符 的优先关系表。
算符优先文法
一个文法,如果它的任何产生式的右部都 不含两个相继(并列)的非终结符,即不 含如下形式的产生式右部:
…QR…
则我们称该文法为算符文法。 在后面的定义中,a、b代表任意终结符; P、Q、R代表任意非终结符;‘…’代表有 终结符和非终结符组成的任意序列,包括 空字。
LASTVT(U)的构造:
若有产生式U → …a或U → …aV,则 a∈LASTVT(U); 若a∈LASTVT(V),且有产生式U → …V,则 a∈LASTVT(U)。
四川大学计算机学院 金军 9 四川大学计算机学院 金军 10
FIRSTVT构造算法
建立一个二维布尔数组F[P, a],使得F[P, a]为真的条件适当且仅当a∈FIRSTVT(P); 再用一个栈STACK,把所有初值为真的数 组元素F[P, a]的符号对(P, a)全都放到栈 中,对栈施加如下操作:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验一实验目的设计、编制并调试一个算符优先分析算法,加深对此分析法的理解二实验过程先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
2.2 各种单词符号对应的种别码2.3 算符优先程序的功能完成一个交互式面向对象的算符优先分析程序,而一个交互式面向对象的算符优先分析程序基本功能是:(1)输入文法规则(2)对文法进行转换(3)生成每个非终结符的FirstVT和LastVT(4)生成算符优先分析表(5)再输入文法符号(6)生成移进规约步骤三设计源码算符优先分析器#include "stdio.h"#include "stdlib.h"#include "iostream.h"char data[20][20]; //算符优先关系char s[100]; //模拟符号栈schar lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1;int m,n,N; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集void table(); //创建文法优先关系表void main(){int i,j,k=0;printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]); //存储文法规则,初始化FIRSTVT集和LASTVT集*/first[i][0]=0; /*first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数*/ last[i][0]=0;}for(i=0;i<r;i++) //判断文法是否合法{for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");exit(-1);}}}}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='| ')lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';table();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++)printf("\t%c",lable[i]);printf("\n");for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}printf("请输入文法输入符号串以#结束:");scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf("转化后的文法为:\n");for(i=0;i<x;i++) //输出转化后的文法规则串{printf("%s\n",text[i]);}for(i=0;i<x;i++) /*求每个终结符的推导结果(去掉"->"后的转化文法,用于最后的规约)*/ {string[i][0]=text[i][0];for(j=3,l=1;text[i][j]!='\0';j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c) //求FIRSTVT集{int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++)int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c) //求LASTVT集{int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z; //输入串的长度k=1;s[k]='#'; //栈置初值for(i=0;input[i]!='\0';i++); //计算输入串的长度z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1;m<=k;m++){for(N=0;N<r1;N++)for(n=1;string[N][n]!='\0';n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])){if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}elseif(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("结束\n");printf("输入串符合文法的定义!\n");return 1; //输入串符合文法的定义}}elseif(data[x][y]=='<'||data[x][y]=='='){ //移进out(1,k,s);printf("%c",a);out(i+1,z,input);printf("移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c) //判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}四实验结果最新文件---------------- 仅供参考--------------------已改成-----------word文本--------------------- 方便更改。