实验1-3-《编译原理》词法分析程序设计方案

合集下载

编译原理实验一词法分析

编译原理实验一词法分析

编译原理实验⼀词法分析实验⼀词法分析【实验⽬的】 (1)熟悉词法分析器的基本功能和设计⽅法; (2)掌握状态转换图及其实现; (3)掌握编写简单的词法分析器⽅法。

【实验内容】 对⼀个简单语⾔的⼦集编制⼀个⼀遍扫描的词法分析程序。

【实验要求】 (1)待分析的简单语⾔的词法 1) 关键字 begin if then while do end 2) 运算符和界符 := + - * / < <= <> > >= = ; ( ) # 3) 其他单词是标识符(ID)和整形常数(NUM),通过以下正规式定义: ID=letter(letter|digit)* NUM=digitdigit* 4) 空格由空⽩、制表符和换⾏符组成。

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

(2)各种单词符号对应的种别编码 (3)词法分析程序的功能 输⼊:所给⽂法的源程序字符串 输出:⼆元组(syn,token 或 sum)构成的序列。

syn 为单词种别码; token 为存放的单词⾃⾝字符串; sum 为整形常数。

【实验代码】1 #include<iostream>2 #include<string.h>3 #include<conio.h>4 #include<ctype.h>5using namespace std;6int sum,syn,p,m,n;7char ch,chs[8],s[100];8char *tab[6]={"begin","if","then","while","do","end"};910int scanner(){11for(n=0;n<8;n++) chs[n]='\0';12 m=0;13 n=0;14 ch=s[p++];15while(ch=='') ch=s[p++];16if(isalpha(ch)){17while(isalpha(ch)||isdigit(ch)){18//isalpha(ch)函数:判断字符ch是否为英⽂字母,⼩写字母为2,⼤写字母为1,若不是字母019//isdigit(ch)函数:判断字符ch是否为数字,是返回1,不是返回020 chs[m++]=ch;21 ch=s[p++];22 }23 syn=10;24for(n=0;n<6;n++)25if(strcmp(chs,tab[n])==0) syn=n+1;26 p--;27 }else if(isdigit(ch)){28 sum=0;29while(isdigit(ch)){30 sum=sum*10+(ch-'0');31 ch=s[p++];32 }33 syn=11;34 p--;35 }else if(ch==':'){36 syn=17;37 chs[m++]=ch;38 ch=s[p++];39if(ch=='='){ syn=18;chs[m]=ch;p++;}40 p--;41 }else if(ch=='<'){42 syn=20;43 chs[m++]=ch;44 ch=s[p++];45if(ch=='>') { syn=21;chs[m]=ch;p++;}46if(ch=='=') { syn=22;chs[m]=ch;p++;}47 p--;48 }else if(ch=='>'){49 syn=23;50 chs[m++]=ch;51 ch=s[p++];52if(ch=='=') { syn=24;chs[m]=ch;p++;}53 p--;54 }else switch(ch){55case'+':syn=13;chs[m]=ch;break;56case'-':syn=14;chs[m]=ch;break;57case'*':syn=15;chs[m]=ch;break;58case'/':syn=16;chs[m]=ch;break;59case'=':syn=25;chs[m]=ch;break;60case';':syn=26;chs[m]=ch;break;61case'(':syn=27;chs[m]=ch;break;62case')':syn=28;chs[m]=ch;break;63case'#':syn=0;chs[m]=ch;break;64default:syn=-1;65 }66return0;67 }68int main(){69 p=0;70 cout<<"Please input code and end with character '#':"<<endl;71do{72//cin>>ch;不识别空格73 ch=getchar();74 s[p++]=ch;75 }while(ch!='#');76 p=0;77do{78 scanner();79switch(syn){80case11:cout<<'('<<syn<<','<<sum<<')'<<endl;break;81case -1:cout<<'('<<syn<<','<<"error"<<')'<<endl;break;82default:cout<<'('<<syn<<','<<chs<<')'<<endl;83 }84 }while(syn!=0);85//getch():是⼀个不回显函数,当⽤户按下某个字符时,函数⾃动读取,⽆需按回车,所在头⽂件是conio.h。

编译原理综合性实验:词法分析的设计

编译原理综合性实验:词法分析的设计
编译过程中编译程序需要不断汇集和反复查证出现在源程序中各种名字的属性和特征 等有关信息。这些信息通常记录在符号表中。符号表中的每一项一般包含两部分:名字,与 此名字有关的信息,如类型,种属,值等。符号表主要在词法或语法分析阶段生成,可能用 于语义检查、产生中间代码以及最终生成目标代码等不同阶段。
对数字常数的处理如下:先查符号表 VAL 栏,若发现相同的常数则直接输出其二元式。 若表内无相同的常数,则将数字常数填入符号表内,在 TYPE 栏内填入整型或实型,然后输 出其二元式。二元式中包含该常数在符号表中的入口。
1.3 词法分析程序的详细设计
图 1-3 的数据流图属于输入-变换-输出形式的变换型数据流图,但加工 1.3—1.9 构成了典型的事务处理型数据流图。根据数据流图,可以得到词法分析 程序的总体框架,如图 1-4。
图 1-3 词法分析程序的详细数据流图 在上面的数据流图中,各个加工处理完成的功能如下: 加工 1.1(读一行并打印):收到读下一行命令后,从源程序读入一行,装入缓冲区,行计 数,并打印。在这里需要注意的是,回车换行在源程序(文本文件)中用两个字符 0D0AH 来表示,而用高级语言(C 语言)读入内存后,就用一个字符 0AH 来表示,这是在用高级
查找函数可以使用顺序查找,也可以使用折半查找。 例如:使用顺序查找方法查找给定单词 key 是否是关键字的函数原型和算法描述如下:
int iskeyword (char * str)/*设 keyword 为所有关键字列表*/ /*该函数返回 0 表示 str 不是关键字,不为 0 表示 str 是关键字*/
词不能跨行书写; (4) 关键字都是保留字。
1.2 词法分析程序的总体设计
图 1-2 词法分析程序的顶层数据流图 图 1-2 是词法分析程序的顶层数据流图,即是词法分析程序的输入输出界面图,由此可 以看出词法分析程序的功能就是从源程序中读入一个个字符,依据一定的构词规则,识别出 各类有用的单词。其中源程序清单和错误信息从屏幕、打印机或文件输出,其余文件均以顺 序文件的形式输出到外存储器上,以供下一阶段使用。由此可以得到更详细的数据流图,如 图 1-3。

