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

合集下载

llvm编译c-概述说明以及解释

llvm编译c-概述说明以及解释

llvm编译c-概述说明以及解释1.引言1.1 概述LLVM(Low Level Virtual Machine)是一个开源的编译器基础设施,它提供了广泛的编译技术和工具。

通过LLVM,我们可以实现高效的代码生成、优化和分析,从而实现跨平台的编译。

LLVM已经成为许多编程语言的编译器后端,如C、C++、Objective-C等。

在本文中,我们将重点讨论LLVM编译C语言的过程。

我们将介绍LLVM的基本结构和原理,探讨如何使用LLVM将C代码编译成机器代码,并深入研究LLVM在编译优化中的应用。

通过本文的学习,读者将能够更深入地了解编译器技术和LLVM在其中的作用。

1.2 文章结构文章结构部分主要介绍了整篇文章的组织和安排,包括引言、正文和结论三个部分。

具体内容如下:引言部分包括概述、文章结构和目的三个小节。

在概述中,会对整个文章的主题进行简要介绍,引出文章的主要内容。

文章结构部分则是本节所在的部分,介绍了整篇文章的框架和组成部分。

而目的部分则会说明为什么要撰写这篇文章,读者可以在这里了解到文章的写作意图和期望达到的效果。

正文部分则包括LLVM简介、LLVM编译C语言的过程和LLVM在编译优化中的应用三个小节。

在这三个小节中,会详细介绍LLVM技术的背景和原理,以及在实际编译C语言过程中的应用和优化效果。

结论部分包括总结、未来展望和结束语三个小节。

在总结部分,会对整篇文章的内容进行概括和总结,重点强调文章的主要观点和结论。

未来展望部分则会展望LLVM技术在未来的发展方向和应用领域,为读者提供展望和思考的角度。

结束语则是文章的结尾部分,可以对读者提出反思或启发,激发读者的思考和讨论。

1.3 目的:本文旨在介绍使用LLVM编译器进行C语言编译的过程,并探讨LLVM 在编译优化中的应用。

通过深入了解LLVM编译器的工作原理和优化技术,读者可以更好地理解现代编译器的工作机制,并学习如何利用LLVM提供的优化功能提高代码执行效率和性能表现。

编译原理----词法分析程序----C语言版

编译原理----词法分析程序----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);}}。

编译原理词法分析器代码

