算符优先报告及代码
算符的运算规则范文

算符的运算规则范文1.优先级规则:不同算符有不同的优先级,按照优先级的高低进行计算。
常见的算符优先级从高到低依次是指数、乘法和除法、加法和减法。
-指数运算(^)具有最高的优先级,它表示多次乘法。
例如,2^3表示2的3次方,即2×2×2=8-乘法(×)和除法(÷)具有相同的优先级,高于加法(+)和减法(-)。
当一个表达式中含有多个乘法和除法运算时,从左到右进行运算。
-加法和减法具有最低的优先级,它们在所有算符中优先级最低。
当一个表达式中含有多个加法和减法运算时,从左到右进行运算。
例如:2+3×5-1÷4^2,按照优先级规则进行计算:首先计算指数运算4^2=16,然后进行乘法和除法运算3×5=15和1÷16≈0.0625,最后进行加法和减法运算2+15-0.0625=17.93752.结合性规则:当一个表达式中有多个相同优先级的运算符时,结合性规则决定了运算的顺序。
结合性规则有左结合和右结合两种情况。
-左结合:指的是从左到右进行运算,先计算前面的运算,然后计算后面的运算。
加法和减法是左结合的运算符。
例如:2-3+4=3,先计算2-3,然后再加上4-右结合:指的是从右到左进行运算,先计算后面的运算,然后计算前面的运算。
指数运算是右结合的运算符。
例如:2^3^4等价于2^(3^4),先计算3^4,然后再进行指数运算。
注意:乘法、除法和指数运算都是左结合的运算符。
3.括号法则:使用括号可以改变运算的优先级和结合性。
括号内的表达式会首先进行运算。
在一个表达式中,可以有多层括号,按照从内到外的顺序进行运算。
例如:(2+3)×4,首先进行括号内的运算,得到5,然后进行乘法运算,得到20。
4.符号规则:符号规则决定了算符和操作数的运算结果的正负。
以下是一些常见的符号规则:-加法和正号:正号(+)表示正数,加法运算默认为正,例如:+2=2,2+3=5-减法和负号:减号(-)表示减法和负号。
算符优先语法分析设计原理与实现技术实验报告