编译原理 词法分析程序设计

编译原理 词法分析程序设计

实验1 词法分析程序设计【实验目的】(1)理解词法分析在编译程序中的作用(2)加深对有穷自动机模型的理解(3)掌握词法分析程序的实现方法和技术【实验内容】对一个简单语言的子集编制一个一遍扫描的词法分析程序。

【设计思路】图1.1 词法分析主程序示意图2、源程序代码(1)scan.h //头文件-----扫描程序#include<stdio.h>#include<string.h>#define CLEAR memset(token,'\0',sizeof(token))//清空数组tokenchar prog[80],token[8];char ch;int syn,p,m,n,sum; //p是缓冲区prog的指针,m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};void scanner() //词法扫描程序{CLEAR;m=0;while(ch==' '){++p;ch=prog[p]; //读下一个字符;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')){token[m++]=ch;++p;ch=prog[p];//读下一个字符;}token[m++]='\0';syn=10;for(n=0;n<6;++n)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}elseif(ch>='0'&&ch<='9'){sum=0;while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';//将ch转换为数字++p;ch=prog[p];}syn=11;}elseswitch(ch)//其他字符情况{case'<':m=0;token[m++]=ch;++p;ch=prog[p];if(ch=='>'){syn=21;++m;token[m]=ch;}else if(ch=='='){syn=22;++m;token[m]=ch;}{syn=20;}break;case'>':token[0]=ch;++p;ch=prog[p];if(ch=='='){syn=24;token[0]=ch;}else{syn=23;}break;case':':token[0]=ch;++p;ch=prog[p];if(ch=='='){syn=18;++m;token[m]=ch;++p;ch=prog[p];}else{syn=17;}break;case'+':syn=13;token[0]=ch;ch=prog[++p];break;case'-':syn=14;token[0]=ch;ch=prog[++p];break;case'*':syn=15;token[0]=ch;ch=prog[++p];case'/':syn=16;token[0]=ch;ch=prog[++p];break;case'=':syn=25;token[0]=ch;ch=prog[++p];break;case';':syn=26;token[0]=ch;ch=prog[++p];break;case'(':syn=27;token[0]=ch;ch=prog[++p];break;case')':syn=28;token[0]=ch;ch=prog[++p];break;case'#':syn=0; token[0]=ch;ch=prog[++p];break;default:syn=-1;}}(2)word.cpp // 词法分析主程序#include"scan.h"void main(void){p=0;printf("\n please input string:\n");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;ch=prog[0];if(ch>='0'&&ch<='9')printf("error!\n");else{do{scanner();//调用扫描子程序switch(syn){case 11:printf("(%d,%d)\n",11,sum);break;case -1:printf("error!\n");break;default:printf("(%d,'%s')\n",syn,token);}} while(syn!=0);}}【思考题】在编程过程中遇到了哪些问题,你是如何解决的。

编译原理实习设计——词法分析程序

编译原理实习设计——词法分析程序

图三:实数的识别
} 27 { * 26 * 25 ] * 24 [ * 23 ( * 22 ) * 21 ; *
20 , * * | 19 18 非| 17 | * * 16 & 15 非& 14 & * = 13 * 12 非= 11 = * 10 # * 9 = * 8 非= 7 %
* 6 ^ * 5 = * 4 非= 3 ! * 2
if(c=='>' || c=='"') { Output("$ID", string); for(int p=0; p<k; p++) { string[p]=NULL; } break; } else if( c=='.' || IsLetter(c) IsDigit(c) ) { string[k++]=c; } } break; } j++; } c=Get_ch(++j); } if(IsLetter(c) || c=='_') { k=0; string[k++]=c; j++; while(1) { c=Get_ch(j); if(IsLetter(c) || c=='_' || IsDigit(c)) { string[k++]=c; } else { if(IsKeyword(string) ) { Output("$keyword", string); }
!= ^ % %= = == && & | || , ; ( ) [ ] { } + ++ += - ―― -= * *= / /=

编译原理实验--词法分析器

编译原理实验--词法分析器

实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。

2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。

3.通过完成词法分析程序,了解词法分析的过程。

【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。

【实验流程图】【实验步骤】1.提取pl/0文件中基本字的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE];int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} }2.提取pl/0文件中标识符的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE]=" ";int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {m=14;n=k+1;}}if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);3.提取pl/0文件中常数的源代码while((ch=fgetc(stream))!='.'){while(ch>='0' && ch<='9'){num=10*num+ch-'0';ch=fgetc(stream);}if(num!=0) printf("%d ",num);num=0;}4.提取pl/0文件中运算符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case'+': printf("+ ");break;case'-': printf("- ");break;case'*': printf("* ");break;case'/': printf("/ ");break;case'>': if(fgetc(stream)=='=')printf(">= "); else printf("> ");break;case'<': if(fgetc(stream)=='=')printf("<= "); else printf("< ");break;case':': printf(":= ");break;case'#': printf("# ");break;case'=': printf("= ");break;default: break;}ch=fgetc(stream);5.提取pl/0文件中界符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case',': printf(", ");break;case';': printf("; ");break;case'(': printf("( ");break;case')': printf(") ");break;default: break;}ch=fgetc(stream);}【实验结果】1.pl/0文件(222.txt)内容const a=10;var b,c;procedure p;beginc:=b+a;end;beginread(b);while b#0 dobegincall p;write(2*c);read(b)endend .2.实验运行结果【实验小结】1.了解程序在运行过程中对词法分析,识别一个个字符并组合成相应的单词,是机器能过明白程序,定义各种关键字,界符。

