编译原理--词法分析,语法分析,语义分析(C语言)
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
编译原理----词法分析程序----C语言版

编译原理----词法分析程序----C语⾔版#include<stdio.h>#include<string.h>#include<stdlib.h>char KeyWord[20][100]={"begin","end","if","while","var","procedure","else","for","do","int","read","write"};char yunsuanfu[]="+-*/<>%=";char fenjiefu[]=",;(){}:";int main(){char test[]="var a=10;\nvar b,c;\nprocedure p; \n\tbegin\n\t\tc=a+b\n\tend\n";int len_yunsuanfu=strlen(yunsuanfu);int len_fenjiefu=strlen(fenjiefu);puts(test);int length=strlen(test),i,j,k;for(i=0;i<length;i++){if(test[i]==' '||test[i]=='\n'||test[i]=='\t')continue;int tag=0;for(j=0;j<len_fenjiefu;j++){if(fenjiefu [j]==test[i]){printf("分界符\t%c\n",test[i]);tag=1;break;}}if(tag==1)continue;tag=0;for(j=0;j<len_yunsuanfu;j++){if(yunsuanfu[j]==test[i]){printf("运算符\t%c\n",test[i]);tag=1;break;}}if(tag==1)continue;if(test[i]>='0'&&test[i]<='9'){printf("数字\t");while(test[i]>='0'&&test[i]<='9'){printf("%c",test[i]);i++;}printf("\n");continue;}char temp[100];j=0;while(test[i]>='0'&&test[i]<='9'||test[i]>='a'&&test[i]<='z'||test[i]>='A'&&test[i]<='Z'||test[i]=='_') {temp[j++]=test[i];i++;}i--;temp[j++]='\0';tag=0;for(j=0;j<20;j++){if(strcmp(temp,KeyWord[j])==0){tag=1;printf("关键字\t%s\n",temp);break;}}if(tag==0)printf("标识符\t%s\n",temp);}}。
编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
编译原理课程设计C编译器词法分析与语法分析的实现