算符优先语法分析设计原理与实现技术实验报告变更说明一、实验目的:本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
二、实验内容:[实验项目]实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
G[E]:E→E+T∣E-T∣TT→T*F∣T/F∣FF→(E)∣i[实验说明]终结符号i 为用户定义的简单变量,即标识符的定义。
[设计要求](1)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。
输出为输入串是否为该文法定义的算术表达式的判断结果;(2)算符优先分析过程应能发现输入串出错;(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
三、实验环境:操作系统:Windows 7软件:VC++6.0四、程序功能描述:●提供了文件输入方式,且输入的内容为二元式序列;●能够对输入的字符串做出正确的算符优先分析判断,并给出判断结果,判断结果输出到文件,并显示在屏幕;●能发现输入串中的错误,包含非法字符,输入不匹配等;●能够处理一些可预见性的错误,如文件不存在,输入非法等。
五、数据结构设计:六、程序结构描述:●设计方法:本程序采用从文件读取的输入方式,输入的内容需为二元式序列,然后按照算符优先分析的方法对输入的字符串进行分析判断,分析完成后输出判断结果到文件,并在屏幕显示。
程序通过对输入串的检查能够发现输入串中的错误。
程序规定的单词符号及其种别码见下表:算符优先矩阵+ - * / ( ) i #+ > > < < < > < >- > > < < < > < >* > > > > < > < >/ > > > > < > < >( < < < < < = < >) > > > > > >i > > > > > ># < < < < < < < =●算符优先分析法简介基本思路是根据既定的规则构建算符优先矩阵,然后根据算符之间的优先关系寻找输入串中的最左素短语,若找到,则寻找与最左素短语匹配的产生式进行规约;否则进行移进操作,及输入的算符进分析栈。
算符优先表

文章作者:Slyar 文章来源:Slyar Home () 转载请注明,谢谢合作。
恩,问这个问题的人太多了,懒得继续回答,直接贴上来自己看。
优先级运算符名称或含义使用形式结合方向说明1 [] 数组下标数组名[常量表达式] 左到右() 圆括号(表达式)/函数名(形参表). 成员选择(对象)对象.成员名-> 成员选择(指针)对象指针->成员名2 - 负号运算符-表达式右到左单目运算符(类型) 强制类型转换(数据类型)表达式++ 自增运算符++变量名/变量名++ 单目运算符-- 自减运算符--变量名/变量名-- 单目运算符* 取值运算符*指针变量单目运算符& 取地址运算符&变量名单目运算符! 逻辑非运算符!表达式单目运算符~ 按位取反运算符~表达式单目运算符sizeof 长度运算符sizeof(表达式)3 / 除表达式/表达式左到右双目运算符* 乘表达式*表达式双目运算符% 余数(取模)整型表达式/整型表达双目运算符式4 + 加表达式+表达式左到右双目运算符- 减表达式-表达式双目运算符5 << 左移变量<<表达式左到右双目运算符>> 右移变量>>表达式双目运算符6 > 大于表达式>表达式左到右双目运算符>= 大于等于表达式>=表达式双目运算符< 小于表达式<表达式双目运算符<= 小于等于表达式<=表达式双目运算符7 == 等于表达式==表达式左到右双目运算符!= 不等于表达式!= 表达式双目运算符8 & 按位与表达式&表达式左到右双目运算符9 ^ 按位异或表达式^表达式左到右双目运算符10 | 按位或表达式|表达式左到右双目运算符11 && 逻辑与表达式&&表达式左到右双目运算符12 || 逻辑或表达式||表达式左到右双目运算符13 ?: 条件运算符表达式1? 表达式2: 表右到左三目运算符达式314 = 赋值运算符变量=表达式右到左/= 除后赋值变量/=表达式*= 乘后赋值变量*=表达式%= 取模后赋值变量%=表达式+= 加后赋值变量+=表达式-= 减后赋值变量-=表达式<<= 左移后赋值变量<<=表达式>>= 右移后赋值变量>>=表达式&= 按位与后赋值变量&=表达式^= 按位异或后赋值变量^=表达式|= 按位或后赋值变量|=表达式15 , 逗号运算符表达式,表达式,…左到右从左向右顺序运算。
表达式求值实验报告

表达式求值的类型定义与操作实现一、需求分析设计一个程序,演示用算符优先法对算术表达式求值的过程。
利用算符优先关系,实现对算术四则混合运算表达式的求值。
(1)输入的形式:表达式,例如2*(3+4)#;包含的运算符只能有'+' 、'-' 、'*' 、'/' 、'('、')';(2)输出的形式:运算结果,例如Answer is:77.000000;(3)程序所能达到的功能:对表达式求值并输出结果。
二、概要设计:本课程设计需要用到抽象数据类型栈存储表达式。
本部分给出栈的类型定义与表达式求值操作描述。
1、存储结构(顺序栈):typedef struct SqStack{SElemType *base;SElemType *top;int stacksize;}SqStack;2、基本操作:Status InitStack(SqStack &s)操作结果:初始化一个空栈s。
Status GetTop(SqStack s,SElemType &e)初始条件:栈s已存在。
操作结果:得到s的栈顶元素并用e带回。
Status Push(SqStack &s,SElemType e)初始条件:栈s已存在。
操作结果:向栈s中压入元素e。
Status Pop(SqStack &s,SElemType &e)初始条件:栈s已存在‘操作结果:弹出栈s栈顶元素,并用e带回。
Status In(char e)操作结果:判断e是否为7种运算符之一char Precede(char p,char c)操作结果:比较运算符p与运算符c的优先级。
SElemType Operate(SElemType x,char n,SElemType y)操作结果:计算x,y对运算符n的运算结果。
三、详细设计本部分主要给出表达式求值的实现算法1、初始化一个空栈sStatus InitStack(SqStack &s) //{s.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!s.base)exit(OVERFLOW);s.top=s.base;s.stacksize=STACK_INIT_SIZE;return OK;}2、读取栈顶元素Status GetTop(SqStack s,SElemType &e){if(s.top==s.base)return ERROR;e=*(s.top-1);return OK;}3、向栈s中压入元素eStatus Push(SqStack &s,SElemType e){if(s.top-s.base>=s.stacksize){s.base=(SElemType*)realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(SElemType));if(!s.base)exit(OVERFLOW);s.top=s.base+s.stacksize;s.stacksize+=STACKINCREMENT;}*s.top++=e;return OK;}4、弹出栈顶元素Status Pop(SqStack &s,SElemType &e) //{if(s.top==s.base)exit(OVERFLOW);e=* --s.top;return OK;}5、判断是否为7种运算符之一Status In(char e) / /{switch(e){case '+':case '-':case '*':case '/':case '(':case ')':case '#':return(1);break;default:return(0);}}6、比较两运算符优先级char Precede(char p,char c){ 'switch(p){case '+':case '-':switch(c){case '*':case '/':case '(':return '<';break;default:return '>';break;}break;case '*':case '/':switch(c){case '(':return '<';break;default:return '>';break;}break;case '(':switch(c){case ')':return '=';break;case '#':printf("ERROR!!\n");exit(OK);default:return '<';break;}break;case ')':switch(c){case '(':printf("ERROR!!\n");exit(OK);default:return '>';break;}break;case '#':switch(c){case ')':printf("ERROR!!\n");exit(OK);case '#':return '=';break;default:return '<';break;}break;}}7、四则运算SElemType Operate(SElemType x,char n,SElemType y) {SElemType e;switch(n){case '+':e=x+y;break;case '-':e=x-y;break;case '*':e=x*y;break;case '/':if(y==0){printf("分母不能为0!\n");exit(1);}else{e=x/y;break;}}return e;}8、主函数进行表达式求值void main(){SqStack OPTR,OPND;SElemType p,s,a,b,theta;char c;printf("请输入一个表达式并以'#'结束\n(只包括' +-*/' 和'('')'):\n");InitStack(OPTR);Push(OPTR,'#');InitStack(OPND);c=getchar();GetTop(OPTR,p);while(c!='#'||p!='#'){if(!In(c)){s=c-48;c=getchar();while(c>='0'&&c<='9'){s=s*10+(c-48);c=getchar();}Push(OPND,s);}else{switch(Precede(p,c)){case '<':Push(OPTR,c);c=getchar();break;case '=':Pop(OPTR,s);c=getchar();break;case '>':Pop(OPTR,theta);Pop(OPND,b);Pop(OPND,a);Push(OPND,Operate(a,theta,b));break;}GetTop(OPTR,p);}}//whileprintf("\n\n");GetTop(OPND,p);printf("Answer is:%f\n",p);getch();}四、调试分析1、初始化了一种类型的两个栈,分别用来存放数值和运算符。
运算符与流程控制实验报告

运算符与流程控制实验报告一、引言运算符与流程控制是程序设计中的重要基础知识,它们能够帮助程序员实现对数据的处理和操作。
本实验旨在通过实际操作和分析,深入理解运算符和流程控制的原理和应用。
二、实验目的1. 掌握常见的运算符及其优先级;2. 熟悉条件语句和循环语句的使用方法;3. 理解程序执行的流程控制。
三、实验过程1. 运算符实验在实验中,我们首先进行了常见运算符的实验,包括算术运算符、关系运算符、逻辑运算符和赋值运算符。
通过编写程序,我们可以观察到不同运算符之间的优先级和操作规则。
例如,在算术运算符中,“*”和“/”的优先级高于“+”和“-”,而在逻辑运算符中,“&&”的优先级高于“||”。
通过实验,我们对运算符的使用和规则有了更深入的了解。
2. 条件语句实验条件语句是根据不同的条件选择性地执行不同的代码块。
我们在实验中使用了if语句、if-else语句和switch语句。
通过编写程序,我们可以根据不同的条件执行不同的操作,实现灵活的程序流程控制。
例如,在一个简单的成绩判断程序中,我们可以根据不同的分数范围输出不同的评语。
3. 循环语句实验循环语句可以重复执行一段代码块,直到满足特定条件才停止。
我们在实验中使用了while循环、do-while循环和for循环。
通过编写程序,我们可以实现重复执行某段代码的需求。
例如,在一个简单的倒计时程序中,我们可以使用循环语句实现从10倒数到1的功能。
四、实验结果与分析通过实验,我们得到了以下结论:1. 运算符的优先级和操作规则是确定的,程序员可以根据需要合理运用;2. 条件语句可以根据不同的条件执行不同的操作,灵活性较高;3. 循环语句可以重复执行一段代码,节省了程序设计的工作量。
五、实验总结通过本次实验,我们深入学习了运算符与流程控制的原理和应用。
实验中我们掌握了常见的运算符及其优先级,熟悉了条件语句和循环语句的使用方法,并理解了程序执行的流程控制。
算符优先_实验报告

一、实验目的1. 理解算符优先分析法的原理和过程。
2. 掌握算符优先分析法的实现方法。
3. 通过实验加深对自底向上语法分析方法的理解。
二、实验内容1. 算符优先分析法原理介绍算符优先分析法是一种自底向上的语法分析方法,它通过比较相邻算符的优先次序来识别句型中的句柄,进而执行归约。
该方法的核心是确立文法的终结符之间的优先关系。
2. 实验步骤(1)判断文法是否为OG文法:OG文法要求所有产生式右部至少有一个终结符。
(2)判断文法是否为OPG文法:计算FIRSTVT集、LASTVT集,并构建算符优先矩阵。
(3)对句子进行分析:根据分析表判断句子是否为文法的句子。
(4)实现程序:从文件和键盘读取输入,将结果输出到指定文件和屏幕,并具有一致性。
3. 实验数据(1)文法:g[e]:e->e+t|t(2)测试句子:12+t, t+12, 12+13t, 12+t13三、实验过程1. 判断文法是否为OG文法根据给定的文法,我们可以看到所有产生式右部至少有一个终结符,因此该文法为OG文法。
2. 判断文法是否为OPG文法,并构建算符优先矩阵(1)计算FIRSTVT集FIRSTVT(e) = {t}FIRSTVT(t) = {t}(2)计算LASTVT集LASTVT(e) = {t}LASTVT(t) = {t}(3)构建算符优先矩阵| + - ( ) t e $+ > - - - > > -- > - - - > > -> > > > > > >( > > > > > > >) - - - - - - -t - - - - - - -e - - - - - - -$ - - - - - - -3. 对句子进行分析(1)分析句子“12+t”根据分析表,我们可以得到以下分析过程:12+t -> 12+t -> 12+t -> t -> t(2)分析句子“t+12”根据分析表,我们可以得到以下分析过程:t+12 -> t+12 -> t+12 -> t+12 -> t+12 -> t -> t (3)分析句子“12+13t”根据分析表,我们可以得到以下分析过程:12+13t -> 12+13t -> 12+13t -> 12+13t -> 12+13t -> t -> t(4)分析句子“12+t13”根据分析表,我们可以得到以下分析过程:12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> t13 -> t13 -> t13 -> t -> t四、实验结果1. 测试句子“12+t”分析结果:正确2. 测试句子“t+12”分析结果:正确3. 测试句子“12+13t”分析结果:正确4. 测试句子“12+t13”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。
编译原理算符优先分析程序设计

编译原理算符优先分析程序设计算符优先分析(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语言运算符和表达式-实验报告

中山大学南方学院电子通信与软件工程系课程名称:高级语言程序设计实践实验题目:运算符和表达式附:实验报告专业:年级:完成日期:学号:姓名:成绩:一、实验目的1、能够使用C语言进行简单的算术运算、关系运算和逻辑运算。
2、掌握不同的类型数据之间赋值的规律。
3、进一步熟悉C语言程序的编辑、编译和运行的过程。
二、实验原理1、用int定义整型变量来存放整数;2、用float定义浮点数变量来存放小数;3、使用scanf() 函数从键盘输入两个整型数据,并赋值给两个变量。
三、实验过程1、算术运算实验代码如下:#include <stdio.h>#include <stdlib.h>int main(){int a=2, b=3;float x=3. 9, y=2. 3;float result;result=(float) (a+b) /2+(int) x%(int) y;return result}输出结果如图:2、算术运算实验代码如下:#include <stdio.h>#include <stdlib.h>int main(){int number;int a1, a2, a3;printf("请输入一个三位数:");scanf("%d", &number) ;a1=number%10;number=number/10;a2=number%10;a3=number/10;printf("三位数%d的个位数字是%d,十位数字是%d,百位数字是%d\n",number,a1, a2, a3) ;return 0;}输出结果如图:3、关系运算与逻辑运算实验代码如下:#include <stdio.h>#include <stdlib.h>int main(){int x;printf("输入x的值:") ;scanf("%d", &x) ;printf("表达式(x>0)的值:%d\n", x>0) ;printf("表达式(x>=-20&&x<=-10)的值:%d\n", x>=-20&&x<=-10) ;printf("表达式(x>=100||x<10)的值:%d\n", x>=-20&&x<=-10) ;printf("表达式(x>20&&x%3==0的值:%d\n", x>20&&x%3==0) ;if(x%5==0&&x%3==0)printf("yes\n") ;elseprintf ("no\n") ;return 0;}输出结果如图:4、综合任务实验代码如下:#include <stdio.h>#include <stdlib.h>int main(){int grad1, grad2;scanf("%d%d", &grad1, &grad2) ;printf("表达式(grad1>=0&&grad1<=100)值:%d\n",grad1>=0&&grad1<=100);printf("表达式(grad2>=0&&grad2<=100)值:%d\n",grad2>=0&&grad2<=100);printf("%d", grad1>grad2? grad1:grad2) ;return 0;}输出结果如图:四、思考并回答以下问题1、举例说明逻辑运算符的短路特性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验任务:对下述描述算符表达式的算符优先文法G[E],给出算符优先分析的实验结果。
E->E+T|E-T|T T->T*F|T/F|F F->(E)|i说明:优先关系矩阵的构造过程:(1)= 关系由产生式F->(E) 知‘(’=‘)’FIRSTVT集FIRSTVT(E)={ +,-,*,/,(,i }FIRSTVT(F)={ (,i }FIRSTVT(T)={ *,/,(,i }LASTVT(E)={ +,-,*,/,),i }LASTVT(F)={ ),i }LASTVT(T)={ *,/,),i }(2) < 关系+T 则有:+ < FIRSTVT(T)-T 则有:- < FIRSTVT(T)*F 则有:* < FIRSTVT(F)/F 则有:/ < FIRSTVT(F)(E 则有:( < FIRSTVT(E)(3) > 关系E+ 则有:LASTVT(E) > +E- 则有:LASTVT(E) > -T* 则有:LASTVT(T) > *T/ 则有:LASTVT(T) > /E) 则有:LASTVT(E) > )(4)优先关系矩阵+ - * / ( ) i # + > > < < < > < >- > > < < < > < >* > > > > < > < >/ > > > > < > < >( < < < < < = <) > > > > > >i > > > > > ># < < < < < < =终结符之间的优先关系是唯一的,所以该文法是算符优先文法。
程序的功能描述:程序由文件读入字符串(以#结束),然后进行算符优先分析,分析过程中如有错误,则终止程序并报告错误位置,最终向屏幕输出移近——规约过程。
程序结构描述程序测试方案测试用例一:b-b*a+7#运行结果一:测试用例二:a+b*c-b*(a-b)#运行结果二:分析成功。
实验总结在算符优先程序设计过程中,程序比较复杂,其中在优先关系矩阵的构造时遇到了非常大的困难,由于最初对程序的总体流程不是十分清晰,而且实验中因本人马虎将优先关系矩阵输入错误,造成了设计与调试的困难。
但经过自己的努力,通过多次调试,最终构造出优先关系矩阵并调试成功。
通过本次实验一定程度上提高了软件开发能力,对编译原理这一门课程也有了比较深刻的了解。
最后,由于所学知识不够全面,实验在很多方面还有待完善,在以后的学习过程中,会掌握更多知识,力求做到更好。
附录#include<string.h>#include<stdlib.h>#include <ctype.h>#include<iostream>using namespace std;const int maxsize=100; //为数组str[]、in[]分配的最大存储空间const int length=100;//为数组array[]分配的最大存储空间class stack{private:int size;//size为当前数组array[]的大小char array[length];//用于存储读入的字符public:stack(){size=0;//数组array[]的初始长度为0}void push(char ch){if(size<length)//如果数组未满,则压入{array[size]=ch;size++;}else//若数组已满,则给出出错信息cout<<"overflow!"<<endl;}int pop(char ch[],int len)//弹出字符准备规约{if(size-len>=0){for(int i=0;i<len;i++)ch[i]=array[size-len+i];size-=len;return len;}else{cout<<"参数错误!"<<endl;return 0;}}char saomiao(int pos)//判断大小是否合法{if(pos>=0&&pos<size)return array[pos];return '\0';}void saomiaosuoyou()//输出当前数组中的字符{for(int i=0;i<getsize();i++)cout<<saomiao(i);cout<<endl;}int getsize()//返回当前数组大小{return size;}};char guiyue(char ch[])//规约为'M'{return 'M';}int isnumch(char ch)//判断ch是不是数字或小写字母{return (ch>='0'&&ch<='9'||ch>='a'&&ch<='z');}int getrank(char ch1,char ch2)//根据算符优先分析矩阵设置读入优先次序{ //0表示等于,1表示大于,-1表示小于,2表示没有优先关系if(isnumch(ch1))ch1='i';if(isnumch(ch2))ch2='i';if(ch1=='+'||ch1=='-'){if(ch2=='+'||ch2=='#'||ch2==')'||ch2=='-')return 1;elsereturn -1;}if(ch1=='*'||ch1=='/'){if(ch2=='('||ch2=='i')return -1;elsereturn 1;}if(ch1=='('){if(ch2==')')return 0;else if(ch2=='#')return 2;elsereturn -1;}if(ch1=='i'||ch1==')'){if(ch2=='i'||ch2=='(')return 2;elsereturn 1;}if(ch1=='#'){if(ch2=='#')return 0;elseif(ch2==')')return 2;elsereturn -1;}return 2;}int isvt(char ch)//区别参加规约的资格{if(ch>='a'&&ch<='z')return 1;if(ch>='('&&ch<='+')return 1;if(ch=='#')return 1;if(ch=='/')return 1;if(ch=='-')return 1;if(ch>='0'&&ch<='9')return 1;return 0;}/****************主函数**************/void main(){char juzhen[9][9]={' ','+','-','*','/','(',')','i','#','+','>','>','<','<','<','>','<','>','-','>','>','<','<','<','>','<','>','*','>','>','>','>','<','>','<','>','/','>','>','>','>','<','>','<','>','(','<','<','<','<','<','=','<',' ',')','>','>','>','>',' ','>',' ','>','i','>','>','>','>',' ','>',' ','>','#','<','<','<','<','<',' ','<','=', };cout<<"******此文法的算符优先矩阵如下所示*******"<<endl;for(int i=0;i<=8;i++) //输出算符优先矩阵{for(int j=0;j<=8;j++){cout<<juzhen[i][j]<<" ";}cout<<endl;}char in[maxsize]; //用于接收输入文件名char str[maxsize];FILE *fin; //用于指向输入文件的指针cout<<"请输入源程序文件名(例如ceshi.txt):";cin>>in;if ((fin=fopen(in,"r"))==NULL) //判断输入文件名是否正确{cout<<endl<<"打开词法分析输入文件出错!"<<endl;}int m=0;char ch1='a';while (ch1!='#')//从文件中读入一串字符{ch1=getc(fin);str[m++]=ch1;}str[m]='#';//将'#'赋给字符串尾stack s;//定义stack类的变量sint len;len=int(strlen(str));//取出输入字符串的长度s.push('#');//先把'#'压入数组array[]int k=s.getsize()-1,t=0,j;//k为当前数组array[]读入已读入字符的位置标识,//t为输入字符串数组str[]即将被读的字符位置标识,//j用于记录当前数组array[]中的最后一个非终结符的位置char a=str[0];//a用于传递即将读入的字符while(a!='#')//如果a不等于'#',则继续读入操作或规约操作{a=str[t];if(isvt(s.saomiao(k)))j=k;elsej=k-1;while(isvt(a)&&getrank(s.saomiao(j),a)==1)//判断是否满足规约的条件{int h=j,low=j-1;//h记录要规约的位置,low记录规约后数组array[]中的最后一个非终结符的位置if(!isvt(s.saomiao(low)))low--;while(getrank(s.saomiao(low),s.saomiao(h))!=-1)//寻找最后一个非终结符的位置用low记录{h=low;low--;if(!isvt(s.saomiao(low)))low--;}h=s.getsize()-1;low++;int len=h-low+1; //len记录要规约的长度char ch[10];for(int p=0;p<10;p++)ch[p]='\0';s.pop(ch,len);//弹出要规约的字符用字符串ch存储char c=guiyue(ch);//将ch规约为Ms.push(c);//再将规约后的M压入数组中cout<<ch<<" 规约为"<<guiyue(ch)<<endl;s.saomiaosuoyou();//规约后输出当前数组array[]中的字符j=s.getsize()-1;if(!isvt(s.saomiao(j)))j--;}if(!(a>='A'&&a<='Z')&&getrank(s.saomiao(j),a)==2)//当待输入字符不是大写字母且与前一个{ //非终结符无优先关系则提示出错并给出提示cout<<"你的输入有错误!"<<endl;cout<<"错误为第"<<t+1<<"个字符:"<<str[t]<<endl;exit(0);}else{cout<<"移近:"<<a<<endl;s.push(a);//将a压入数组array[]s.saomiaosuoyou();//读入后输出当前数组array[]中的字符t++;k=s.getsize()-1;}}char temp[10];s.pop(temp,3);if(s.getsize()==0)//如果最后数组array[]的长度size的值为0,则分析成功cout<<"成功!"<<endl;else//否则,分析失败cout<<"失败!"<<endl;fclose(fin);//关闭输入文件}。