编译原理实验报告——词法分析器(内含源代码)

编译原理实验报告——词法分析器(内含源代码)

编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。

该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。

二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。

四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。

int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。

void GetChar(char *ch); //将下一个输入字符读到ch中。

void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。

void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。

int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。

void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。

编译原理词法分析实验

编译原理词法分析实验

编译原理词法分析实验一、实验目的本实验旨在通过编写一个简单的词法分析器,了解编译原理中词法分析的基本原理和实现方法。

二、实验材料1. 计算机编程环境2. 编程语言三、实验步骤1. 了解词法分析的概念和作用。

词法分析是编译器中的第一个阶段,它的主要任务是将源代码中的字符序列转化为有意义的标识符,如关键字、操作符、常量和标识符等。

2. 设计词法分析器的流程和算法。

词法分析器的主要原理是通过有限状态自动机来识别和提取标识符。

在设计过程中,需考虑各种可能出现的字符序列,并定义相应的状态转移规则。

3. 根据设计的流程和算法,使用编程语言编写词法分析器的代码。

4. 编译并运行词法分析器程序,输入待分析的源代码文件,观察程序的输出结果。

5. 分析输出结果,检查程序是否正确地提取了源代码中的标识符。

四、实验结果经过词法分析器的处理,源代码将被成功地转化为有意义的标识符。

结果可以通过以下几个方面来验证:1. 关键字和操作符是否被正确识别和提取。

2. 常量和标识符是否被正确识别和提取。

3. 检查程序的错误处理能力,如能否发现非法字符或非法标识符。

4. 输出结果是否符合预期,可与自己编写的语法规则进行对比。

5. 对于特殊情况,如转义字符等是否正确处理。

五、实验总结通过本次实验,我深入了解了编译原理中词法分析的重要性和基本原理。

编写词法分析器的过程中,我学会了使用有限状态自动机来识别和提取标识符,并通过实践巩固了相关知识。

此外,我还对源代码的结构有了更深入的了解,并且掌握了如何运用编程语言来实现词法分析器。

通过本次实验,我不仅提升了自己的编程技术,也对编译原理有了更深入的认识和理解。

六、实验心得通过实验,我深刻体会到了词法分析在编译过程中的重要性。

合理设计和实现词法分析器,可以大大提高编译器的效率和准确性。

同时,通过编写词法分析器的代码,我不仅锻炼了自己的编程能力,还提升了对编译原理的理解和掌握。

这次实验让我更加深入地了解了编译原理中的词法分析,也为我今后在编程领域的发展打下了坚实的基础。

(完整word版)编译原理词法分析程序实现实验报告

(完整word版)编译原理词法分析程序实现实验报告

(完整word版)编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。

输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。

输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。

二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:GOTO 1:(完整word版)编译原理词法分析程序实现实验报告GOTO 2:三、源程序代码部分#include <stdio.h>#include<stdlib.h>#include <math.h>#define MAX 100#define UNSIGNEDNUMBER 1#define PLUS 2#define SUBTRACT 3#define MULTIPLY 4#define DIVIDE 5#define LEFTBRACKET 6#define RIGHTBRACKET 7#define INEFFICACIOUSLABEL 8#define FINISH 111int count=0;int Class;void StoreType();int Type[100];char Store[20]={'\0'};void ShowStrFile();//已经将要识别的字符串存在文件a中void Output(int a,char *p1,char *p2);//字符的输出过程int Sign(char *p);//'+''-''*''/'整体识别过程int UnsignedNum(char *p);//是否适合合法的正整数0~9int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程void TypyDistinguish();//字符的识别过程void ShowType();//将类别码存储在Type[100]中,为语法分析做准备void ShowStrFile()//已经将要识别的字符串存在文件a中{FILE *fp_s;char ch;if((fp_s=fopen("a.txt","r"))==NULL){printf("The FILE cannot open!");exit(0);}elsech=fgetc(fp_s);while(ch!=EOF){putchar(ch);ch=fgetc(fp_s);}printf("\n");}void StoreStr()//将文件中的字符串存储到数组Store[i] {FILE *fp=fopen("a.txt","r");char str;int i=0;while(!feof(fp)){fscanf(fp,"%c",&str);if(str=='?'){Store[i]='\0';break;}Store[i]=str;i++;}Store[i]='\0';}void ShowStore(){int i;for (i=0;Store[i]!='\0';i++)printf("%c",Store[i]);printf("\n");}void Output(int a,char *p1,char *p2){printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");while(p1<=p2){printf("%c",*p1);p1++;}printf("\n");}int Sign(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int UnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int LegalCharacter(char *p){char ch=*p;if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')。

2021年编译原理实验报告词法分析程序的设计

2021年编译原理实验报告词法分析程序的设计

试验2 词法分析程序设计一、试验目掌握计算机语言词法分析程序开发方法。

二、试验内容编制一个能够分析三种整数、标识符、关键运算符和关键关键字词法分析程序。

三、试验要求1、依据以下正规式, 编制正规文法, 画出状态图;标识符<字母>(<字母>|<数字字符>)*十进制整数0 | ((1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*)八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和界符+ - * / > < = ( ) ;关键字if then else while do2、依据状态图, 设计词法分析函数int scan( ), 完成以下功效:1)从文本文件中读入测试源代码, 依据状态转换图, 分析出一个单词,2)以二元式形式输出单词<单词种类, 单词属性>其中单词种类用整数表示:0: 标识符1: 十进制整数2: 八进制整数3: 十六进制整数运算符和界符, 关键字采取一字一符, 不编码其中单词属性表示以下:标识符, 整数因为采取一类一符, 属性用单词表示运算符和界符, 关键字采取一字一符, 属性为空3、编写测试程序, 反复调用函数scan( ), 输出单词种别和属性。

