C++词法分析器

合集下载

基于LEX的C语言词法分析器

基于LEX的C语言词法分析器

基于LEX的C语言词法分析器下面是一个基于LEX的C语言词法分析器的示例代码:```c#include <stdio.h>%}letter [a-zA-Z]digit [0-9]id {letter}({letter},{digit})*number {digit}+(\.{digit}+)?([eE][+-]?{digit}+)?%%{number} { printf("Number: %s\n", yytext); }{if} { printf("If: %s\n", yytext); }{else} { printf("Else: %s\n", yytext); }{while} { printf("While: %s\n", yytext); }{for} { printf("For: %s\n", yytext); }{id} { printf("Identifier: %s\n", yytext); }[ \t\n]+ // ignore white space. { printf("Unrecognized character: %c\n", yytext[0]); }%%int maiyylex(;return 0;```在上述代码中,首先是一些初始化的定义,定义了一些正则表达式模式,例如`letter`表示字母,`digit`表示数字,`id`表示标识符,`number`表示数字。

然后是各个模式的匹配规则和对应的处理逻辑。

其中,`{number}`表示如果匹配到了数字模式,就打印出该数字;`{if}`、`{else}`、`{while}`、`{for}`和`{id}`分别表示匹配到了if、else、while、for关键字和标识符,就打印出对应的信息;`[ \t\n]+`表示忽略空格和换行符;`.`表示匹配到了其他未定义的字符,就打印出异常信息。

【精编完整版】C语言词法分析器和C-语言语法分析器编译原理毕业论文

【精编完整版】C语言词法分析器和C-语言语法分析器编译原理毕业论文

(此文档为word格式,下载后您可任意编辑修改!) 《编译原理课程设计》课程报告题目 C语言词法分析器和C-语言语法分析器学生姓名学生学号指导教师提交报告时间 2019 年 6 月 8 日C语言词法分析器1 实验目的及意义1.熟悉C语言词法2.掌握构造DFA的过程3.掌握利用DFA实现C语言的词法分析器4.理解编译器词法分析的工作原理2 词法特点及正则表达式2.1词法特点2.1.1 保留字AUTO, BREAK , CASE , CHAR , CONST , CONTINUE , DEFAULT , DO , DOUBLE , ELSE,ENUM , EXTERN , FLOAT , FOR , GOTO,IF , INT , LONG , REGISTER , RETURN,SHORT , SIGNED , SIZEOF , STATIC , STRUCT , SWITCH , TYPEDEF , UNION , UNSIGNED , VOID,VOLATILE , WHILE,2.1.2 符号+ - * ++ -- += -= *= < <= > >= == != = ; , ( ) [ ] { } * * :2.2 正则表达式whitespace = (newline|blank|tab|comment)+digit=0|..|9nat=digit+signedNat=(+|-)?natNUM=signedNat(“.”nat)?letter = a|..|z|A|..|ZID = letter(letter|digit|“_”)+CHAR = 'other+' STRING = “other+”3 Token定义3.1 token类型3.2 tokenType类型代码4 DFA设计4.1 注释的DFA设计注释的DFA如下所示,一共分为5个状态,在开始状态1时,如果输入的字符为, 则进入状态2,此时有可能进入注释状态,如果在状态2时,输入的字符为*,则进入注释状态,状态将转到3,如果在状态3时,输入的字符为*,则有可能结束注释状态,此时状态将转到状态4,如果在状态4时输入的字符为,则注释状态结束,状态转移到结束状态。

C语言词法分析器_内容说明注释完整_可运行代码

C语言词法分析器_内容说明注释完整_可运行代码

1.实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C 语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。

运行环境:硬件:windows xp软件:visual c++6.02.实验步骤1.查询资料,了解词法分析器的工作过程与原理。

2.分析题目,整理出基本设计思路。

3.实践编码,将设计思想转换用c语言编码实现,编译运行。

4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。

通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。

3.实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。

将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。

在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。

标识符、常数是在分析过程中不断形成的。

对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。

输出形式例如:void $关键字流程图、程序流程图:程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;return 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\n",Word); //输出关键字 }else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); 快快快快快快快快可 //回退printf("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行 else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

用C语言实现简单的词法分析器

用C语言实现简单的词法分析器

⽤C语⾔实现简单的词法分析器词法分析器⼜称扫描器。

词法分析是指将我们编写的⽂本代码流解析为⼀个⼀个的记号,分析得到的记号以供后续语法分析使⽤。

词法分析器的⼯作是低级别的分析:将字符或者字符序列转化成记号.。

要实现的词法分析器单词符号及种别码对照表:单词符号#begin if then while do End+-*/:: =种别码0123456131415161718单词符号<<><=>>==;()Letter(letter|digit)digit digit*种别码2021222324252627281011#include<stdio.h>#include<string.h>char input[200];//存放输⼊字符串char token[5];//存放构成单词符号的字符串char ch; //存放当前读⼊字符int p; //input[]下标int fg; //switch标记int num; //存放整形值//⼆维字符数组,存放关键字char index[6][6]={"begin","if","then","while","do","end"};main(){p=0;printf("please intput string(End with '#'):\n");do{ch=getchar();input[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(fg){case 11:printf("( %d,%d ) ",fg,num);break;case -1:printf("input error\n"); break;default:printf("( %d,%s ) ",fg,token);}}while(fg!=0);getch(); //⽤于让程序停留在显⽰页⾯}/*词法扫描程序:*/scaner(){int m=0;//token[]下标int n;//清空token[]for(n=0;n<5;n++)token[n]=NULL;//获取第⼀个不为0字符ch=input[p++];while(ch==' ')ch=input[p++];//关键字(标识符)处理流程if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')){while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0')){token[m++]=ch;ch=input[p++];}token[m++]='\0';ch=input[--p];fg=10;for(n=0;n<6;n++)if(strcmp(token,index[n])==0)//strcmp()⽐较两个字符串,相等返回0{fg=n+1;break;}}//数字处理流程else if((ch<='9'&&ch>='0')){num=0;while((ch<='9'&&ch>='0')){num=num*10+ch-'0';ch=input[p++];}ch=input[--p];fg=11;}//运算符界符处理流程elseswitch(ch){case '<':m=0;token[m++]=ch;ch=input[p++];if(ch=='>') //产⽣<>{fg=21;token[m++]=ch;}else if(ch=='=') //产⽣<={fg=22;token[m++]=ch;}else{fg=20;ch=input[--p];}break;case '>':token[m++]=ch;ch=input[p++];if(ch=='=') //产⽣>={fg=24;token[m++]=ch;}else //产⽣>{fg=23;ch=input[--p];}break;case ':':token[m++]=ch;ch=input[p++];if(ch=='=') //产⽣:={fg=18;token[m++]=ch;}else //产⽣:{fg=17;ch=input[--p];}break;case '+':fg=13;token[0]=ch;break; case '-':fg=14;token[0]=ch;break; case '*':fg=15;token[0]=ch;break; case '/':fg=16;token[0]=ch;break; case ':=':fg=18;token[0]=ch;break; case '<>':fg=21;token[0]=ch;break; case '<=':fg=22;token[0]=ch;break; case '>=':fg=24;token[0]=ch;break; case '=':fg=25;token[0]=ch;break; case ';':fg=26;token[0]=ch;break; case '(':fg=27;token[0]=ch;break; case ')':fg=28;token[0]=ch;break; case '#':fg=0;token[0]=ch;break; default:fg=-1;}}。

实验一、词法分析器(含源代码)

实验一、词法分析器(含源代码)

词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。

运行环境:硬件:windows xp软件:visual c++6.0二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。

2.分析题目,整理出基本设计思路。

3.实践编码,将设计思想转换用c语言编码实现,编译运行。

4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。

通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。

三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。

将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。

在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。

标识符、常数是在分析过程中不断形成的。

对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。

输出形式例如:void $关键字流程图、程序流程图:程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;return 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\n",Word); //输出关键字 }else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

基于LEX的C语言词法分析器

基于LEX的C语言词法分析器

实验二C-语言的词法分析器(基于Lex)1. 课程设计目标自动构造C-语言的的词法分析器,要求能够掌握编译原理的基本理论,,理解编译程序的基本结构,掌握编译各阶段的基本理论和技术,掌握编译程序设计的基本理论和步骤.,增强编写和调试高级语言源程序的能力,掌握词法分析的基本概念和实现方法,熟悉C-语言的各种Token。

2. 分析与设计基于Parser Genarator的词法分析器构造方法Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。

这三个部分由位于新一行第一列的双百分号分开,因此,Lex输入文件的格式如下{definitions}%%{rules}%%{auxiliary routines}而且第一部分用“%{”和“%}”括起来。

第一和第三个部分为C语言的代码和函数定义,第二个部分为一些规则。