编译原理词法分析器代码

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <conio.h>#define KEYWORD_LEN 32 //保留字个数#define STR_MAX_LEN 300 //标识符最大长度#define PRO_MAX_LEN 20480 //源程序最大长度#define STB_MAX_LEN 1000 //符号表最大容量#define CTB_MAX_LEN 1000 //常数表最大容量#define ERROR 0 //错误#define ID (KEYWORD_LEN+1) //标识符#define CONST (KEYWORD_LEN+2) //常量#define OPERAT (KEYWORD_LEN+3) //运算符#define DIVIDE (KEYWORD_LEN+4) //界符int errorLine=0; char proBuffer[PRO_MAX_LEN] = ""; //存储程序代码的全局缓冲区char ch; //读出来的当前字符char wordget[STR_MAX_LEN]; //标识符或常量int point = 0; //源程序当前位置指针char signTab[STB_MAX_LEN][STR_MAX_LEN]; //符号表int pointSTB = 0; //符号表指针char constTab[CTB_MAX_LEN][STR_MAX_LEN]; //常量表int pointCTB = 0; //常数表指针char kwTab[KEYWORD_LEN][10]={ //保留字表C语言一共有32个保留字[关键字]"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"};char errorTab[][50]={ //错误代码表/*0*/"未知错误", /*1*/"非法的字符", /*2*/"不正确的字符常量表达",/*3*/"不正确的字符串表达", /*4*/"不正确的数字表达", /*5*/"注释丢失'*/'"};typedef struct signDuality{int kind;int value;}*pDualistic, Dualistic;void pretreatment(); //预处理void ProcError(int id); //错误bool GetChar(); //获得一个字符不包括结束标记bool GetBC(); //获得一个非空白字符void Concat(char *str); //将ch连接到str后int Reserve(char *str); //对str字符串查找保留字表若是一个保留字-返回其编码否则返回0void Retract(); //将搜索指示器回调一个字符位置int InsertId(char *str);//将str串以标识符插入符号表,并返回符号表指针int InsertConst(char *str); //将str串以常数插入符号表,并返回常数表指针bool wordAnalyse(pDualistic pDu); //词法分析true正常//预处理将缓冲区内的源代码去掉注释和无效空格void pretreatment(){int lines=0;char tmp[PRO_MAX_LEN]; //先将处理结果保存到临时空间int tmpp = 0; //这个临时空间的末尾指针bool flg;char tmpc; //去掉注释先//注释有两种一种是// 另一种是/**/point = 0;do{flg = GetChar();if(ch == '/'){flg = GetChar();switch(ch){case '/':do{flg = GetChar();}while(!(ch == '\n' || flg == false));//注释一直到行尾或文件结束if(ch == '\n')Retract(); //归还换行break;case '*':do{flg = GetChar();tmpc = ch;//为了保证出错处理程序能正确定位出错位置保留注释中的换行if(tmpc == '\n')tmp[tmpp++] = tmpc;flg = GetChar();Retract(); //归还一个字符}while(flg && !(flg && tmpc == '*' && ch == '/'));flg = GetChar();if (!flg){ProcError(5);}break;default: //不是任何一种注释Retract();Retract();GetChar();tmp[tmpp++] = ch;flg = GetChar();tmp[tmpp++] = ch;}}else{tmp[tmpp++] = ch;}}while(flg);tmp[tmpp] = '\0';strcpy(proBuffer,tmp);}//错误void ProcError(int id){printf("\nError:第%d行,%s\n",errorLine, errorTab[id]);}//获得一个字符bool GetChar(){if(point < PRO_MAX_LEN && proBuffer[point] != '\0'){//如果当前下标合法且当前字符为结束标记则取字符增游标ch = proBuffer[point++];if (ch == '\n')errorLine ++;return true;}ch = '\0';return false;}//获得一个非空白字符bool GetBC(){do{if(!GetChar()) //获取字符失败{ch = '\0';return false;}}while(isspace(ch)); //直到获得一个非空白字符return true;}//将ch连接到str后void Concat(char *str){int i;for(i=0; str[i]; ++i);str[i] = ch;str[i+1] = '\0';}//对str字符串查找保留字表若是一个保留字-返回其编码否则返回0int Reserve(char *str){int i;for(i=0; i<KEYWORD_LEN; ++i) //从保留字表中查找str串{if(0 == strcmp(kwTab[i], str))return i+1; //注意,这里加一原因是0值被错误标记占用}return 0;}//将搜索指示器回调一个字符位置void Retract()///char *ch{if(proBuffer[point] == '\n' && errorLine > 0)errorLine --;point --;}//将str串以标识符插入符号表,并返回符号表指针int InsertId(char *str){int i;for(i=0; i < pointSTB; ++i)if(0 == strcmp(signTab[i], str))return i;strcpy(signTab[pointSTB++], str);return (pointSTB-1);}//将str串以常数插入常量表,并返回常数表指针int InsertConst(char *str){int i;for(i=0; i < pointCTB; ++i)if(0 == strcmp(constTab[i], str))return i;strcpy(constTab[pointCTB++], str);return (pointCTB-1);}//词法分析false--分析结束bool wordAnalyse(pDualistic pDu){int code, value;char judge; //这里有个技巧借用此变量巧妙的运用SWITCH结构int i = 0; //辅助GetBC();judge = ch;if (isalpha(ch) || ch == '_')judge='L';if (isdigit(ch))judge='D';switch(judge){case 'L':while(isalnum(ch) || ch == '_'){ //标识符wordget[i++] = ch;GetChar();}wordget[i] = '\0';Retract(); //回退一个字符code = Reserve(wordget);if(code == 0){value = InsertId(wordget);pDu->kind = ID;pDu->value = value;}else{pDu->kind = code;pDu->value = -1;}return true;case 'D':while(isdigit(ch)){wordget[i++] = ch;GetChar();}wordget[i] = '\0';Retract();value = InsertConst(wordget);pDu->kind = CONST;pDu->value= value;return true;//( ) [ ] . , ! != ~ sizeof < << <= > >> >= = == & && &= | || |= ?: + ++ +=// --> ---= * *= / /= % %= >>= <<= ^ ^=case '"': //字符串常量do{wordget[i++] = ch;GetChar();}while(ch != '"' && ch != '\0');wordget[i++] = ch;wordget[i] = '\0';if(ch == '\0'){printf("%s",wordget);ProcError(3);pDu->kind = ERROR;pDu->value = 0;}else{value = InsertConst(wordget);pDu->kind = CONST;pDu->value = value;}return true; //字符常量case '\'':wordget[i++] = ch; // 'GetChar();wordget[i++] = ch;if(ch == '\\') // '\n'{//如果是转义字符则要多接收一个字符GetChar(); // ch = 'wordget[i++] = ch;}GetChar();wordget[i++] = ch;wordget[i] = '\0';if(ch != '\''){//'\b'printf("%s",wordget);ProcError(2);pDu->kind = ERROR;pDu->value = 0;}else{value = InsertConst(wordget);pDu->kind = CONST;pDu->value = value;}return true;case '(':case ')':case '[':case ']':case '.':case ',':case '~':case '?':case ':':case ';':case '{':case '}':case '#':wordget[i++] = ch;wordget[i] = '\0';pDu->kind = DIVIDE; //界符pDu->value = -1;return true;case '!': //!=wordget[i++] = ch;GetChar();if (ch=='=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '<': // << <=wordget[i++] = ch;GetChar();if (ch == '<' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '>': // >> >=wordget[i++] = ch;GetChar();if (ch == '>' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '=': // ==wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '&': // && &=wordget[i++] = ch;GetChar();if (ch == '&' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break; case '|': // || |=wordget[i++] = ch;GetChar();if (ch == '|' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '+': // ++ +=wordget[i++] = ch;GetChar();if (ch == '+' || ch == '=')wordget[i++] = ch;else Retract();wordget[i]='\0';break;case '-': // ---= ->wordget[i++] = ch;GetChar();if (ch == '-' || ch == '=' || ch == '>')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '*':// ** *=wordget[i++] = ch;GetChar();if (ch == '*' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '/': // /=wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '%': // %=wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '^': // ^=wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '\0':return false;default:ProcError(1);return false;}pDu->kind = OPERAT;return true;}//主函数int main(){Dualistic tmp;pDualistic ptmp = &tmp;FILE *fin, *fout;int i;char c;char filename[20];printf("源代码读入\n");//scanf("%s",filename);//将源程序读入缓冲区if ((fin=fopen("Test.txt","r")) == NULL){printf("Cannot open infile\n");return 0;}i = 0;//c = fgetc(fin);while((c = fgetc(fin)) != EOF){if(i >= PRO_MAX_LEN-1){printf("\n程序代码太长,无法处理\a");return 0;}proBuffer[i++] = c;}fclose(fin); //关闭文件proBuffer[i++] = '\0';printf("\n***************************\n源代码读入成功,源代码如下:\n%s",proBuffer);printf("\n按任意键继续\n");getch(); //预处理printf("\n预处理\n");pretreatment();printf("\n***************************\n预处理成功,去掉注释后的源代码为:\n%s*",proBuffer);printf("\n按任意键继续\n");getch();printf("\n词法分析\n");point = 0;//词法分析if ((fout=fopen("Result.txt","wb")) == NULL){printf("建立文件Result.txt失败。