四、试验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境五、试验步骤1、依据正规式, 画出状态转换图;2、依据状态图, 设计词法分析算法;观察状态图, 其中状态2、4、7、10(右上角打了星号)需要回调一个字符。

申明部分变量和函数:ch: 字符变量, 存放最新读进源程序字符。

strToken: 字符串变量, 存放组成单词符号字符串。

编译原理课程设计方案词法分析

编译原理课程设计方案词法分析

目录一、实验题目3二、实验目的3三、实验要求4四、实验步骤4基本设计思路4流程框图5算法设计6函数相关说明6输入与输出8程序运行结果9五、实验方案设计实现9六、实验程序亮点描述10七、实验程序使用说明10八、实验心得体会10九、源程序清单10一、实验题目设计、编制、调试一个识别一简单语言单词的词法分析程序。

程序能够识别基本字、标识符、无符号整数、浮点数、运算符和界符)。

单词符号及种别表如下:二、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

三、实验要求词法分析程序需具备词法分析的功能:输入:所给文法的源程序字符串。

(字符串以“#”号结束)输出:二元组(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)……四、实验步骤基本设计思路➢基本字作为一类特殊的标识符来处理:识别出标识符,差基本字表,给出相应种别码。

基本字表置初值:char *rwtab[6]={"begin","if","then","while","do","end"}。

(字符指针的数组)➢识别无符号整数是将数字串转换为无符号整数。

我们在getchar()的时候是把数字当做字符从外部输出读取的。

将数字串345#转换为整数:(3*10+4)*10+5=345送到sum中➢程序主要由2个函数组成,主函数main()和扫描子函数scanner()。

扫描程序每次读取1个独立意义的单词符号,并判断单词类型。

主程序做相应处理后做控制台输出。

编译原理实验词法分析实验报告

编译原理实验词法分析实验报告

编译原理实验词法分析实验报告一、实验目的词法分析是编译过程中的第一个阶段,其主要任务是从输入的源程序中识别出具有独立意义的单词符号,并将其转换为内部编码形式。

本次实验的目的是通过设计和实现一个简单的词法分析程序,深入理解词法分析的基本原理和方法,提高对编程语言语法结构的认识和编程能力。

二、实验原理词法分析的基本原理是根据编程语言的词法规则,使用有限自动机或正则表达式等技术来识别单词符号。

在本次实验中,我们采用了状态转换图的方法来设计词法分析器。

状态转换图是一种用于描述有限自动机的图形表示方法,它由状态节点和有向边组成。

每个状态节点表示自动机的一个状态,有向边表示状态之间的转换条件。

当输入字符与当前状态的转换条件匹配时,自动机将从当前状态转换到下一个状态。

当到达一个终态时,表示识别出了一个单词符号。

三、实验环境本次实验使用了 Python 编程语言,并在 PyCharm 集成开发环境中进行开发和调试。

四、实验内容1、定义单词符号的种类和编码关键字:如`if`、`else`、`while` 等标识符:由字母、数字和下划线组成,且以字母或下划线开头常数:包括整数和浮点数运算符:如`+`、``、``、`/`等分隔符:如`(){},;`等2、设计状态转换图根据单词符号的定义,设计了相应的状态转换图,用于识别不同类型的单词符号。

例如,对于标识符的识别,从起始状态开始,当输入字符为字母或下划线时,进入标识符状态,继续输入字母、数字或下划线,直到遇到非标识符字符为止,此时到达终态,识别出一个标识符。

3、实现词法分析程序使用 Python 语言实现了基于状态转换图的词法分析程序。

程序首先读取输入的源程序文本,然后逐个字符进行处理,根据当前状态和输入字符进行状态转换,当到达终态时,输出识别出的单词符号及其编码。

4、进行测试编写了一些测试用例,包括包含各种单词符号的源程序代码。

运行词法分析程序对测试用例进行分析,检查输出结果是否正确。

编译原理词法分析程序设计实验报告

编译原理词法分析程序设计实验报告

编译原理词法分析程序设计实验报告【实验目的】1.了解词法分析的主要任务。

2.熟悉编译程序的编制。

【实验内容】根据某文法,构造一基本词法分析程序。

找出该语言的关键字、标识符、整数以及其他一些特殊符号,给出单词的种类和值。

【实验要求】1.构造一个小语言的文法类C小语言文法(以EBNF表示)<程序>::=<分程序>{<分程序>} .<分程序>::=<标识符>’(’<变量说明部分>{,<变量说明部分>}’)’<函数体><变量说明部分>::=int<标识符>{,<标识符>}<函数体>::=’{’[<变量说明部分>;]<语句序列>’}’<语句序列>::=<语句序列>;<语句>|<语句><语句>::=<赋值语句>|<条件语句>|<循环语句>|<函数调用语句><赋值语句>::=<标识符>=<表达式><表达式>::=[+|-]<项>{<加法运算符><项>}<项>::=<因子>{<乘法运算符><因子>}<因子>:=<标识符>|<无符号整数><加法运算符>::= +|-<乘法运算符>::= *|/<条件语句>::=if<条件>’{’<语句序列>’}’[else’{’<语句序列>’}’]<条件>::=<表达式><关系运算符><表达式><关系运算符>::= ==|!=|>|<|>=|<=<循环语句>::=for’(’<表达式>;<条件>;<表达式>’)’ ’{’<语句序列>’}’<函数调用语句>::=<标识符>’(’<标识符>{,<标识符>}|<空>’)’<标识符>::=<字母>{<字母>|<数字>}<无符号整数>::=<数字>{<数字>}<字母>::=a|b|c|…|X|Y|Z<数字>::=0|1|2|…|8|9单词分类情况关键字:int if else for标识符:以字母开头的字母和数字的组合关系运算符:==|!=|>|<|>=|<=加法运算符:+|-乘法运算符:*|/界符:,;{ } ( )2.设计单词的输出形式,单词的种类和值的表示方法种别码单词值如:1 int3.编写词法分析程序cffx.c实现基本的词法分析器,能够分析关键字、标识符、数字、运算符(需要有“==”或“:=”之类需要超前搜索的运算符)以及其他一些符号。

实验1-3 《编译原理》词法分析程序设计方案教学内容

实验1-3 《编译原理》词法分析程序设计方案教学内容

实验1-3 《编译原理》S语言词法分析程序设计方案一、实验目的了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式;二、实验内容1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。

在此,词法分析程序作为单独的一遍,如下图所示。

具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。

将错误信息输出到屏幕上。

(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。

标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。

常量表结构:常量名,常量值三、实验要求1.能对任何S语言源程序进行分析在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。

2.能检查并处理某些词法分析错误词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。

本实验要求处理以下两种错误(编号分别为1,2):1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。

2:源程序文件结束而注释未结束。

注释格式为:/* …… */四、保留字和特殊符号表单词的构词规则:字母=[A-Za-z]数字=[0-9]标识符=(字母|_)(字母|数字)*数字=数字(数字)*(.数字+| )四、S语言表达式和语句说明1.算术表达式:+、-、*、/、%2.关系运算符:>、>=、<、<=、==、!=3.赋值运算符:=,+=、-=、*=、/=、%=4.变量说明:类型标识符变量名表;5.类型标识符:int char float6.If语句:if 表达式then 语句[else 语句]7.For语句:for(表达式1;表达式2;表达式3)语句8.While语句:while 表达式do 语句9.S语言程序:由函数构成,函数不能嵌套定义。

编译原理实验(词法分析程序设计)

编译原理实验(词法分析程序设计)
"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;
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;
analyse(fpin);
fclose(fpin);
}
实验记录
程序测试:
1、文件位置:f:\\11.txt
目标程序如下:
begin
x:=9
if x>0 then x:=x+1;
while a:=0 do
b:=2*x/3;
end;
2、运行结果:
实验总结
通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。以后我会更加专心的研究计算机知识,不断将现实中遇到的实际问题,向程序方面转变,做到灵活运用所学知识。

编译原理实验报告 词法分析

编译原理实验报告 词法分析

编译原理实验一·词法分析一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

二、实验内容及要求对某特定语言A ,构造其词法规则。

该语言的单词符号包括:保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表) 。