编译原理课程设计报告课落款称: C-编译器词法分析与语法分析的实现提交文档学生姓名:黄臻旸提交文档学生学号: 1043041227 同组成员名单:无指导教师姓名:金军指导教师评阅成绩:指导教师评阅意见:..提交报告时刻:2021年 6 月 5 日编译原理课程设计报告 (1)一、课程设计目标 (3)二、分析与设计 (3)2.一、说明所用的方式: (3)2.二、系统总图: (3)2.2.一、scanner部份: (3)2.2.二、parse部份: (5)2.2.3、代码设计说明 (7)3、程序代码实现 (10)3.一、获取输入部份(在main.c中): (10)3.二、词法分析部份(在scan.c中): (10)3.3、语法分析部份(在parse.c中): (15)3.4、输出与结点的成立(在util.c中) (29)3.五、TokenType、treeNode与结点类型的声明(在globals.h中) (35)4、测试结果 (36)五、总结 (40)5.一、收成 (43)5.二、不足 (43)一、课程设计目标本次实验,本C- 编译器要紧设计而且实现了C- 编译器的词法分析功能与语法分析功能。
二、分析与设计2.一、说明所用的方式:各部份的实现方式(scanner:手工实现、Lex;parser:递归下降、LL(1)、LR(0)、SLR(1)、2.二、系统总图:2.2.一、scanner部份:2.2.1.一、实验原理:扫描程序的任务是从源代码中读取字符并形成由编译器的以后部份(一般是分析程序)处置的逻辑单元。
由扫描程序生成的逻辑单元称作记号(token),将字符组合成记号与在一个英语句子中将字母将字母组成单词并确信单次的含义很相像。
在此程序中,我将记号分成了以下类型:typedef enum {ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,PLUS,MINUS,TIMES,OVER,L T,LET,BT,BET,EQ,NEQ,// = + - * / < <= > >= == !=LPAREN_1,RP AREN_1,SEMI,COM,LPAREN_2,RP AREN_2,LPAREN_3,RP AREN_3,LIN,RIN// { } ; , [ ] ( ) /*} TokenType;其中,关键字有:else、if、int、return、void、while;专用符号有:+、-、*、/、<、<=、>、>=、==、~=、=、;、,、(、)、[、]、{、}、/*、*/其他标记是ID、NUM,通过以下正那么表达式概念:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9小写大写字母是有区别的。
编译原理实验 词法分析&语法分析程序

编译原理实验词法分析程序实验一:词法分析程序1、实验目的从左至右逐个字符的对源程序进行扫描,产生一个个单词符号,把字符串形式的源程序改造成单词符号形式的中间程序。
2、实验内容表C语言子集的单词符号及内码值单词符号种别编码助记符内码值while 1 while --if 2 if --else 3 else --switch 4 switch --case 5 case --标识符 6 id id在符号表中的位置常数7 num num在常数表中的位置+ 8 + --- 9 - --* 10 * --<= 11 relop LE< 11 relop LT== 11 relop LQ= 12 = --; 13 ; --输入源程序如下if a==1 a=a+1;else a=a+2;输出对应的单词符号形式的中间程序3、实验过程实验上机程序如下:#include "stdio.h"#include "string.h"int i,j,k;char s ,a[20],token[20];int letter(){if((s>=97)&&(s<=122))return 1;else return 0;}int Digit(){if((s>=48)&&(s<=57))return 1;else return 0;}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(){if(strcmp(token, "while")==0)return 1;else if(strcmp(token, "if")==0)return 2;else if(strcmp(token,"else")==0)return 3;else if(strcmp(token,"switch")==0)return 4;else if(strcmp(token,"case")==0)return 5;else return 0;}void main(){printf("please input you source program,end('#'):\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*10);j=0;get();while(s!='#'){if(s==' '||s==10||s==13)get();else{switch(s){case'a':case'b':case'c':case'd':case'e':case'f':case'g':case'h':case'i':case'j':case'k':case'l':case'm':case'n':case'o':case'p':case'q':case'r':case's':case't':case'u':case'v':case'w':case'x':case'y':case'z':while(Digit()||letter()){token[j]=s;j=j+1;get();}retract();k=lookup();if(k==0)printf("(6,%s)\n",token); elseprintf("(%d,null)\n",k); break;case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':while(Digit()){token[j]=s;j=j+1;get();}retract();printf("(%d,%s)\n",7,token); break;case'+':printf("(+,null)\n"); break;case'-':printf("(-,null)\n"); break;case'*':printf("(*,null)\n"); break;case'<':get();if(s=='=')printf("(relop,LE)\n"); else{retract();printf("(relop,LT)\n");}break;case'=':get();if(s=='=')printf("(relop,EQ)\n"); else{retract();printf("(=,null)\n");}break;case';':printf("(;,null)\n"); break;default:printf("(%c,error)\n",s);break;}memset(token,0,sizeof(char)*10);j=0;get();}}}4、实验结果实验结果分析:if是关键字,对应种别编码为2,输出(2,null)a是标识符,对应种别编码为6,值为a,输出(6,a)==的助记符是relop,内码值为LE,输出(relop,LE)1是常数,对应种别编码为7,值为1,输出(7,1)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)1是常数,对应种别编码为7,值为1,输出(7,1);是语句结束符号,直接输出(;,null)else是关键字,对应种别编码为3,输出(3,null)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)2是常数,对应种别编码为7,值为2,输出(7,2);是语句结束符号,直接输出(;,null)#是输入结束标志编译原理实验语法分析程序实验二:语法分析程序1、实验目的:将单词组成各类语法单位,讨论给类语法的形成规则,判断源程序是否符合语法规则3、实验内容:给定文法:G[E]:E→E+E|E-E|E*E|E/E|(E)E→0|1|2|3|4|5|6|7|8|9首先把G[E]构造为算符优先文法,即:G’[E]:E→E+T|TT→T-F|FF→F*G|GG→G/H|HH→(E)|i得到优先关系表如下:+ - * / i ( ) # + ·><·<·<·<·<··>·> - ·>·><·<·<·<··>·> * ·>·>·><·<·<··>·> / ·>·>·>·><·<··>·>i ·>·>·>·>·>·>( <·<·<·<·<·<·=) ·>·>·>·>·>·> # <·<·<·<·<·<·=构造出优先函数+ - * / i ( ) #f 6 8 10 12 12 2 12 2g 5 7 9 11 13 13 2 2要求输入算术表达式:(1+2)*3+2*(1+2)-4/2输出其对应的语法分析结果4、实验过程:上机程序如下:#include "stdio.h"#include "string.h"char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>=48)&&(s<=57))return 1;else return 0;}int f(char s){switch(s){case'+':return 6;case'-':return 8;case'*':return 10;case'/':return 12;case'(':return 2;case')':return 12;case'#':return 2;default:printf("error");}}int g(char s){switch(s){case'+':return 5;case'-':return 7;case'*':return 9;case'/':return 11;case'(':return 13;case')':return 2;case'#':return 2;default:printf("error");}}void get(){s=a[i];i=i+1;}void main(){printf("请输入算数表达式,并以‘#’结束:\n");i=0;do{scanf("%c",&a[i]);i++;}while(a[i-1]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j]!='#')||(s!='#')){if(operand(s)){opnd[k]=s-48;k=k+1;get();}else if(f(optr[j])<g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j])==g(s)){if(optr[j]=='('&&s==')'){j=j-1;get();}else if(optr[j]=='('&&s=='#'){printf("error\n");break;}else if(optr[j]=='#'&&s==')'){printf("error\n");break;}}else if(f(optr[j])>g(s)){op=optr[j];j=j-1;x2=opnd[k-1];x1=opnd[k-2];k=k-2;switch(op){case'+':x3=x1+x2;break;case'-':x3=x1-x2;break;case'*':x3=x1*x2;break;case'/':x3=x1/x2;break;}opnd[k]=x3;k=k+1;printf("(%c,%d,%d,%d)\n",op,x1,x2,x3);}else{printf("error\n");break;}}if(j!=0||k!=1)printf("error\n");}5、实验结果:实验结果分析:(1+2)*3+2*(1+2)-4/2#因为‘)’优先级大于‘*’,先计算1+2=3,并输出(+,1,2,3)原式变为:3*3+2*(1+2)-4/2#因为‘*’优先级大于‘+’,先计算3*3=9,并输出(*,3,3,9)原式变为:9+2*(1+2)-4/2#因为‘)’优先级大于‘-’,先计算1+2=3,并输出(+,1,2,3)原式变为:9+2*3-4/2#因为‘*’优先级大于‘-’,先计算2*3=6,并输出(*,2,3,6)原式变为:9+6-4/2#因为‘/’优先级大于‘#’,先计算4/2=2,并输出(/,4,2,2)原式变为:9+6-2#因为‘-’优先级大于‘#’,先计算6-2=4,并输出(-,6,2,4)原式变为:9+4#因为‘+’优先级大于‘#’,计算9+4=13,并输出(+,9,4,13)原式变为13#优先级等于#,跳出while循环,运算结束!。
编译原理-课程简介

编译原理中的程序分析技术可以 用于逆向工程中的程序分析,帮
助理解程序的结构和功能。
代码重构
在逆向工程中,编译原理可以帮助 对代码进行重构,提高代码的可读 性和可维护性。
病毒分析和防治
编译原理可以帮助分析和防治计算 机病毒,保护计算机系统的安全。
计算机体系结构相关应用
指令集设计
编译原理可以指导计算机指令集 的设计,提高处理器的性能。
• 向量化技术的实现方法:向量化技术的实现方法包括自动向量化和手动向量化 两种。自动向量化是指编译器自动将程序中的循环结构转换为向量运算;而手 动向量化则需要程序员手动编写向量运算的代码。在实现向量化技术时,需要 注意处理器的向量长度、数据对齐等问题。
04
CATALOGUE
运行时环境支持
存储管理策略及实现
定义不同类型的异常,如语法错误、 运行时错误等,以便程序能够识别并 处理异常情况。
控制异常在程序中的传播范围,避免异常对 程序其他部分的影响,同时提供异常恢复机 制,使程序能够从异常情况中恢复执行。
异常捕获与处理
在程序中设置异常捕获机制,当异常发 生时能够捕获异常并执行相应的处理代 码,保证程序的稳定性和可靠性。
自顶向下语法分析
从文法的开始符号出发,根据产生式 规则推导出输入符号串的过程。
自底向上语法分析
从输入符号串出发,逐步归约到文法 的开始符号的过程。
LL(1)语法分析方法
一种预测分析方法,根据当前输入符 号和上下文信息预测下一个要产生的 非终结符。
LR(1)语法分析方法
一种规范归约分析方法,根据当前输 入符号和栈顶信息确定句柄并进行归 约。
01
02
03
静态存储分配
C语言编译原理词法分析和语法分析

C语言编译原理词法分析和语法分析编程语言的编写和使用离不开编译器的支持,而编译器的核心功能之一就是对代码进行词法分析和语法分析。
C语言作为一种常用的高级编程语言,也有着自己的词法分析和语法分析规则。
一、词法分析词法分析是编译器的第一阶段,也是将源代码拆分为一个个独立单词(token)的过程。
在C语言中,常见的单词包括关键字(如if、while等)、标识符(如变量名)、常量(如数字、字符常量)等。
词法分析器会根据预定义的规则对源代码进行扫描,并将扫描到的单词转化为对应的符号表示。
词法分析的过程可以通过有限自动机来实现,其中包括各种状态和状态转换规则。
词法分析器通常会使用正则表达式和有限自动机的方法来进行实现。
通过词法分析,源代码可以被分解为一个个符号,为后续的语法分析提供基础。
二、语法分析语法分析是编译器的第二阶段,也是将词法分析得到的单词序列转换为一棵具有语法结构的抽象语法树(AST)的过程。
在C语言中,语法分析器会根据C语言的文法规则,逐句解析源代码,并生成相应的语法树。
C语言的语法规则相对复杂,其中包括了各种语句、表达式、声明等。
语法分析的过程主要通过递归下降分析法、LR分析法等来实现。
语法分析器会根据文法规则建立语法树的分析过程,对每个语法结构进行逐步推导和分析,最终生成一棵完整的语法树。
三、编译器中的词法分析和语法分析在编译器中实现词法分析和语法分析是一项重要的技术任务。
编译器通常会将词法分析和语法分析整合在一起,形成一个完整的前端。
在C语言编译器中,词法分析和语法分析器会根据C语言的词法规则和文法规则,对源代码进行解析,并生成相应的中间表示形式,如语法树或者中间代码。
词法分析和语法分析的结果会成为后续编译器中各个阶段的输入,如语义分析、中间代码生成、目标代码生成等。
编译器的优化和错误处理也与词法分析和语法分析有密切关系。
因此,对词法分析和语法分析的理解和实现对于编译器开发者而言是非常重要的。
编译原理全复习(完整版)

1》编译程序的框架图与功能块:(1)画出编译程序的总体结构,并简述各部分的主要功能:七个部分(2)编译程序的结构分为几个阶段,各阶段的任务是什么?答编译程序总框架(1)词法分析器,又称扫描器,输入源程序,进行词法分析,输出单词符号。
(2)语法分析器,简称分析器,对单词符号串进行语法分析(根据语法规则进行推导或规约),识别出各类语法单位,最终判断输入串是否构成语法上正确的“程序”。
(3)语义分析与中间代码产生器,按照语义规则对语法分析器归约出(或推导出)的语法单位进行语义分析并把它们翻译成一定形式的中间代码。
(4)优化器,对中间代码进行优化处理。
(5)目标代码生成器,把中间代码翻译成目标程序。
(6)表格管理,登记源程序的各类信息,编译各阶段的进展状况。
(7)出错管理,把错误信息报告给用户。
编译程序的结构分为五个阶段:(1)词法分析.任务是:输入源程序,对构成源程序的字符串进行扫描和分解,识别出一个个的单词(亦称单词符号或简称符号),如基本字,标识符,常熟,算符和界符。
(2)。
语法分析,任务是:在词法分析的基础上,根据语言的语法规则,把单词符号串分解成各类语法单位(语法范畴)。
(3)语义分析与中间代码产生。
任务:对语法分析所识别出的各类语法范畴,分析其含义,并进行初步翻译(产生中间代码)。
(4)优化。
任务在于对前段产生的中间代码进行加工变换,以期在最后阶段能产生出更为高效(省时间和空间)的目标代码。
(5)目标代码生成。
任务是:把中间代码(或优化出理之后)变换成特定机械上的低级语言代码。
2》.重要概念:a. 编译程序:是指能够把源语言程序转换成逻辑上等价的目标语言程序的一个程序。
b. 单词符号:是语言的基本组成成分,是人们理解和编写程序的基本要素,是语言中具有独立意义的最基本结构,它一般包括:基本字、标识符、常数、运算符和界符等c. 中间代码:是一种含义明确,便于处理的记号系统,它通常独立于具体的硬件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
词法分析#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAXN 20000int syn,p,sum,kk,m,n,row;double dsum,pos;char index[800],len;//记录指数形式的浮点数char r[6][10]={"function","if","then","while","do","endfunc"}; char token[MAXN],s[MAXN];char ch;bool is_letter(char c){return c>='a' && c<='z' || c>='A' && c<='Z';}bool is_digtial(char c){return c>='0' && c<='9';}bool is_dot(char c){return c==',' || c==';';}void identifier()//标示符的判断{m=0;while(ch>='a' && ch<='z' || ch>='0' && ch<='9'){token[m++]=ch;ch=s[++p];}token[m]='\0';ch=s[--p];syn=10;for(n=0;n<6;n++)if(strcmp(token,r[n])==0){syn=n+1;break;}}void digit(bool positive)//数字的判断{len=sum=0;ch=s[p];while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=s[++p];}if(ch=='.'){dsum=sum;ch=s[++p];pos=0.1;while(ch>='0' && ch<='9'){dsum=dsum+(ch-'0')*pos;pos=pos*0.1;ch=s[++p];}if(ch=='e'){index[len++]=ch;ch=s[++p];if(ch=='-' || ch=='+'){index[len++]=ch;ch=s[++p];}if(!(ch>='0' && ch<='9')){syn=-1;}else{while(ch>='0' && ch<='9'){index[len++]=ch;ch=s[++p];}}}if(syn==-1 || (ch>='a' && ch<='z') || ch=='.'){syn=-1;//对数字开头的标识符进行判错。
while(ch>='0' && ch<='9' || ch>='a' && ch<='z' || ch=='.') ch=s[++p];//找到下一次要判断的开头ch=s[--p];}else{ch=s[--p];syn=12;if(!positive) dsum*=-1.0;}}else{if(ch>='a' && ch<='z'){syn=-1;//对数字开头的标识符进行判错。
while(ch>='0' && ch<='9' || ch>='a' && ch<='z') ch=s[++p];//找到下一次要判断的开头ch=s[--p];}else{ch=s[--p];syn=11;if(!positive) sum*=-1;}}}bool check_behind_digit(){int i=p+1;while(s[i]!='\0')if(s[i]>='0' && s[i]<='9') return true;else if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n') return false;i++;}return false;}bool check_pre_prog(){int i=p-1;while(i>=0){if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n'){if(s[i]>='0' && s[i]<='9' || s[i]>='a' && s[i]<='z') return false;else return true;}i--;}return true;}void pot(){while(1){ch=s[++p];if(ch=='\n')row++;if(!(ch==' ' || ch=='\t' || ch=='\n'))break;}}void scaner(){memset(token,0,sizeof(token));pot();//cout<<p<<' '<<ch<<endl;if(is_letter(ch)){syn=10;identifier();else if(is_digtial(ch)){syn=11;digit(true);}else{if(ch=='<'){len=0,token[len++]=ch;if(s[p+1]=='='){syn=22;token[len++]=s[p+1];p++;}else syn=20;}else if(ch=='>'){len=0,token[len++]=ch;if(s[p+1]=='='){syn=24;token[len++]=s[p+1];p++;}else syn=23;}else if(ch=='='){len=0,token[len++]=ch;if(s[p+1]=='='){syn=25;token[len++]=s[p+1];p++;}else syn=18;}else if(ch=='!'){len=0,token[len++]=ch;if(s[p+1]=='='){syn=22;token[len++]=s[p+1];p++;}else syn=-1;}else if(ch=='+'){if(check_behind_digit() && check_pre_prog()) {++p;pot();digit(true);syn=12;}else{syn=13;token[0]=ch;}}else if(ch=='-'){if(check_behind_digit() && check_pre_prog()) {++p;pot();digit(false);syn=12;}else{syn=13;token[0]=ch;}}else if(ch=='*') syn=15,strcpy(token,"*");else if(ch=='/') syn=16,strcpy(token,"/");else if(ch==';') syn=26,strcpy(token,";");else if(ch=='(') syn=27,strcpy(token,"(");else if(ch==')') syn=28,strcpy(token,")");else if(ch=='#') syn=0,strcpy(token,"#");}//cout<<token<<' '<<sum<<' '<<syn<<endl;}int main(){int i,j;p=0;row=1;cout<<"请选择输入方式,按0表示键盘输入,按1表示文件输入"<<endl;scanf("%d",&i);if(i) freopen("1.txt","r",stdin);else printf("\nPlease input the string:\n");do{scanf("%c",&ch);s[++p]=ch;}while(ch!='#');s[0]='#';cout<<s<<endl;p=0;printf("种别码单词符号\n");do{scaner();switch(syn){case 11:printf("(%-3d ,%d)\n",syn,sum);break;case 12:{printf("\n(%d,%lf",syn,dsum);if(len){for(i=0;i<len;i++) printf("%c",index[i]);len=0;}printf(")\n");break;//实数输出}case -1:printf("(第%d行,error!)\n",row);break;default:printf("(%-3d ,%s)\n",syn,token);}}while(syn!=0);//printf("词法分析成功!请按任意键结束\n");return 0;}/*functiona=9;x=2*4;b=a+x;endfunc#x=a+b*c;endfunc#functionx=a+b*c;#functiona=(a+b)/c;x=(x+y)*(a+b)+c+d*(a+c)+(a+f)+(d-g);endfunc#functiona=(a+b)/c;x=(x+y)*(a+b)+c+d*(a+c)+(a+f)+(d-g);b=(a*c+4)*9;endfunc#*/语法分析#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;#define MAXN 20000int syn,p,sum,kk,m,n,row,error;double dsum,pos;char index[800],len;//记录指数形式的浮点数char r[6][10]={"function","if","then","while","do","endfunc"}; char token[MAXN],s[MAXN];char ch;bool is_letter(char c){return c>='a' && c<='z' || c>='A' && c<='Z';}bool is_digtial(char c){return c>='0' && c<='9';}bool is_dot(char c){return c==',' || c==';';}void identifier()//标示符的判断{m=0;while(ch>='a' && ch<='z' || ch>='0' && ch<='9'){token[m++]=ch;ch=s[++p];}token[m]='\0';ch=s[--p];syn=10;for(n=0;n<6;n++)if(strcmp(token,r[n])==0){syn=n+1;break;}}void digit(bool positive)//数字的判断{len=sum=0;ch=s[p];while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=s[++p];}if(ch=='.'){dsum=sum;syn=12;ch=s[++p];pos=0.1;while(ch>='0' && ch<='9'){dsum=dsum+(ch-'0')*pos;pos=pos*0.1;ch=s[++p];}if(ch=='e'){index[len++]=ch;ch=s[++p];if(ch=='-' || ch=='+'){index[len++]=ch;ch=s[++p];}if(!(ch>='0' && ch<='9')){//cout<<"Looooooooooook"<<endl;syn=-1;}else{while(ch>='0' && ch<='9'){index[len++]=ch;ch=s[++p];}}}if(syn==-1 || (ch>='a' && ch<='z') || ch=='.'){syn=-1;//对数字开头的标识符进行判错。