定义正则表达式如下ID = letter letter*NUM = digit digit*Letter = a|…|z|A|…|ZDig it = 0|…|9Keyword = else|if|int|return|void|whileSpecial symbol = +|-|*|/|<|<=|>|>=|==|!=|=|;|,|(|)|[|]|{|}|/*|*/White space = “ ”Enter = \n在lex中的构造letter [A-Za-z]digit [0-9]id ({letter}|[_])({letter}|{digit}|[_])*error_id ({digit})+({letter})+num {digit}+whitespace [ \t]+enter [\n]+在Lex中的规则定义构造定义识别保留字规则"int"|"else"|"return"|"void"|"if"|"while"{Upper(yytext,yyleng);printf("%d 行",lineno);printf("%s reserved word\n",yytext);}//保留字定义识别数字规则{num}{printf("%d 行",lineno);printf("%s NUM\n",yytext);}//数字定义识别专用符号规则","|";"|"("|")"|"{"|"}"|"*"|"/"|"+"|"-"|">"|"<"|">="|"<="|"=="|"!="|"="|"/*"|"*/" {printf("%d 行",lineno);printf("%s special symbol\n",yytext);}//特殊符号定义识别标识符规则{id}{printf("%d 行",lineno);printf("%s ID\n",yytext);}//标识符定义识别错误的字符串规则当开头为数字的后面为字母的字符串时,是错误的标识符。

C语言实现词法分析器

C语言实现词法分析器

C语⾔实现词法分析器问题描述:⽤C或C++语⾔编写⼀个简单的词法分析程序,扫描C语⾔⼩⼦集的源程序,根据给定的词法规则,识别单词,填写相应的表。

如果产⽣词法错误,则显⽰错误信息、位置,并试图从错误中恢复。

简单的恢复⽅法是忽略该字符(或单词)重新开始扫描。

相关词法规则<标识符>::=<字母><标识符>::=<标识符><字母><标识符>::=<标识符><数字><常量>::=<⽆符号整数><⽆符号整数>::=<数字序列><数字序列>::=<数字序列><数字><数字序列>::=<数字><字母>::=a|b|c|……|x|y|z<数字>::=0|1|2|3|4|5|6|7|8|9<加法运算符>::=+|-<乘法运算符>::=*|/<关系运算符>::=<|>|!=|>=|<=|==<分界符>::=,|;|(|)|{|}<保留字>::=main|int|if|else|while|do编写词法分析程序的步骤:(1)确定所要翻译的语⾔(或其⼦集)。

C语⾔(2)设计属性字,及各类表格,如标识符表、常量表、符号及其机内表⽰对照表等。

与词法分析有关的表格:1. 字符表保留字:main,int,if,else,while,do字母(全⼩写):a|b|c|……|x|y|z数字:0,1,2,3,4,5,6,7,8,9运算符和界符:<,>,!=,>=,<=,==,,,;,(,),{,}2. 特定单词机内表⽰表3.画出总控流程图及各个⼦程序的流程图。

4. 程序输⼊:⼀个存放C语⾔程序的s.txt⽂件输出:存放以(单词,种别码)形式输出的result.txt⽂件需要6个数组:1. 存储关键字 key[6]2. 存储对应下标关键字的种别码 keyNum[6]3. 存储运算符和界符 symbol[17]4. 存储运算符对应下标的种别码 symbolNum[17]5. 存储从⽂件中取出的每个字符(不包括括号)letter[1000]主要函数:TakeWord();功能:将⽂件letter[]中每个字符进⾏提取,找出关键字,输出种别码Num作为全局变量保存提取到字符的哪个下标1. 先提取⼀个字符,如果是字母,进⼊case1,调⽤identifier(),不断的提取字母或数字进⾏连接,没连接⼀个字符⽤int isKeyWord()程序(返回关键字种别码)判断是否为关键字,是就退出函数返回string,不是就继续执⾏函数,直到连接的字符不再是字母或数字,即此时字符串为标识符2. 如果是数字,进⼊case 2,调⽤Number()函数,不断进⾏字符串连接,知道下⼀个连接字符不再是数字3. 如果是符号,进⼊case 3,调⽤symbolStr()函数,如果是=,>,<,!,则要继续进⾏下个字符判断,其余符号可以直接返回其他辅助函数:int isSymbol()判断运算符和界符,并返回种别码bool isNum()判断是否为数字bool isLetter()判断是否为字母int isKeyWord()判断是否为关键字,是返回种别码int typeword()返回单个字符的类型string identifier()标识符的连接string symbolStr()符号和界符的连接string Number()数字的连接void print()输出程序:#include <iostream>#include<stdio.h>#include<string.h>#include<stdlib.h>using namespace std;//关键字string key[6]={"main","int","if","else","while","do"};//关键字的种别码int keyNum[6]={1,2,3,4,5,6};//运算符和界符string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="};//char symbol[12]={'<','>','!=','>=','<=','==',',',';','(',')','{','}'};//运算符和界符的种别码int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};//存放⽂件取出的字符string letter[1000];//将字符转换为单词string words[1000];int length; //保存程序中字符的数⽬int num;int isSymbol(string s){ //判断运算符和界符int i;for(i=0;i<17;i++){if(s==symbol[i])return symbolNum[i];}return 0;}//判断是否为数字bool isNum(string s){if(s>="0" && s<="9")return true;return false;}//判断是否为字母bool isLetter(string s){if(s>="a" && s<="z")return true;return false;}//判断是否为关键字,是返回种别码int isKeyWord(string s){int i;for(i=0;i<6;i++){if(s==key[i])return keyNum[i];}return 0;}//返回单个字符的类型int typeword(string str){if(str>="a" && str<="z") // 字母return 1;if(str>="0" && str<="9") //数字return 2;if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}" ||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符return 3;}string identifier(string s,int n){int j=n+1;int flag=1;while(flag){if(isNum(letter[j]) || isLetter(letter[j])){s=(s+letter[j]).c_str();if(isKeyWord(s)){j++;return s;}j++;}else{flag=0;}}num=j;return s;}string symbolStr(string s,int n){int j=n+1;string str=letter[j];if(str==">"||str=="="||str=="<"||str=="!") { s=(s+letter[j]).c_str();j++;}num=j;return s;}string Number(string s,int n){int j=n+1;int flag=1;while(flag){if(isNum(letter[j])){s=(s+letter[j]).c_str();j++;}else{flag=0;}}num=j;return s;}void print(string s,int n){cout<<"("<<s<<","<<n<<")"<<endl;}void TakeWord(){ //取单词int k;for(num=0;num<length;){string str1,str;str=letter[num];k=typeword(str);switch(k){case 1:{str1=identifier(str,num);if(isKeyWord(str1))print(str1,isKeyWord(str1));elseprint(str1,0);break;}case 2:{str1=Number(str,num);print(str1,24);break;}case 3:{str1=symbolStr(str,num);print(str1,isSymbol(str1));}}}}int main(){char w;int i,j;freopen("s.txt","r",stdin);freopen("result.txt","w",stdout); //从控制台输出,⽽不是⽂本输出 length=0;while(cin>>w){if(w!=' '){letter[length]=w;length++;} //去掉程序中的空格}TakeWord();// for(j=0;j<length;j++){// cout<<letter[j]<<endl;// }fclose(stdin);//关闭⽂件fclose(stdout);//关闭⽂件return 0;}运⾏结果:s.txtResult.txt以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

编译原理_词法分析器C_C++

编译原理_词法分析器C_C++