功能要求如下所示:·按单词符号出现的顺序,返回二元组序列,并输出。

·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。

·如果出现词法错误,报出:错误类型,位置(行,列)。

·处理段注释(/* */),行注释(//)。

·有段注释时仍可以正确指出词法错误位置(行,列)。

三、实验过程1、词法形式化描述使用正则文法进行描述,则可以得到如下的正规式:其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。

A→(ID | NUM | RES | DEL | OPR) *ID→letter(letter | didit)*NUM→digit digit*letter→a | …| z | A | …| Zdigit→0 | …| 9RES→program | begin | end | var | int | and | or | not | if | then | else | while | doDEL→( | ) | . | ; | ,OPR→+ | * | := | > | < | = | >= | <= | <>如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。

空格由空白、制表符和换行符组成。

2、单词种别定义;3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、运行环境介绍;本次实验采用win-tc进行代码的编写和编译及运行程序的运行环境为windows5、关键算法的流程图及文字解释;程序中用到的函数列表:变量ch储存当前最新读进的字符的地址strToken存放当前字符串voidmain() //主函数struct binary *lexicalAnalyze(); //词法分析的主函数,返回一个二元组的指针void GetBC(); //检查ch指向的字符是否为空格、制表或回车符,如果是则调用GetChar()直至不是上述字符void GetChar(); //ch前移一个地址单元int ConCat(); //将ch指向的字符连接到strToken之后int isLetter(); //判断ch指向的字符是否字母int isDigit(); //判断ch指向的字符是否数字int insertId(); //向标识符表中插入当前strToken的字符串int insertConst(); //将strToken的常数插入常数表中int Reserved(); //检测当前strToken中的字符串是否保留字,若是,则返回编码,否则返回0int isId(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回其编号,否则返回0int isConst(); //检测当前strToken中的字符串是否在常数表中已存在,若是,则返回其编号,否则返回0void errProc(int errType); //出错处理过程,errType是错误类型,将错误信息加入错误表中main()函数的流程图如下:lexicalAnalyze()函数的流程图如下所示:Reserved()、isId()和isConst()函数均采用了对链表的遍历算法,errProc()函数通过识别不同的错误编号,向错误链表中添加相应的错误信息。

《编译原理》词法分析程序设计方案

《编译原理》词法分析程序设计方案

实验1-4 《编译原理》S语言词法分析程序设计方案一、实验目的了解词法分析程序的两种设计方法:1.根据状态转换图直接编程的方式;2.利用DFA 编写通用的词法分析程序。

二、实验内容1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。

在此,词法分析程序作为单独的一遍,如下图所示。

具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。

将错误信息输出到屏幕上。

(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。

标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。

常量表结构:常量名,常量值2.编写DFA模拟程序算法如下:DFA(S=S0,MOVE[][],F[],ALPHABET[])/*S为状态,初值为DFA的初态,MOVE[][]为状态转换矩阵,F[] 为终态集,ALPHABET[] 为字母表,其中的字母顺序与MOVE[][] 中列标题的字母顺序一致。

*/{Char Wordbuffer[10]=“”//单词缓冲区置空Nextchar=getchar();//读i=0;while(nextchar!=NULL)//NULL代表此类单词{ if (nextcha r!∈ALPHABET[]){ERROR(“非法字符”),return(“非法字符”);}S=MOVE[S][nextchar] //下一状态if(S=NULL)return(“不接受”);//下一状态为空,不能识别,单词错误wordbuffer[i]=nextchar ;//保存单词符号i++;nextchar=getchar();}Wordbuffer[i]=‘\0’;If(S∈F)return(wordbuffer);//接受Else return(“不接受”);}该算法要求:实现DFA算法,给定一个DFA(初态、状态转换矩阵、终态集、字母表),调用DFA(),识别给定源程序中的单词,查看结果是否正确。

编译原理实验一词法分析设计

编译原理实验一词法分析设计

实验1 词法分析设计一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用二、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、将标识符填写的相应符号表须提供给编译程序的以后各阶段使用。

3、根据测试数据进行测试。

测试实例应包括以下三个部分:全部合法的输入。

各种组合的非法输入。

由记号组成的句子。

4、词法分析程序设计要求输出形式:例:输入VC++语言的实例程序:If i=0 then n++;a﹤= 3b %);输出形式为:单词二元序列类型位置(行,列)(单词种别,单词属性)for (1,for ) 关键字(1,1)i ( 6,i ) 标识符(1,2)= ( 4,= ) 关系运算符(1,3)0 ( 5,0 ) 常数(1,4)then ( 1,then) 关键字(1,5)n (6,n ) 标识符(1,6)++ Error Error (1,7);( 2, ; ) 分界符(1,8)a (6,a ) 标识符(2,1)﹤= (4,<= ) 关系运算符(2,2)3b Error Error (2,4)% Error Error (2,4)) ( 2, ) ) 分界符(2,5);( 2, ; ) 分界符(2,6)三、实验内容用VC++/VB/JAV A 语言实现对 C 语言子集的源程序进行词法分析。