【编译原理】词法分析(CC++源代码+实验报告)

【编译原理】词法分析(CC++源代码+实验报告)

【编译原理】词法分析(CC++源代码+实验报告)⽂章⽬录1 实验⽬的和内容1.1实验⽬的(1)根据 PL/0 语⾔的⽂法规范,编写PL/0语⾔的词法分析程序;或者调研词法分析程序的⾃动⽣成⼯具LEX或FLEX,设计并实现⼀个能够输出单词序列的词法分析器。

(2)通过设计调试词法分析程序,实现从源程序中分离出各种类型的单词;加深对课堂教学的理解;提⾼词法分析⽅法的实践能⼒。

(3)掌握从源程序⽂件中读取有效字符的⽅法和产⽣源程序的内部表⽰⽂件的⽅法。

(4)掌握词法分析的实现⽅法。

(5)上机调试编出的词法分析程序。

1.2实验内容根据PL/0语⾔的⽂法规范,编写PL/0语⾔的词法分析程序。

要求:(1)把词法分析器设计成⼀个独⽴⼀遍的过程。

(2)词法分析器的输出形式采⽤⼆元式序列,即:(单词种类, 单词的值)2 设计思想2.1单词种类及其正规式(1)基本字单词的值单词类型正规式rbegin beginsym begincall callsym callconst constsym constdo dosym doend endsym endif ifsym ifodd oddsym oddprocedure proceduresym procedureread readsym readthen thensym thenvar varsym varwhile whilesym whilewrite writesym write(2)标识符单词的值单词类型正规式r标识符ident(字母)(字母|数字)*(3)常数单词的值单词类型正规式r常数number(数字)(数字)*(4)运算符单词的值单词类型正规式r+plus+-minus-*times*/slash/=eql=<>neq<><lss<<=leq<=>gtr>>=geq>=:=becomes:=(5)界符单词的值单词类型正规式r(lparen()rparen),comma,;semicolon;.period.2.2 根据正规式构造NFA下⾯我们根据上述的正规式来构造该⽂法的NFA,如下图所⽰,其中状态0为初态,凡带双圈的状态均为终态,状态24是识别不出单词符号的出错情形,其他状态的识别情况如下图中右边的注释所⽰。