出处:/blog/static/984507512011224863279/词法分析器C/C++编程(体悟+感想2011-03-24 20:25:00 阅读282 评论0 字号:大中小订阅词法分析(1)---词法分析的有关概念以及转换图词法分析是编译的第一个阶段,前面简介中也谈到过词法分析器的任务就是:字符流------>词法记号流这里词法分析和语法分析会交错进行,也就是说,词法分析器不会读取所有的词法记号再使用语法分析器来处理,通常情况下,每取一个词法记号,就送入语法分析器进行分析,图解:词法分析器是编译器中与源程序直接接触的部分,因此词法分析器可以做诸如1). 去掉注释,自动生成文档(c#中的///注释)2). 提供错误位置(可以通过记录行号来提供),当字符流变成词法记号流以后,就没有了行的概念3). 完成预处理,比如宏定义1. 词法记号,词法单元(lexeme),模式模式是一种规则每个词法单元都有一个特定记号比如int a=3,这里int,a,=,3都是词法单元,每个词法单元都属于某个词法记号,比如3就是"num"这个词法记号的一个词法单元,而模式规定了什么样的字符串的词法记号是什么样的(模式是一种规则)某一特定模式规定了某个词法记号下的一类词法单元,比如:模式:用字母开头的包含字母和数字的串上面模式的词法记号:id(所有符合上面模式的字符串的记号都是id)词法单元:a123 或者aabc 等词法记号举例(简称为记号):1) 每个的关键字都有属于自己的一个记号,比如关键字for,它可以使用记号for;关键字int,可以使用记号int2) 所有的关系运算符只有一个记号,比如>=,<=都用记号relation3) 所有的标识符只有一个记号,比如a123,aab使用记号id4) 所有的常数只有一个记号,比如123,22,32.3,23E10使用记号num5) 所有的字符串只有一个记号,比如"123","ab1"使用记号literal在实际的编译器设计中,词法记号,一般用一个整形数字表示词法记号的属性:我们喜欢用<词法记号, 属性>这个二元组来描述一个词法单元,比如,对于源代码:position := initial +rate * 60对于词法单元+,我们可以使用<add_op, '+'> 来表示。

《C-语言的词法分析器(基于Lex)》课程设计报告

《C-语言的词法分析器(基于Lex)》课程设计报告

《C-语⾔的词法分析器(基于Lex)》课程设计报告《编译原理与实践》课程报告课题名称: C-语⾔的词法分析器实现(基于Lex)课题负责⼈名(学号):李恒(0643111198)同组成员名单(⾓⾊):⽆指导教师:于中华评阅成绩:评阅意见:提交报告时间:2007 年12 ⽉31⽇1. ⽬的与意义词法分析是编译原理中⼀个重要的部分。

它可将源程序读作字符⽂件并将其分为若⼲个记号,每⼀个记号都是表⽰源程序中信息单元的字符序列。

词法分析器是翻译步骤的第⼀步,它对于编译器接下来要进⾏的⼯作起着开头的作⽤,因此要想实现对C-语⾔的编译器,词法分析器必不可少。

2. 基于Parser Generator的词法分析器构造⽅法利⽤Parser Generator构造词法分析器规则,⽣成对应的c语⾔及其头⽂件。

然后进⾏编译。

3. C-语⾔词法分析的设计重要数据类型:关键字枚举:typedef enum{ENDFILE, ERROR,/* reserved words */ELSE, IF, INT, RETURN, VOID, WHILE,/* multicharacter tokens */ID, NUM,/* special symbols */PLUS, MINUS, TIMES, OVER, LT, LE, GT, GE, EQU, NEQU,ASSIGN, SEMI, COMMA, LPAREN, RPAREN, LBRKT, RBRKT, LBRC, RBRC, LCOM, RCOM}TokenType;关键字声明:digit [0-9]number {digit}+letter [a-zA-Z]identifier {letter}+newline \nwhitespace [ \t]+c-语⾔的词法规则:"else" {return ELSE;} "if" {return IF;}"int" {return INT;} "return" {return RETURN;} "void" {return VOID;} "while" {return WHILE;} "+" {return PLUS;} "-" {return MINUS;} "*" {return TIMES;} "/" {return OVER;} "<" {return LT;}"<=" {return LE;} ">" {return GT;}">=" {return GE;}"==" {return EQU;}"!=" {return NEQU;} "=" {return ASSIGN;} ";" {return SEMI;} "," {return COMMA;} "(" {return LPAREN;} ")" {return RPAREN;} "[" {return LBRKT;} "]" {return RBRKT;} "{" {return LBRC;} "}" {return RBRC;} {number} {return NUM;} {identifier} {return ID;} {newline} {lineNo++} {whitespace} {/* skip */} "/*" { char c;do{ c = input();if (c == EOF ) break;if (c == '\n' ) lineNo++;} while ( c != '/*');}{return ERROR;}重要处理程序设计:⽂件util.c执⾏输出结果的打印:void printToken(TokenType token, const char* tokenString) { switch (token){case ELSE:case IF:case INT:case RETURN:case VOID:case WHILE:fprintf(listing, "reserved word: %s\n", tokenString);break;case PLUS:fprintf(listing, "+\n");break;case MINUS:fprintf(listing, "-\n");break;case TIMES:fprintf(listing, "*\n");break;case OVER:fprintf(listing, "/\n");break;case LT:fprintf(listing, "<\n");break;case LE:fprintf(listing, "<=\n");break;fprintf(listing, ">\n"); break;case GE:fprintf(listing, ">=\n"); break;case EQU:fprintf(listing, "==\n"); break;case NEQU:fprintf(listing, "!=\n"); break;case ASSIGN: fprintf(listing, "=\n"); break;case SEMI:fprintf(listing, ";\n"); break;case COMMA: fprintf(listing, ",\n"); break;case LPAREN: fprintf(listing, "(\n"); break;case RPAREN: fprintf(listing, ")\n"); break;case LBRKT: fprintf(listing, "[\n"); break;case RBRKT: fprintf(listing, "]\n"); break;case LBRC:fprintf(listing, "{\n");case RBRC:fprintf(listing, "}\n");break;case LCOM:fprintf(listing, "/*\n");break;case RCOM:fprintf(listing, "*/\n");break;case ENDFILE:fprintf(listing,"EOF\n");break;case NUM:fprintf(listing, "NUM,val=%s\n",tokenString); break;case ID:fprintf(listing, "ID, name=%s\n",tokenString); break;case ERROR:fprintf(listing, "ERROR: %s\n",tokenString); break;default:break;}}函数getToken获取下⼀个token:TokenType getToken(void){ static int firstTime = TRUE; TokenType currentToken;if (firstTime){ firstTime = FALSE;lineNo++;yyin = source;yyout = listing;}currentToken = yylex();strncpy(tokenString,yytext,MAXTOKENLEN);if (TraceScan) {fprintf(listing, "\t%d: ", lineNo);printToken(currentToken,tokenString);}return currentToken;}4. 运⾏结果及分析输⼊⽂件如果所⽰:输出结果如图:对于输⼊的每⼀⾏进⾏词法分析,表⽰出保留字,标识符,以及终结符。

C语言解释器源码剖析

C语言解释器源码剖析

C语言解释器源码剖析概述C语言是一门广泛应用于系统开发、嵌入式设备以及高性能计算等领域的编程语言。

在C语言的开发和使用过程中,解释器起着重要的作用。

本文将深入剖析C语言解释器的源码,分析其原理和实现方式。

引言解释器是将高级语言程序逐行解析并执行的工具。

C语言解释器的源码包含了解析C语言程序,将其转换为可执行指令的过程。

通过深入分析C语言解释器的源码,我们能够了解其内部的工作原理和核心算法。

解析过程C语言解释器的源码主要包含了以下几个模块:词法分析器、语法分析器、语义分析器和解释器核心。

词法分析器负责将C语言程序的源代码分割成一个个的记号,如关键字、标识符、运算符等。

语法分析器将这些记号组合成语法树,用于表达程序的结构。

语义分析器进行语义检查,如类型检查、作用域检查等。

解释器核心则负责执行语法树上的指令,实现C语言程序的功能。

核心算法C语言解释器的源码中使用了一些核心算法,如递归下降法、LL(1)分析法、符号表等。

递归下降法是一种自顶向下的语法分析方法,通过递归地展开非终结符号来构建语法树。

在识别语法错误时,递归下降法能够提供有关错误种类和位置的准确信息。

LL(1)分析法是一种基于输入流的预测性语法分析方法,只需预读一个输入记号即可判断下一个正确的语法规则。

LL(1)分析法在编写语法分析器时具有简单和高效的特点。

符号表是解释器执行过程中存储变量和函数信息的数据结构。

通过符号表,解释器能够正确地访问和管理程序中的变量和函数。

源码剖析在源码中,词法分析器使用正则表达式来识别C语言程序中的关键字、标识符和运算符。

语法分析器使用递归下降法来生成语法树,并通过LL(1)分析法进行语法分析。

语义分析器使用符号表来进行语义检查,并生成中间代码。

解释器核心通过解释执行中间代码,实现C语言程序的功能。

总结C语言解释器源码的剖析深入分析了解释器内部的工作原理和核心算法。

通过对词法分析、语法分析、语义分析和解释器核心的剖析,我们能够更好地理解C语言解释器的实现方法。

简单的C语言编译器--词法分析器

简单的C语言编译器--词法分析器

简单的C语⾔编译器--词法分析器1. 定义词法单元Tag ⾸先要将可能出现的词进⾏分类,可以有不同的分类⽅式。

如多符⼀类:将所有逗号、分号、括号等都归为⼀类,或者⼀符⼀类,将⼀个符号归为⼀类。

我这⾥采⽤的是⼀符⼀类的⽅式。

C代码如下:#ifndef TAG_H#define TAG_Hnamespace Tag {//保留字const intINT = 1, BOOL = 2, MAIN = 3, IF = 4,ELSE = 5, FOR = 6, WHILE = 7, FALSE = 8,BREAK = 9, RETURN = 10, TRUE = 11 ;//运算符const intNOT = 20, NE = 21, AUTOMINUS =22, MINUS = 23,AUTOADD = 24, ADD = 25, OR = 26,AND = 27, MUTIPLY = 28, DIVIDE = 29, MOD = 30,EQ = 31, ASSIN = 32, GE = 33, GT = 34,LE = 35, LS = 36;//分界符const intCOMMA = 40, SEMICOLON = 41, LLBRACKET = 42,RLBRACKET = 43, LMBRACKET = 44, RMBRACKET = 45,LGBRACKET = 46, RGBRACKET = 47;//整数常数const int NUM = 50;//标识符const int ID = 60;//错误const int ERROR = 404;//空const int EMPTY = 70;}#endif2. 具体步骤⼀个⼀个字符地扫描测试代码,忽略空⽩字符,遇到回车时,记录⾏数加1要进⾏区分标识符(即普通变量名字)和保留字因为将标识符和常数都guiwe各⾃归为⼀类,所以要有算法能够识别出⼀整个常数和完整的标识符加⼊适当的⾮法词检测3. 设计词法分析类 设计⼀个词法分析器,当然要包括如何存储⼀个词法单元,如何扫描(scan)测试代码等,直接上代码:myLexer.h#ifndef MYLEXER_H#define MYLEXER_H#include <fstream>#include <string>#include <unordered_map>#include "tag.h"/** 主要是定义基本的词法单元类,* 声明了词法分析类*///存储词法单元class Word {public:Word() = default;Word(std::string s, int t) : lexeme(s), tag(t) {};std::string getLexeme() { return lexeme; };int getTag() { return tag; }void setTag(int t) { tag = t; }void setLexeme(std::string s) { lexeme = s; }private:std::string lexeme;int tag;};//词法分析器类class Lexer {public:Lexer();void reserve(Word w);bool readnext(char c, std::ifstream &in);Word scan(std::ifstream &in);int getLine() { return line; }private:char peek;std::unordered_map<std::string, Word> words;int line;};#endifmyLexer.cpp#include <iostream>#include <cctype>#include <sstream>#include "myLexer.h"void Lexer::reserve(Word w) {words.insert({w.getLexeme(), w});}Lexer::Lexer() {//存⼊保留字,为了区分标识符reserve( Word("int", Tag::INT) );reserve( Word("bool", Tag::BOOL) );reserve( Word("main", Tag::MAIN) );reserve( Word("if", Tag::IF) );reserve( Word("else", Tag::ELSE) );reserve( Word("for", Tag::FOR) );reserve( Word("while", Tag::WHILE) );reserve( Word("break", Tag::BREAK) );reserve( Word("return", Tag::RETURN) );reserve( Word("true", Tag::TRUE) );reserve( Word("false", Tag::FALSE) );peek = ' ';line = 1;}//⽅便处理像>=,++等这些两个字符连在⼀起的运算符 bool Lexer::readnext(char c, std::ifstream &in) {in >> peek;if( peek != c)return false;peek = ' ';return true;}Word Lexer::scan(std::ifstream &in) {//跳过空⽩符while(!in.eof()) {if(peek == ' ' || peek == '\t') {in >> peek;continue;}else if(peek == '\n')++line;elsebreak;in >> peek;}//处理分界符、运算符等switch(peek) {case '!':if(readnext('=', in))return Word("!=", Tag::NE);elsereturn Word("!", Tag::NOT);case '-':if(readnext('-', in))return Word("--", Tag::AUTOMINUS);elsereturn Word("-", Tag::MINUS);case '+':if(readnext('+', in))return Word("++", Tag::AUTOADD);elsereturn Word("+", Tag::ADD);case '|':if(readnext('|', in))return Word("||", Tag::OR);elsereturn Word("error", Tag::ERROR);case '&':if(readnext('&', in))return Word("&&", Tag::AND);elsereturn Word("error", Tag::ERROR);case '*':in >> peek;return Word("*", Tag::MUTIPLY);case '/':in >> peek;return Word("/", Tag::DIVIDE);case '%':in >> peek;return Word("%", Tag::MOD);case '=':if(readnext('=', in))return Word("==", Tag::EQ);elsereturn Word("=", Tag::ASSIN);case '>':if(readnext('=', in))return Word(">=", Tag::GE);elsereturn Word(">", Tag::GT);case '<':if(readnext('=', in))return Word("<=", Tag::LE);elsereturn Word("<", Tag::LS);case ',':in >> peek;return Word(",", Tag::COMMA);case ';':in >> peek;return Word(";", Tag::SEMICOLON);case '(':in >> peek;return Word("(", Tag::LLBRACKET);case ')':in >> peek;return Word(")", Tag::RLBRACKET);case '[':in >> peek;return Word("[", Tag::LMBRACKET);case ']':in >> peek;return Word("]", Tag::RMBRACKET);case '{':in >> peek;return Word("{", Tag::LGBRACKET);case '}':in >> peek;return Word("}", Tag::RGBRACKET);}//处理常数if(isdigit(peek)) {int v = 0;do {v = 10*v + peek - 48;in >> peek;} while(isdigit(peek));if(peek != '.')return Word(std::to_string(v), Tag::NUM);}//处理标识符if(isalpha(peek)) {std::ostringstream b;do {b << peek;in >> peek;} while(isalnum(peek) || peek == '_');std::string tmp = b.str();//判断是否为保留字if(words.find(tmp) != words.end())return words[tmp];elsereturn Word(tmp, Tag::ID);}if(peek != ' ' && peek != '\t' && peek != '\n')return Word("error", Tag::ERROR);return Word("empty", Tag::EMPTY);} 设计完成后,⾃⼰写⼀个Main函数,在while循环中调⽤scan函数,每次打印出Word内容,就能够得到。

词法分析器(C#实现)

词法分析器(C#实现)

/****************************************************************************** **************************************** 写在最前面* 词法分析前先将源码预处理,去掉多余的空格和换行以及注释* 单词与单词之间最好用空格隔开,否则将被识别为未知符号******************************************************************************** **************************************/using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Collections;using System.Text;using System.Windows.Forms;using System.IO;namespace 词法分析{public partial class Form1 : Form{private static string[] 保留字={"bool","break","case","char","do","double","else","false","float","for","if","int","long","main","new","null","private","protected","public","static","true","try","typeof","unit","void","while","return","short","sizeof","switch"};private static string[] 运算符={"*","/","%","+","-","<<",">>","<",">","<=",">=","==","!=","&","^","|","&&","||","?:","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>=","="};private static string[] 界符={ ",", ";", ".", "'", "(", ")", ":", "[", "]", "{", "}", "/" };private static string[] 标识符;private static string[] 常数;private static string[] 未知符号;private ArrayList temp = new ArrayList();public Form1(){InitializeComponent();}public int Search_Location(string str, string[] a) //查找字符编码{for (int i = 0; i < a.Length; i++){if (str == a[i])return i + 1;}return -1;}public int InsertId(string strr, ref string[] a)//标识符插入标识符表返回位置{temp.Clear();if (a == null)temp.Add(strr);else{for (int i = 0; i < a.Length; i++)if (strr == a[i])return i;for (int j = 0; j < a.Length; j++){temp.Add(a[j]);}temp.Add(strr);}a = (string[])temp.ToArray(typeof(string));return a.Length - 1;}private string Pretreatment() //预处理{string s1 = textBox1.Text;string str1 = null;//去除换行和//注释string[] str = textBox1.Lines;for (int i = 0; i < str.Length; i++){if (str[i].Contains("//")){string[] strr = str[i].Split('/');str[i] = strr[0];}}for (int i = 0; i < str.Length; i++){str1 += str[i] + " ";}//去除跳格,回车if (str1.Contains("/v")){str1 = str1.Replace("/v", " ");}if (str1.Contains("/r")){str1 = str1.Replace("/r", " ");}if (str1.Contains("/n"))str1 = str1.Replace("/n"," ");if (str1.Contains("/t")){str1 = str1.Replace("/t", " ");}//去除注释while (str1.Contains("/*") && str1.Contains("*/")){str1 = str1.Remove(str1.IndexOf("/*"), str1.IndexOf("*/") - str1.IndexOf("/*") + 2);}//去除多余空格while (str1.Contains(" ")){str1 = str1.Replace(" ", " ");}return str1;}private bool IsOperator(string str){for (int i = 0; i < 运算符.Length; i++)if (str == 运算符[i])return true;return false;}private bool IsCommunity_character(string str){for (int i = 0; i < 界符.Length; i++)if (str == 界符[i])return true;return false;void analyze(string string1, ref string string2){string[] str = string1.Split(new char[] { ' ' });for (int i = 0; i < str.Length - 1; i++)switch (liexingpanduan(str[i])){case 0:string2 += "( " + str[i] + "," + "保留字," + Search_Location(str[i], 保留字) + " )" + '\r' + '\n';break;case 1:string2 += "( " + str[i] + "," + "标识符," + InsertId(str[i], ref 标识符) + " )" + '\r' + '\n';break;case 2:string2 += "( " + str[i] + "," + "常数," + InsertId(str[i], ref 常数) + " )" + '\r' + '\n';break;case 3:string2 += "( " + str[i] + "," + "运算符," + Search_Location(str[i], 运算符) + " )" + '\r' + '\n';break;case 4:string2 += "( " + str[i] + "," + "界符," + Search_Location(str[i], 界符) + " )" + '\r' + '\n';break;case 5:string2 += "( " + str[i] + "," + "未知符号," + InsertId(str[i], ref 未知符号) + " )" + '\r' + '\n';break;}}private int liexingpanduan(string str){if(str == null)return -1;char a = str[0];if (char.IsLetter(a)) //首个字符为字母,则可能为保留字/标识符,也可能是未{int i = 0;for (int k = 0; k < 保留字.Length; k++)if (str == 保留字[k])return 0;//保留字for (i = 0; i < str.Length; i++)if (char.IsLetterOrDigit(str[i]) == false)return 5;//未知符号if (i >= str.Length)return 1;//标识符}else if (char.IsDigit(a))//首个字符为数字,则可能为数字也可能为未知字符{int j = 0;for (j = 0; j < str.Length; j++)if (char.IsDigit(str[j]) == false)return 5;//未知符号if (j >= str.Length)return 2; //常数}else//首个字符不是字母/数字,则可能是运算符/界符或未知字符{if (IsOperator(str))return 3;//运算符if (IsCommunity_character(str))return 4;//界符}return 5;}private void button1_Click(object sender, EventArgs e){string textbox1text = textBox1.Text;if (textbox1text == ""){MessageBox.Show("您没有输入任何字符!");return;}textbox1text = Pretreatment();string textbox2text = null;analyze(textbox1text, ref textbox2text);textBox2.Text = textbox2text;private void button2_Click(object sender, EventArgs e){DialogResult result = openFileDialog1.ShowDialog();if (result == DialogResult.OK){string dir = openFileDialog1.FileName;string text = null;StreamReader sr;try{sr = new StreamReader(dir, System.Text.Encoding.Default);}catch{MessageBox.Show("操作失败");return;}while (sr.Peek() != -1){text += sr.ReadLine() ;}sr.Close();textBox1.Text = text;textBox1.Text = Pretreatment();}else{MessageBox.Show("操作失败");}}private void button3_Click(object sender, EventArgs e){DialogResult result = saveFileDialog1.ShowDialog();if (result == DialogResult.OK){string dir = saveFileDialog1.FileName;StreamWriter sw;try{sw = File.CreateText(dir);}catch{MessageBox.Show("文件创建失败");return;}string[] text = textBox2.Lines;for (int i = 0; i < text.Length; i++){sw.WriteLine(text[i]);}sw.Close();}}private void Form1_Load(object sender, EventArgs e){textBox1.Text = "int i = 10 ; /*注释部分*/ ?";}}}。

C语言词法分析器

C语言词法分析器

C语言词法分析器
词法分析器通常使用有限状态自动机(finite state machine,FSM)来实现。

它根据一组正则表达式规则识别源代码中的模式,并将其转换为
相应的词素。

以下是一些常见的C语言词法单元(lexical elements):
1. 标识符(identifiers):由字母、数字和下划线组成,以字母或
下划线开头。

例如,变量名、函数名等。

2. 关键字(keywords):由C语言预定义的单词,具有特殊的含义。

例如,if、else、for等。

3. 运算符(operators):用于执行特定操作的符号。

例如,+、-、*、/等。

4. 界符(delimiters):用于标记代码块的符号。

例如,括号、分
号等。

5. 常量(literals):表示固定值的符号。

例如,整数常量、浮点
常量、字符常量和字符串常量。

词法分析器在编译过程中是非常重要的一步,它为后续的语法分析和
语义分析提供了基础。

通过词法分析,编译器能够将源代码转化为更易于
处理的数据结构,以便进行进一步的编译处理。

编译原理C语言词法分析器

编译原理C语言词法分析器

编译原理 C语言词法分析器一、实验题目编制并调试C词法分析程序。

a.txt源代码:•main() {int sum=0 ,it=1;/* Variable declaration*/if (sum==1)it++;elseit=it+2;}•设计其词法分析程序,能识别出所有的关键字、标识符、常数、运算符(包括复合运算符,如++)、界符;能过滤掉源程序中的注释、空格、制表符、换行符;并且能够对一些词法规则的错误进行必要的处理,如:标识符只能由字母、数字和下划线组成,且第一个字符必须为字母或下划线。

实验要求:要给出所分析语言的词法说明,相应的状态转换图,单词的种别编码方案,词法分析程序的主要算法思想等。

二、实验目的1、理解词法分析在编译程序中的作用;2、掌握词法分析程序的实现方法和技术;3、加深对有穷自动机模型的理解。

三、主要函数四、设计1.主函数void main ( )2. 初始化函数void load ( )3. 保留字及标识符判断函数void char_search(char *word)4. 整数类型判断函数void inta_search(char *word)5. 浮点类型判断函数void intb_search(char *word)6. 字符串常量判断函数void cc_search(char *word)7. 字符常量判断函数void c_search(char *word)同4、5函数图8.主扫描函数void scan ( )五、关键代码#include <stdio.h>#include <string.h>#include <stdlib.h>char *key0[]={" ","auto","break","case","char","const","continue","default","do","double","else","enum","extern","float","for","goto","if" ,"int","long","register","return","short","signed","sizeof","static","struct","switch","typedef","_Complex","_Imaginary"," union","unsigned","void","volatile","while"};/*保留字表*/char *key1[]={" ","(",")","[","]","{","}",",",";","'"};/*分隔符表*/char *key2[]={" ","+","-","*","/","%","<",">","==",">=","<=","!=","!","&&","||","<<",">>","~","|","^","&","=","?:","->","++","--",".","+ =","-=","*=","/="};/*运算符表*/int xx0[35],xx1[10],xx2[31];int temp_key3=0,temp_c40=0,temp_c41=0,temp_c42=0,temp_c43=0;/******* 初始化函数*******/void load(){int mm;for (mm=0;mm<=34;mm++){xx0[mm]=0;}for (mm=0;mm<=9;mm++){xx1[mm]=0;}for (mm=0;mm<=30;mm++){xx2[mm]=0;}FILE *floading;if ((floading=fopen("key0.txt","w"))==NULL){printf("Error! Can't create file : key0.txt");return;}fclose (floading);/*建立保留字表文件:key0.txt*/if ((floading=fopen("key1.txt","w"))==NULL){printf("Error! Can't create file : key1.txt");return;}/*建立分隔符表文件:key1.txt*/if ((floading=fopen("key2.txt","w"))==NULL){printf("Error! Can't create file : key2.txt");return;}fclose(floading);/*建立运算符表文件:key2.txt*/if ((floading=fopen("key3.txt","w"))==NULL){printf("Error! Can't create file : key3.txt");return;}fclose (floading);/*建立标识符表文件:key3.txt*/if ((floading=fopen("c40.txt","w"))==NULL){printf("Error! Can't create file : c40.txt");return;}fclose (floading);/*建立整数类型常量表文件:c40.txt*/if ((floading=fopen("c41.txt","w"))==NULL){printf("Error! Can't create file : c41.txt");return;}fclose (floading);/*建立浮点类型常量表文件:c41.txt*/if ((floading=fopen("c42.txt","w"))==NULL){printf("Error! Can't create file : c42.txt");return;}fclose (floading);/*建立字符类型常量表文件:c42.txt*/if ((floading=fopen("c43.txt","w"))==NULL){printf("Error! Can't create file : c43.txt");return;}fclose (floading);/*建立字符串类型常量表文件:c43.txt*/if ((floading=fopen("defination.txt","w"))==NULL) {printf("Error! Can't create file : defination.txt");return;}fclose (floading);/*建立注释文件:defination.txt*/if ((floading=fopen("output.txt","w"))==NULL) {printf("Error! Can't create file : output.txt");return;}fclose (floading);/*建立内部码文件:output.txt*/if ((floading=fopen("temp_key1","w"))==NULL) {printf("Error! Can't create file : temp_key1");return;}fclose (floading);/*建立保留字临时表文件:temp_key1*/if ((floading=fopen("temp_key3","w"))==NULL) {printf("Error! Can't create file : temp_key3");return;}fclose (floading);/*建立标识符临时文件:temp_key3*/if ((floading=fopen("temp_c40","w"))==NULL) {printf("Error! Can't create file : temp_c40");return;}fclose (floading);/*建立整数类型常量临时文件:temp_c40*/if ((floading=fopen("temp_c41","w"))==NULL) {printf("Error! Can't create file : temp_c41");return;}fclose (floading);/*建立浮点类型常量临时文件:temp_c41*/if ((floading=fopen("temp_c42","w"))==NULL) {printf("Error! Can't create file : temp_c42");return;}fclose (floading);/*建立字符类型常量临时文件:temp_c42*/if ((floading=fopen("temp_c43","w"))==NULL) {printf("Error! Can't create file : temp_c43");return;}fclose (floading);/*建立字符串类型常量临时文件:temp_c43*/ }/******* 保留字及标识符判断函数*******/void char_search(char *word){int m,line=0,csi=0;int value=0;int value2=0;char c,cs[100];FILE *foutput,*finput;for (m=1;m<=34;m++){if (strcmp(word,key0[m])==0){value=1;break;}}if (value==1){if (xx0[m]==0){foutput=fopen("key0.txt","a");fprintf(foutput,"0\t%d\t\t%s\n",m,word);fclose(foutput);xx0[m]=1;}foutput=fopen("output.txt","a");fprintf(foutput,"0\t%d\t\t%s\n",m,word);fclose(foutput);}else{if (temp_key3==0){foutput=fopen("temp_key3","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_key3++;foutput=fopen("key3.txt","a");fprintf(foutput,"3\t1\t\t%s\n",word);fclose(foutput);}finput=fopen("temp_key3","r");c=fgetc(finput);while (c!=EOF){while (c!='\n'){cs[csi++]=c;c=fgetc(finput);}cs[csi]='\0';csi=0;line++;if ((strcmp(cs,word))==0){value2=1;break;}else{value2=0;c=fgetc(finput);}}fclose(finput);if (value2==1){foutput=fopen("output.txt","a");fprintf(foutput,"3\t%d\t\t%s\n",line,word);fclose(foutput);}else{foutput=fopen("temp_key3","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_key3++;foutput=fopen("output.txt","a");fprintf(foutput,"3\t%d\t\t%s\n",temp_key3,word);fclose(foutput);foutput=fopen("key3.txt","a");fprintf(foutput,"3\t%d\t\t%s\n",temp_key3,word);fclose(foutput);}}}/******* 整数类型判断函数*******/void inta_search(char *word){FILE *foutput,*finput;char c;char cs[100];int csi=0;int line=0;int value2=0;if (temp_c40==0){foutput=fopen("temp_c40","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c40++;foutput=fopen("c40.txt","a");fprintf(foutput,"4\t0\t1\t%s\n",word);fclose(foutput);}finput=fopen("temp_c40","r");c=fgetc(finput);while (c!=EOF){while (c!='\n'){cs[csi++]=c;c=fgetc(finput);}cs[csi]='\0';csi=0;line++;if (strcmp(cs,word)==0){value2=1;break;}c=fgetc(finput);}fclose(finput);if (value2==1){foutput=fopen("output.txt","a");fprintf(foutput,"4\t0\t%d\t%s\n",line,word);fclose(foutput);}else{foutput=fopen("temp_c40","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c40++;foutput=fopen("output.txt","a");fprintf(foutput,"4\t0\t%d\t%s\n",temp_c40,word);fclose(foutput);foutput=fopen("c40.txt","a");fprintf(foutput,"4\t0\t%d\t%s\n",temp_c40,word);fclose(foutput);}}/******* 浮点类型判断函数*******/void intb_search(char *word){FILE *foutput,*finput;char c;char cs[100];int csi=0;int line=0;int value2=0;if (temp_c41==0){foutput=fopen("temp_c41","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c41++;foutput=fopen("c41.txt","a");fprintf(foutput,"4\t1\t1\t%s\n",word);fclose(foutput);}finput=fopen("temp_c41","r");c=fgetc(finput);while (c!=EOF){while (c!='\n'){cs[csi++]=c;c=fgetc(finput);}cs[csi]='\0';csi=0;line++;if (strcmp(cs,word)==0){value2=1;break;}c=fgetc(finput);}fclose(finput);if (value2==1){foutput=fopen("output.txt","a");fprintf(foutput,"4\t1\t%d\t%s\n",line,word);fclose(foutput);}else{foutput=fopen("temp_c41","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c41++;foutput=fopen("output.txt","a");fprintf(foutput,"4\t1\t%d\t%s\n",temp_c41,word);fclose(foutput);foutput=fopen("c40.txt","a");fprintf(foutput,"4\t1\t%d\t%s\n",temp_c41,word);fclose(foutput);}}/******* 字符串常量判断函数*******/void cc_search(char *word){FILE *foutput,*finput;char c;char cs[100];int csi=0;int line=0;int value2=0;if (temp_c43==0){foutput=fopen("temp_c43","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c43++;foutput=fopen("c43.txt","a");fprintf(foutput,"4\t3\t1\t%s\n",word);}finput=fopen("temp_c43","r");c=fgetc(finput);while (c!=EOF){while (c!='\n'){cs[csi++]=c;c=fgetc(finput);}cs[csi]='\0';csi=0;line++;if (strcmp(cs,word)==0){value2=1;break;}c=fgetc(finput);}fclose(finput);if (value2==1){foutput=fopen("output.txt","a");fprintf(foutput,"4\t3\t%d\t%s\n",line,word);fclose(foutput);}else{foutput=fopen("temp_c43","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c43++;foutput=fopen("output.txt","a");fprintf(foutput,"4\t3\t%d\t%s\n",temp_c43,word);fclose(foutput);foutput=fopen("c43.txt","a");fprintf(foutput,"4\t3\t%d\t%s\n",temp_c43,word);fclose(foutput);}}/******* 字符常量判断函数*******/void c_search(char *word){char c;char cs[100];int csi=0;int line=0;int value2=0;if (temp_c42==0){foutput=fopen("temp_c42","a");fprintf(foutput,"%s\n",word);fclose(foutput);temp_c42++;foutput=fopen("c42.txt","a");fprintf(foutput,"4\t2\t1\t%s\n",word);fclose(foutput);}finput=fopen("temp_c42","r");c=fgetc(finput);while (c!=EOF){while (c!='\n'){cs[csi++]=c;c=fgetc(finput);}cs[csi]='\0';csi=0;line++;if (strcmp(cs,word)==0){value2=1;break;}c=fgetc(finput);}fclose(finput);if (value2==1){foutput=fopen("output.txt","a");fprintf(foutput,"4\t2\t%d\t%s\n",line,word);fclose(foutput);}else{foutput=fopen("temp_c42","a");fprintf(foutput,"%s\n",word);fclose(foutput);foutput=fopen("output.txt","a");fprintf(foutput,"4\t2\t%d\t%s\n",temp_c42,word);fclose(foutput);foutput=fopen("c42.txt","a");fprintf(foutput,"4\t2\t%d\t%s\n",temp_c42,word);fclose(foutput);}}/******* 主扫描函数*******/void scan(){int count;char chin;FILE *fin;FILE *fout;char filename[50];char temp[100];char target[3]="'";printf("请输入文件名:");scanf("%s",filename);if ((fin=fopen(filename,"r"))==NULL){printf("Error! Can't open file : %s\n",filename);return;}chin=fgetc(fin);while (chin!=EOF){/*对文件包含、宏定义进行处理*/if (chin=='#'){while (chin!='>')chin=fgetc(fin);/*chin=fgetc(fin);*/}/*对空格符、水平制表符进行处理*/else if ((chin==' ')||(chin=='\t')){;}/*对回车符进行处理*/else if (chin=='\n'){;/*对单引号内的字符常量进行处理*/else if (chin==target[0]){if (xx1[9]==0){fout=fopen("key1.txt","a");fprintf(fout,"1\t9\t\t%c\n",target[0]);fclose(fout);xx1[9]=1;}temp[0]=chin;chin=fgetc(fin);temp[1]=chin;chin=fgetc(fin);if (chin!=target[0]){temp[2]=chin;chin=fgetc(fin);temp[3]=chin;temp[4]='\0';}else{temp[2]=chin;temp[3]='\0';}c_search(temp);}/*对双引号内的字符串常量进行处理*/else if (chin=='"'){int i=0;temp[i++]='"';chin=fgetc(fin);while (chin!='"'){temp[i++]=chin;chin=fgetc(fin);}temp[i]='"';temp[i+1]='\0';cc_search(temp);}/*对保留字、标识符进行处理*/else if (((chin>='A')&&(chin<='Z'))||((chin>='a')&&(chin<='z'))||(chin=='_')) {while(((chin>='A')&&(chin<='Z'))||((chin>='a')&&(chin<='z'))||(chin=='_')||((chin>='0')&&(chin<='9'))) {temp[i++]=chin;chin=fgetc(fin);}temp[i]='\0';char_search(temp);if (chin!=EOF)fseek (fin,-1L,SEEK_CUR);}/*对整型、浮点型数据进行处理*/else if ((chin>='0')&&(chin<='9')){int dotcount=0;int i=0;while (((chin>='0')&&(chin<='9'))||(chin=='.')){if (chin=='.')dotcount++;if (dotcount==2)break;temp[i++]=chin;chin=fgetc(fin);}temp[i]='\0';if (dotcount==1)intb_search(temp);elseinta_search(temp);if (chin!=EOF)fseek (fin,-1L,SEEK_CUR);}/*对注释进行处理*/else if (chin=='/'){chin=fgetc(fin);if (chin=='='){fout=fopen("output.txt","a");fprintf(fout,"2\t30\t\t/=\n");fclose(fout);}else if (chin!='*'){fout=fopen("output.txt","a");fclose(fout);fseek(fin,-1L,SEEK_CUR);}else if (chin=='*'){count=0;chin=fgetc(fin);fout=fopen("defination.txt","a");fprintf(fout,"/*");while (count!=2){count=0;while (chin!='*'){fprintf(fout,"%c",chin);chin=fgetc(fin);}count++;fprintf(fout,"%c",chin);chin=fgetc(fin);if (chin=='/'){count++;fprintf(fout,"%c\n",chin);}else{fprintf(fout,"%c",chin);chin=fgetc(fin);}}}}/*对运算符、分隔符进行处理*/else{int time=0;int firstblood=0;temp[0]=chin;chin=fgetc(fin);if (chin!=EOF){temp[1]=chin;temp[2]='\0';for (time=1;time<=30;time++){{firstblood=1;if (xx2[time]==0){fout=fopen("key2.txt","a");fprintf(fout,"2\t%d\t\t%s\n",time,temp);fclose(fout);xx2[time]=1;}fout=fopen("output.txt","a");fprintf(fout,"2\t%d\t\t%s\n",time,temp);fclose(fout);break;}}if (firstblood!=1){fseek(fin,-1L,SEEK_CUR);temp[1]='\0';for (time=1;time<=9;time++){if (strcmp(temp,key1[time])==0){if (xx1[time]==0){fout=fopen("key1.txt","a");fprintf(fout,"1\t%d\t\t%s\n",time,temp);fclose(fout);xx1[time]=1;}fout=fopen("output.txt","a");fprintf(fout,"1\t%d\t\t%s\n",time,temp);fclose(fout);break;}}for (time=1;time<=30;time++){if (strcmp(temp,key2[time])==0){if (xx2[time]==0){fout=fopen("key2.txt","a");fprintf(fout,"2\t%d\t\t%s\n",time,temp);fclose(fout);xx2[time]=1;fout=fopen("output.txt","a");fprintf(fout,"2\t%d\t\t%s\n",time,temp);fclose(fout);break;}}}}}chin=fgetc(fin);}fout=fopen("output.txt","a");fprintf(fout,"1\t6\t\t}\n");fclose(fout);}/******* Main函数*******/void main(){FILE *fread;char charin;char command='Q';printf("\n");printf("******************** C语言词法分析工具********************\n");printf("* *\n");printf("* *\n");printf("* 命令如下:*\n");printf("* 0 --> 查看保留字表文件*\n");printf("* 1 --> 查看分隔符表文件*\n");printf("* 2 --> 查看运算符表文件*\n");printf("* 3 --> 查看标识符表文件*\n");printf("* 4 --> 查看整数类型常量表*\n");printf("* 5 --> 查看浮点类型常量表*\n");printf("* 6 --> 查看字符类型常量表*\n");printf("* 7 --> 查看字符串类型常量表*\n");printf("* 8 --> 查看注释文件*\n");printf("* 9 --> 查看内部码文件*\n");printf("* -------------------------- *\n");printf("* Q --> 退出*\n");printf("***************************************************************\n");printf("\n");load();scan();printf("\n");printf("分析完成!\n");getchar();printf("请输入命令:");command=getchar();while ((command!='Q')&&(command!='q')){switch (command){case '0':{printf("*************************\n");printf("\n");fread=fopen("key0.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '1':{printf("*************************\n");printf("\n");fread=fopen("key1.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '2':{printf("*************************\n");printf("\n");fread=fopen("key2.txt","r");charin=fgetc(fread);{putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '3':{printf("*************************\n");printf("\n");fread=fopen("key3.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '4':{printf("*************************\n");printf("\n");fread=fopen("c40.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '5':{printf("*************************\n");printf("\n");fread=fopen("c41.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '6':{printf("*************************\n");printf("\n");fread=fopen("c42.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '7':{printf("*************************\n");printf("\n");fread=fopen("c43.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '8':{printf("*************************\n");printf("\n");fread=fopen("defination.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case '9':{printf("*************************\n");printf("\n");fread=fopen("output.txt","r");charin=fgetc(fread);while (charin!=EOF){putchar(charin);charin=fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}}command=getchar();}}。

c语言词法分析器

c语言词法分析器

c语言词法分析器实验内容:实现标准C语言词法分析器实验目的:1(掌握程序设计语言词法分析的设计方法;2(掌握DFA的设计与使用方法;3(掌握正规式到有限自动机的构造方法;实验要求:1(单词种别编码要求基本字(关键字)、运算符、界符:一符一种;标识符(变量名):统一为一种;常量():按类型编码;2(词法分析工作过程中建立符号表、常量表,并以文本文件形式输出; 3(词法分析的最后结果以文本文件形式输出;4(完成对所设计词法分析器的功能测试,并给出测试数据和实验结果; 5(为增加程序可读性,请在程序中进行适当注释说明;6(整理上机步骤,总结经验和体会;7(认真完成并按时提交实验报告。

# include<stdio.h># include <string.h># include <stdlib.h># include <time.h># include <ctype.h>FILE *fr,*fw,*temp1,*temp2;char*key0[]={"main","printf","scanf","else","if","auto","double","int"," struct","break","long","switch","case","enum","register","typedef","char","extern","return ","union","const","float","short","unsigned","continue","for","signed","void","default","g oto","sizeof","volatile","do","while","static"};/*关键字表*/char *key1[]={"\"","\\","%%","(",")","[","]","{","}",",",";","'"}; /*边界符表*/char *key2[]={"","+","-","*","/","%","<",">","==",">=","<=","!=","!","&&","||","<<",">>","~","| ","^","&","=","?:","->","++","--",".","+=","-=","*=","/="};/*运算符表*/int isLet(char c)//判断是否是字母{if(c>='a'&& c<='z'||c>='A'&&c<='Z')return 1;elsereturn 0;}int isNum(char c)//判断是否是数字 { if (c>='0'&&c<='9')return 1;elsereturn 0;}int isKey(char *word) {int m,i;for(i=0;i<36;i++) {if((m=strcmp(word,key0[i]))==0) {if(i==0)return 2;elsereturn 1;}}return 0;}int isBoudany(char *word) {int m,i;for(i=0;i<12;i++){if((m=strcmp(word,key1[i]))==0){if(i==1)return 2;elseif(i==2)return 3;return 1;}}return 0;}void check(FILE *fr){char word[30];while(fscanf(fr,"%*\n")!= EOF ){memset(word,0,sizeof(word));char ch,temp;ch=fgetc(fr); //获取字符,指针fr并自动指向下一个字符int i,c;if(ch=='#')//预处理{temp=fgetc(fr);while(ch!='>')ch=fgetc(fr);ch=fgetc(fr);fprintf(fw,"*****************************************跳过头文件和文件宏定义\n");}elseif (ch=='/')//跳过注释/**/类型{ch=fgetc(fr);if (ch=='/')//跳过注释//类型{while(ch!='\n')ch=fgetc(fr);fprintf(fw,"******************************************************** *跳过注释\n");}elseif (ch=='*'){ch=fgetc(fr);temp=fgetc(fr);do{ch=fgetc(fr);temp=fgetc(fr);}while (ch!='*'||temp!='/');fprintf(fw,"******************************************************跳过注释\n");ch=fgetc(fr);}}elseif(isLet(ch)){word[0]=ch;ch=fgetc(fr);i=1;while(isNum(ch)||isLet(ch))//判断该字符是否是字母或数字{word[i]=ch;i++;ch=fgetc(fr);}word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fr,-1,1);c=isKey(word); //判断是否是关键字if(c==0){fprintf(temp1,"%s ",word);fprintf(fw,"字符%s是:标识符,种别编码为:%d\n",word,2);}//不是关键字else{if(ch!='"')//判断是否是定义的字符{if(c==2)fprintf(fw,"字符%s是:***************************************************主函数,种别编码为:%d\n",word,0);//主函数elsefprintf(fw,"字符%s是:关键字,种别编码为:%d\n",word,1);//关键字}else{fprintf(fw,"字符%s是:定义的字符常量,种别编码为:%d\n\n",word,32);}}}else //开始判断的字符不是字母if(isNum(ch)){ //判断是否是数字word[0]=ch;ch=fgetc(fr);i=1;while(isNum(ch)){word[i]=ch;i++;ch=fgetc(fr);}word[i]='\0';fseek(fr,-1,1); //回退fprintf(fw,"字符%s是:常量,种别编码为:%d\n",word,3); }else//开始判断的字符不是字母也不是数字word[0]=ch;word[1]='\0';c=isBoudany(word); //边界符if(c){if(c==2)//判断是否是转义字符{ch=fgetc(fr);word[1]=ch;word[2]='\0';fprintf(fw,"字符%s是:转义字符,种别编码为:%d\n",word,4);}elseif(c==1){fprintf(fw,"字符%c是:界符,种别编码为:%d\n",ch,5); fprintf(temp2,"%s ",word);}}elseswitch(ch){case'+':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,6);//运算符"+=" }elseif(ch=='+'){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,7); //判断结果为"++"}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,8); //判断结果为"+" }break;case'-':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,9); }elseif(ch=='-'){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,10); //判断结果为"--"}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,11); //判断结果为"-"}break;case'*':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch!='='){if(isNum(ch)){fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c:是运算符,种别编码为:%d\n",ch,12);//判断结果为"*"}else{ //判断是否是指针i=2;ch=fgetc(fr);while(isLet(ch)){word[i]=ch;ch=fgetc(fr);i++;}fprintf(fw,"字符%s:是指针定义运算符,种别编码为:%d\n",word,13); }}else {word[2]='\0';fprintf(fw,"字符%s:是运算符,种别编码为:%d\n",word,14);//判断结果为"*="}break;case'/':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch!='='){if(isNum(ch)){fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c:是运算符,种别编码为:%d\n",ch,15);//判断结果为"/"}}else {word[2]='\0';fprintf(fw,"字符%s:是运算符,,种别编码为:%d\n",word,16);//判断结果为"/="}break;case'!':case'?':case':':case'.':case'=':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch!='='){fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c:是运算符,种别编码为:%d\n",ch,17); }else {word[2]='\0';fprintf(fw,"字符%s:是运算符,种别编码为:%d\n",word,18); }break;case'|':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='|'){word[2]='\0';fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,19); //判断结果为运算符"||"}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,20); //判断结果为"|"}break;case '%':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,21);}elseif(isLet(ch)){word[2]='\0';fprintf(fw,"字符%s是输出类型标识符,种别编码为:%d\n",word,22);}else{2,1); fseek(fr,-ch=fgetc(fr);fprintf(fw,"字符%c是取余运算符,种别编码为:%d\n",ch,23);}break;case'&':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='&'){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,24); //判断结果为运算符"&&"}else {fseek(fr,-2,1);ch=getc(fr);fprintf(fw,"字符%c是:运算符,种别编码为:%d\n",ch,25); //判断结果为"&" }break;case'<':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,26); //判断结果为运算符"<="}elseif(ch=='<'){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,27); //判断结果为运算符"<<"}else{fseek(fr,-2,1);fgetc(fr); ch=fprintf(fw,"字符%c是:运算符,种别编码为:%d\n",ch,28); //判断结果为"<"}break;case'>':ch=fgetc(fr);word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='=') {word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,29); }elseif(ch=='>'){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,30); }else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,31); }break;default: break;}fprintf(fw,"\n");}}int main(){clock_t start,end;char cr;char str_in[25],str_out[25],str_out1[25],str_out2[25];double duration;start=clock();printf("请输入文件的读取路径(包含文件的后缀名):\n");scanf("%s",str_in);fr=fopen(str_in,"r");while(fr==NULL){printf("文件路径输入错误~请重新输入:\n");scanf("%s",str_in);fr=fopen(str_in,"r");}printf("文件读入成功~内容显示如下:\n");printf("**************************************************\n"); cr=fgetc(fr);while (cr!=EOF) {putchar(cr);cr=fgetc(fr);}printf("\n");printf("**************************************************\n");printf("请输入文件的最终结果的写入路径(包含文件的后缀名):\n");scanf("%s",str_out);printf("请输入文件的常量表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out1);printf("请输入文件的符号表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out2);fw=fopen(str_out,"w");temp1=fopen(str_out1,"w");temp2=fopen(str_out2,"w");while(fw==NULL||temp1==NULL||temp2==NULL||str_out==str_out1||str_out 1==str_out2||str_out2==str_out){printf("文件路径输入错误~请重新输入:\n");if(str_out==str_out1){printf("请输入文件的常量表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out1);}elseif(str_out==str_out2){printf("请输入文件的符号表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out2);}elseif (str_out1==str_out2) {printf("请输入文件的符号表的写入路径(包含文件的后缀名):\n"); scanf("%s",str_out2);}if(fw==NULL){scanf("%s",str_out);fr=fopen(str_out,"w");}elseif(temp1=NULL){scanf("%s",str_out1);fr=fopen(str_out1,"w");}elseif (temp2=NULL) {scanf("%s",str_out2);fr=fopen(str_out2,"w");}}while(str_in==str_out||str_in==str_out1||str_in==str_out2){if(str_out==str_in){printf("请输入文件的最终结果的写入路径(包含文件的后缀名):\n");scanf("%s",str_out);}elseif(str_in==str_out1){printf("请输入文件的常量表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out1);}elseif(str_in==str_out2){printf("请输入文件的符号表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out2);}}fprintf(temp1,"文件中依次出现的标识符\n");fprintf(temp2,"文件中依次出现的符号\n");fr=fopen(str_in,"r");check(fr);printf("文件写入成功~编译结果已写入指定文件区域~请注意查看...........\n\n");fclose(fw);/*FILE *fr1;fr1=fopen(str_out2,"w");cr=fgetc(fr1);char ctemp=fgetc(fr1);while (cr!=EOF) {while(ctemp!=cr){ctemp=fgetc(fr1);}ctemp=NULL;cr=fgetc(fr1);ctemp=fgetc(fr1);}*/fclose(temp1);fclose(temp2);fclose(fr);printf("\n");end=clock();duration=(double)(end-start)/CLOCKS_PER_SEC * 1000; printf("该词法分析程序共运行约%lf ms\n", duration); return 0;}。

C语言的词法分析器

C语言的词法分析器

1.实验目的及要求1、目的通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

2、要求●根据具体情况,由同学们自己选取C语言的一个适当大小的子集(可取一类典型单词,也可以尽可能使各种类型的单词都兼顾到);在实习前一定要制出相应的表。

●实验时间:4-8学时●检查内容及时间:A)完整的实验报告。

B)在机器上调试成功的源程序。

3、软件、硬件环境●Visual studio 2010 ,Windows 7操作系统●计算机一台2.实验步骤●分析对于单词符号我们将其分成四类:保留字K、标识符I、常数C和界符P,每类单词符号均可使用一张表格表示.在词法分析过程中,保留字K和界符P这两个表格的内容是固定不变的(由语言确定),源程序字符串只能从其中选取,而标识符I、常数C这两表是在分析过程中不断形成的.对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是K、I、C或P中之一,那么就以单词的二元式形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串.各类单词的二元式表述均具有相同的结构与长度,形式如下:(单词种别t,单词自身的值i)t是单词种别,而单词种别共分为K、I、C、P四类且每类对应一张表格.因此,t实际上就是一个指向这四类中某一类对应表格的指针.i则为指向该类表格中一个特定项目的指针.所以整个的词法分析过程就是从源程序中获得一个个的单词符号,将这些符号分别填入四张类表中,并且有一个二元式序列构成一个索引,这个索引为以后的语法分析提供处理上的方便.为了减少实习量,可以适量地选取K,P中的一个子集来进行.如下表:表保留字表包括10个有代表性的保留字,界符表包括关系运算符,算术运算符,分隔符三种,一对圆括号,加上赋值号,花括号,分号,引号.这两表的内容表明C语言的条件语句,赋值语句,WHILE型循环语句,复合语句,过程及变量说明均可作为源程序例子输入给词法分析程序,标识符表I中的每一项包含一个标识符,常数表C中的每一项包含一个整常数,后两表的内容都是在词法分析过程中产生的.如何从源程序中识别出一个个的单词符号呢?图1中的流图清晰地反映出这一过程.图1中,双圆圈的状态表示终态,即能到达终态就代表识别出一个单词符号,而带有*号的终态是指处理时应回退一字符.算法词法分析器在扫描过程中,依次从源程序中取出源字符,根据图1的扫描过程状态转换图,当碰到终态时,即双圆圈的状态时就得到一个单词符号,此时可以根据第一个字符判断单词属于K,I,C,P中哪一个类,从而确定单词的“单词种别”和“单词自身的值”。

词法分析器(c语言实现)

词法分析器(c语言实现)

词法分析c实现一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。

(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的C语言程序源代码:#include <stdio.h>#include <string.h>char prog[80],token[8],ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};scaner();main(){p=0;printf("\n please input a string(end with '#'):/n");do{scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11:printf("( %-10d%5d )\n",sum,syn);break;case -1:printf("you have input a wrong string\n");getch();exit(0);default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);getch();}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;ch=prog[p++];m=0;while((ch==' ')||(ch=='\n'))ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;break;}}else if((ch>='0')&&(ch<='9')) { while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=22;token[m++]=ch;}else{ syn=20;p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=24;token[m++]=ch;}else{ syn=23;p--;}break;case '+': token[m++]=ch;ch=prog[p++];if(ch=='+'){ syn=17;token[m++]=ch;}else{ syn=13;p--;}break;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;token[m++]=ch;}else{ syn=31;p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=25;token[m++]=ch;}else{ syn=18;p--;}break;case '*': syn=15;token[m++]=ch;break;case '/': syn=16;token[m++]=ch;break;case '(': syn=27;token[m++]=ch;break;case ')': syn=28;break;case '{': syn=5;token[m++]=ch;break;case '}': syn=6;token[m++]=ch;break;case ';': syn=26;token[m++]=ch;break;case '\"': syn=30;token[m++]=ch;break;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5-1所示:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理—词法分析器实验报告一、实验目的:1.设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。

2.掌握在对程序设计语言的源程序扫描的过程中,将其分解后各类单词的语法分析方法。

二、实验要求:1. 对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。

而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。

2. 本程序自行规定:(1)关键字"begin","end","if","then","else","while","write","read","do", "call","const","char","until","procedure","repeat"(2)运算符:"+","-","*","/","="(3)界符:"{","}","[","]",";",",",".","(",")",":"(4)其他标记如字符串,表示以字母开头的标识符。

(5)空格、回车、换行符跳过。

在屏幕上显示如下:( 1 , 无符号整数)( begin , 关键字)( if , 关键字)( +, 运算符)( ;, 界符)( a , 普通标识符)三、使用环境:Window vista 下的Visual Studio 2008;四、实验步骤1.查询资料,了解词法分析器的工作过程与原理。

2.分析题目,整理出基本设计思路。

3.实践编码,将设计思想转换用c语言编码实现,编译运行。

4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。

通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。

五、流程图五、调试程序:1.举例说明文件位置:C:\TEST.txt目标程序如下:Int main(){i=10;j=100;n=1;sum=0;mult=1;while (i>0) {n=n+1;i=i-1;}if (j>=50) then sum=sum+j; else {mult=mult*(j+1);sum=sum+i;} if (i<=10) then sum=sum-i; else mult=mult+i/2;if (i==j) then sum=sum-j; else mult=mult-j/2;if (n>1) then n=n-1; else n=n+1;if (n<2) then n=n+2; else n=n-2;}2.运行结果:六、程序源代码:#include<iostream>#include<string>using namespace std;#define MAX 22char ch =' ';string key[15]={"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"};int Iskey(string c){ //关键字判断int i;for(i=0;i<MAX;i++) {if(key[i].compare(c)==0) return 1;}return 0;}int IsLetter(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void analyse(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF) {arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)){while(IsLetter(ch)||IsDigit(ch)) {if((ch<='Z')&&(ch>='A')) ch=ch+32; arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if (Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;}else cout<<arr<<"\t$普通标识符"<<endl; }else if(IsDigit(ch)){while(IsDigit(ch)||ch=='.'&&IsDigit(fgetc(fpin))){ arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t$无符号实数"<<endl;}else switch(ch){case'+':case'-' :case'*' :case'=' :case'/' :cout<<ch<<"\t$运算符"<<endl;break;case'(' :case')' :case'[' :case']' :case';' :case'.' :case',' :case'{' :case'}' :cout<<ch<<"\t$界符"<<endl;break;case':' :{ch=fgetc(fpin);if(ch=='=') cout<<":="<<"\t$运算符"<<endl;else {cout<<"="<<"\t$运算符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>' :{ch=fgetc(fpin);if(ch=='=') cout<<">="<<"\t$运算符"<<endl;if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;else {cout<<">"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<' :{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;else if(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl;else if(ch=='>') cout<<"<>"<<"\t$运算符"<<endl;else{cout<<"<"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default : cout<<ch<<"\t$无法识别字符"<<endl;}}}void main(){char in_fn[30];FILE * fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL) break;else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";}cout<<"\n********************分析如下*********************"<<endl;analyse(fpin);fclose(fpin);cout<<endl;cout<<"按任意键结束"<<endl;int a;cin>>a;}六、实验心得:通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。

相关文档
最新文档