通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。

以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。

(2)统计行数和列数用于错误单词的定位。

(3)删除空格类字符,包括回车、制表符空格。

(4)按拼写单词,并用(内码,属性)二元式表示。

编译原理-实验一.词法分析程序

编译原理-实验一.词法分析程序

实验一.词法分析程序一.实验目的:1>通过设计和实现一个词法分析程序,加深对词法分析原理的理解;2>掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法;二.实验内容:1>编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

2>保留字:if、then、else、while、do;单词种别码为1;标识符;单词种别码为2;无符号整形数;单词种别码为3;运算符包括:+、-、*、/、=、<、>、<=、>=;单词种别码为4;分隔符包括:;、(、);单词种别码为5;if (a>10) then b = a + 20;(1,”if”)(5,”(”)(2,”a”)(4,”>”)(3,”10”)(5,”)”)(1,”then ”)(2,”b”)(4,”=”)(2,”a”)(4,”+”)(3,”20”)(5,”; ”)三.运行结果及代码:#include<stdio.h>#include<string.h>#include<iostream.h>char prog[80],token[8];char ch;int syn,p,q,m=0,n,sum=0;char *rwtab[5]={"else","if","then","while","do"};//种别码1char *operat[9]={"+","-","*","/",">","<",">=","<=","="};// 4int scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];//while(ch=='_')//ch=prog[p++];if((ch>='A'&&ch<='Z')||( ch>='a'&&ch<='z')){ m=0;while((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')/*||(ch>='0'&&ch<='9')*/){token[m++]=ch;//token[m++]=ch;ch=prog[p++];for(n=0;n<5;n++)if(strcmp(token,rwtab[n])==0)//111111111111111111111{syn=1;//syn=n+1;token[m++]='\0';p--;return 0;}}token[m++]='\0';p--;syn=2;//syn=10;//22222222222222222222222222222222222222222return 0;}if((ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch=='=')||(ch=='>=')||(ch=='<=')||ch=='<'||ch=='>') {syn=4;token[0]=ch;token[1]='\0';return 0;}else if(ch>='0'&&ch<='9'){ sum=0;while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=3;//syn=11;}/*elseif(ch=='*')syn=13;else if(ch=='/')syn=14;else if(ch=='+')syn=15;else if(ch=='-')syn=16;else if(ch=='>'){ch=prog[p++];if(ch=='=') syn=24;else syn=20;}else if(ch==':'){ch=prog[p++];if(ch=='=') syn=18;else syn=17;}else if(ch=='<'){ch=prog[p++];if(ch=='=') syn=22;else if(ch=='>') syn=21;else syn=23;}else if(ch=='=')syn=25;*/else if(ch==';' ||ch=='('||ch==')')syn=5;else if(ch=='#')syn=0;return 0;}int main(){p=0;cout<<"词法分析\n 请输入源程序: \n";do {cin>>ch;prog[p++]=ch;}while(ch!='#');q=p;p=0;do{scaner();switch(syn){ case 3: cout<<"(3,"<<sum<<")\n";break;case -1: cout<<"error!"; break;case 4: cout<<"(4,"<<ch<<")"<<endl;break;case 5:cout<<"(5,"<<ch<<")\n";break;case 0:cout<<"(0,#)"<<endl;break;default: cout<<"("<<syn<<","<<token<<")\n";}}while (syn!=0);return 0;}四.心得与体会:通过本次实验,对词法分析原理有了更深层次的理解,掌握了程序设计语言源程序进行扫描过程中为其分解为各类单词的词法分析方法,提高了动手能力,虽然在实验过程中遇到了一些问题,经过同学的帮助,得以解决。

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

实验1-3 《编译原理》S语言词法分析程序设计方案一、实验目的了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式;二、实验内容ﻩ1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。

在此,词法分析程序作为单独的一遍,如下图所示。

具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。

将错误信息输出到屏幕上。