基于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语⾔实现简单的词法分析器词法分析器⼜称扫描器。

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

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

要实现的词法分析器单词符号及种别码对照表:单词符号#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语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

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

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

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

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

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

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

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

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

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

例如:对源程序begi n x:=9: if x>9 then x:=2*x+1/3; end # 的源文件,经过词法分析后输出如下序列:(1,begi n)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的C语言程序源代码:#i nclude <stdio.h>#in clude <stri ng.h>char prog[80],toke n[ 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;case '-':token[m++]=ch; 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;toke n[ m++]=ch; break;case '{': syn=5;toke n[ m++]=ch; break;case '}': syn=6;toke n[ m++]=ch; break;case ';': syn=26; toke n[ m++]=ch; break; case '、"': syn=30; toke n[ m++]=ch; break; case '#': syn=0; toke n[ m++]=ch; break; case ':':s yn=17;toke n[ m++]=ch; break;default: syn=-1;break; }toke n[ m++]='\0'; }四、结果分析:输入 beg in x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列: (begin 1)(x 10)(: 17)(=11)(; 26)(if2)1 y 10) 17〉 is y 11〉 26、2 ?IH 、 23 ) 11 y 3〉 io y 17〉 18 \ II 、15 > 10 ) 13 ? 11〉 16 ) 11〉 2£ 〉 m 、 u y;HC 三卜TV®译原理比IFAFE" ・exe如图5-1所示:X9Xend ttbegin Xx>0。

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

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","re turn"};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语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

相关文档
最新文档