(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。

标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。

常量表结构:常量名,常量值三、实验要求1.能对任何S语言源程序进行分析ﻩ在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。

2.能检查并处理某些词法分析错误词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。

本实验要求处理以下两种错误(编号分别为1,2):1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。

2:源程序文件结束而注释未结束。

注释格式为:/* …… */四、保留字和特殊符号表单词的构词规则:字母=[A-Za-z]数字=[0-9]标识符=(字母|_)(字母|数字)*数字=数字(数字)*(.数字+| )四、S语言表达式和语句说明ﻩ1.算术表达式:+、-、*、/、%ﻩ2.关系运算符:>、>=、<、<=、==、!=3.赋值运算符:=,+=、-=、*=、/=、%=ﻩ4.变量说明:类型标识符变量名表;5.类型标识符:int char floatﻩ6.If语句:if表达式then 语句[else语句] ﻩ7.For语句:for(表达式1;表达式2;表达式3) 语句ﻩ8.While语句:while表达式do 语句9.S语言程序:由函数构成,函数不能嵌套定义。

函数格式为:返回值函数名(参数){数据说明语句}五、程序参考结构说明ﻩ1.Initscanner函数:程序初始化:输入并打开源程序文件和目标程序文件,初始化保留字表2.Scanner函数:若文件未结束,反复调用lexscan函数识别单词。

3.Lexscan函数:根据读入的单词的第一个字符确定调用不同的单词识别函数4.Isalpha函数:识别保留字和标识符5.Isnumber函数:识别整数,如有精力,可加入识别实数部分工功能6.Isanotation函数:处理除号/和注释7.Isother函数识别其他特殊字符8.Output函数:输出单词的二元式到目标文件,输出格式(单词助记符,单词内码值),如(int,-)(rlop,>)……9.Error函数:输出错误信息到屏幕10.除此之外,还可以设置查符号表,填写符号表等函数,学生可自行设计。

实验中,可以将某些类型的单词识别过程利用DFA算法实现,DFA算法参考如下: DFA(S=S0,MOVE[][],F[],ALPHABET[],ALLS[])/*S为状态,初值为DFA的初态,MOVE[][]为状态转换矩阵,F[]为终态集,ALPHABET [] 为字母表,其中的字母顺序与MOVE[][]中列标题的字母顺序一致。

ALLS[]为状态集*/{Char Wordbuffer[10]=“”//单词缓冲区置空Nextchar=getchar();//读字符i=0;while(nextchar!=NULL)//NULL代表此类单词{ if (nextchar!∈ALPHABET[]) {ERROR(“非法字符”),return(“非法字符”);} S=MOVE[S][nextchar]//下一状态if(S=NULL)return(“不接受”);//下一状态为空,不能识别,单词错误wordbuffer[i]=nextchar ;//保存单词符号i++;nextchar=getchar();}Wordbuffer[i]=‘\0’;If(S∈F)return(wordbuffer); //接受Else return(“不接受”);}六、实验过程说明1.每人单独完成。

2.完成后,由老师验收,并给出成绩。

3.实验完成后,写出实验报告(要求交打印稿)。

报告内容要求如下:七、测试源程序示例://aa.cvoid aa(){float rate,circle;rate=3;circle=3.14*rate*rate;}输出结果:(1)输出结果文件:(void,-)(id, 0) ((,-) (),-) ({,- )( float,-)(id,1)……(2)标识符的符号表:Name type address12345(3)常数表:e123实验地点:教10五楼计算机学院软一机房实验时间:第4周周二3单元、周四1单元、第五周周二3单元八、实验代码#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<string.h>#define MAX10//保留字符号长度#define MAXSIZE 45//保留字和特殊符号表长度#define NUM30//标识符和常数的个数FILE *in,*out;//指向文件的指针char infile[MAX];//文件名字char token[MAX];char Word[NUM][MAX];//标识符char consts[NUM][MAX];//常数char lownum[NUM][MAX]={"0","1","2","3","4","5","6","7","8","9",ﻩﻩﻩ"10","11","12","13","14","15","16","17","18","19"ﻩ"20","21","22","23","24","25","26","27","28","29"}; //自定义表int n=1;//行号int num=0;//错误统计数typedefstructKey_word//保留字和特殊符号表结构{ﻩ//intkeyNum;charkeyWord[MAX];char keySign[MAX];ﻩchar keyValue[MAX];}Key_word;//初始化保留字表Key_word Key[MAXSIZE]={{"int","int","-"},{"char","char","-"},{"float","float","-"},ﻩﻩﻩﻩ{"void","void","-"},{"const","const","-"},{"for","for","-"}, ﻩ{"if","if","-"},{"else","else","-"},{"then","then","-"},ﻩﻩﻩ{"while","while","-"},{"switch","switch","-"},{"break","break","-"}, ﻩﻩﻩ{"begin","begin","-"},{"end","end","-"},{"","",""},ﻩﻩﻩ{"","",""},{"","id",""},{"","num",""},ﻩﻩ{"+","+","-"},{"-","-","-"},{"*","*","-"},ﻩﻩﻩﻩ{"/","/","-"},{"%","%","-"},{"(","(","-"},ﻩ{")",")","-"},{"[","[","-"},{"]","]","-"},ﻩﻩﻩﻩﻩ{"","",""},{"<","rlop","<"},{">","rlop",">"},ﻩﻩﻩ{"<=","rlop","<="},{">=","rlop",">="},{"=","rlop","="}, ﻩﻩﻩﻩ{"!=","rlop","!="},{";",";","-"},{"","",""},ﻩﻩﻩ{"/=","/=","-"},{"+=","+=","-"},{"-=","-=","-"},ﻩ{"*=","*=","-"},{"%=","%=","-"},{"||","or","-"},ﻩﻩﻩ{"&&","and","-"},{"!","not","-"},{"=","=","-"}};//打开关闭文件intInitscanner(){printf("请输入要输入的文件:\n");scanf("%s",infile);if((in=fopen(infile,"r"))==NULL)ﻩ{ﻩprintf("cannot openinfile!\n");ﻩreturn 0;ﻩ}if((out=fopen("word.txt","a+"))==NULL)ﻩ{ﻩprintf("cannot open outfile!\n");ﻩreturn 0;ﻩ}return0;}//写入文件void Output(int n,intm){ﻩfputs("(",out);ﻩfputs(Key[n].keySign,out);fputs(",",out);ﻩif(m==-1)ﻩfputs(Key[n].keyValue,out);ﻩelseﻩfputs(lownum[m],out);//下标fputs(")",out);}//Isalpha函数:识别保留字和标识符intIsalpha(){ﻩinti;for(i=0;i<16;i++)//关键字{ﻩﻩif(strcmp(token,Key[i].keyWord)==0){ﻩOutput(i,-1);ﻩreturn0;ﻩﻩ}}ﻩ//标识符Word[NUM][MAX]ﻩfor(i=0;i<NUM;i++){ﻩif((Word[i][0]!=NULL)&&strcmp(token,Word[i])==0)ﻩ{ﻩﻩOutput(16,i);ﻩﻩreturn0;ﻩ}ﻩif(Word[i][0]==NULL){ﻩﻩstrcpy(Word[i],token);ﻩOutput(16,i);ﻩﻩﻩreturn 0;ﻩﻩ}}return 0;}int Isnumber()//Isnumber函数:consts[NUM][MAX]{int i;for(i=0;i<NUM;i++){if((consts[i][0]!=NULL)&&strcmp(token,consts[i])==0) ﻩﻩ{ﻩﻩOutput(17,i);return 0;}if(consts[i][0]==NULL)ﻩ{strcpy(consts[i],token);ﻩﻩOutput(17,i);ﻩreturn0;}ﻩ}ﻩreturn 0;}void remove()//扫描指针回退一个字符{fseek(in,-1,SEEK_CUR);}//Isanotation函数:处理除号/和注释void Isanotation()//提示第一个字符已经存为/了{ﻩcharch,pre;ﻩch=getc(in);ﻩif(ch=='=')//"/="Output(36,-1);elseif(ch=='*')//"/*"{ﻩﻩch=getc(in);ﻩdo{if(feof(in))ﻩﻩ{ﻩﻩﻩnum++;ﻩprintf("\n第(%d)行: 注释错误: /*后面的字符全部当做注释,缺少结束注释*/\n",n);ﻩﻩﻩbreak;ﻩﻩ}ﻩpre=ch;ﻩch=getc(in);ﻩﻩ}while(pre!='*'||ch!='/');}ﻩelse//"/"ﻩ{ﻩremove(); //指针回退一个字符Output(21,-1);}//Isother函数识别其他特殊字符void Isother(){ﻩint i=1;intj=0;ﻩcharch;ﻩif(token[0]=='<'||token[0]=='>'||token[0]=='!'||token[0]=='%') {ﻩch=getc(in);ﻩif(ch=='=')ﻩtoken[i++]=ch;elseremove();ﻩ}elseﻩif(token[0]=='|'){ch=getc(in);ﻩﻩif(ch=='|')ﻩtoken[i++]=ch;ﻩﻩelseﻩremove();}elseﻩif(token[0]=='&'){ﻩch=getc(in);ﻩif(ch=='&')ﻩﻩﻩtoken[i++]=ch;elseﻩﻩﻩremove();}token[i]='\0';for(i=18;i<45;i++)ﻩ{if(strcmp(token,Key[i].keyWord)==0)ﻩﻩ{Output(i,-1);break;ﻩﻩ}}if(i==45)ﻩ{ﻩnum++;printf("\n第(%d)行:字符错误: %s字符非法\n",n,token);}voidScanner(){char ch;int i;ch=getc(in);while(!feof(in))ﻩ{ﻩﻩwhile(ch==' '||ch=='\t'||ch=='\n') //先统计行数ﻩﻩ{ﻩif(ch=='\n')ﻩﻩ++n;ﻩﻩch=getc(in);ﻩ}ﻩif(((ch>='a')&&(ch<='z'))||(ch=='_'))//标识符isalpha(ch)单词ﻩﻩ{ﻩﻩi=1;ﻩtoken[0]=ch;ﻩﻩﻩch=getc(in);ﻩﻩwhile(((ch>='a')&&(ch<='z'))||((ch>='0')&&(ch<='9')))//word number ﻩ{ﻩﻩﻩtoken[i++]=ch;ﻩﻩch=getc(in);ﻩ}ﻩtoken[i]='\0';ﻩIsalpha();ﻩ}else if((ch>='0')&&(ch<='9'))//整数ﻩ{ﻩi=1;ﻩtoken[0]=ch;ﻩﻩch=getc(in);ﻩﻩﻩwhile(isdigit(ch))ﻩ{ﻩtoken[i++]=ch;ﻩﻩch=getc(in);ﻩ}token[i]='\0';ﻩIsnumber();ﻩ}ﻩﻩelse if(ch=='/')//区分"/" , "/=" , "/*"{ﻩﻩtoken[0]=ch;Isanotation();ﻩﻩch=getc(in);}ﻩﻩelse //特殊字符ﻩﻩ{token[0]=ch;Isother();ﻩﻩch=getc(in);ﻩ}}}voidshow(){inti;charch;printf("\n二元式:\n");ﻩrewind(out);while(!feof(out)){ﻩﻩprintf("%c",getc(out));ﻩ}ﻩprintf("\n标志符表\n");ﻩfor(i=0;i<NUM;i++){if(Word[i][0]!=NULL)ﻩprintf("%d,%s\n",i,Word[i]);}ﻩprintf("\n常数表\n");ﻩfor(i=0;i<NUM;i++){if(consts[i][0]!=NULL)printf("%d,%s\n",i,consts[i]); ﻩ}}void main(){ﻩInitscanner();Scanner();ﻩprintf("\n共有%d个错误\n",num); ﻩshow();ﻩfclose(in);ﻩfclose(out);}九、实验结果输入文件void aa()beginfloat rate,circle; rate=3;circle=3.14*rate;/******/ end输出文件(void,-)(id,0)((,-) (),-)(begin,-) (float,-) (id,1)(id,2)(;,-)(id,1) (rlop,=) (num,0) (;,-)(id,2)(rlop,=)(num,0)(num,1)(*,-)(id,1)(;,-)(end,-)十、实验总结经过此次实验,了解了程序的词法构词规则和词法分析过程。

相关文档
最新文档