词法分析报告

词法分析报告
词法分析报告

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

指导教师:

姓名:

学号:

班级:

一、实验目的

基本掌握计算机语言的词法分析程序的开发方法。

二、实验内容

编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。三、实验要求

1.根据以下的正规式,编制正规文法,画出状态图;

标识符<字母>(<字母>|<数字字符>)*

十进制整数0 | (1|2|3|4|5|6|7|8|9) (0|1|2|3|4|5|6|7|8|9)*

八进制整数0 (0|1|2|3|4|5|6|7) (0|1|2|3|4|5|6|7)*

十六进制整数0 (x|X) (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 do

2.根据状态图,设计词法分析函数int scan( ),完成以下功能:

(1)从输入流(键盘或文件)读入数据,分析出一个单词。

(2)返回单词种别(用整数表示),

(3)返回单词属性(不同的属性可以放在不同的全局变量中)。

3.编写测试程序,循环调用函数scan( ),每次调用,获得一个单词的信息。在测试程序中,打印输出单词种别、属性(注意:不要在词法分析函数

scan 中打印输出!)。

四、实验环境

微型计算机。

Windows 操作系统/Linux 操作系统。

编程语言:C/C++/Java/C#。建议使用Visual C++/Netbeans/Eclipse 集成开发环境。

五、实验步骤

1. 根据状态图,设计词法分析算法

2. 设计函数scan( ),实现该算法

3. 编制测试程序(在本试验中,可以是主函数main( ) )。

4. 调试程序:输入一组单词,检查输出结果。

六、状态图

七. 测试数据:0 92+data> 0x3f

00 while

八.测试结果

九,思考题

1.词法分析能否采用空格来区分单词?

答:不能,因为比如abc+bcd中没有空格,但这是三个单词。

2.程序设计中哪些环节影响词法分析的效率?如何提高效率?

答:整个程序都由状态转换图而来。由递归方法实现的状态转换图,影响了整个词法分析器的分析效率,可以考虑使用栈来非递归的实现词法分析。

十.实验心得

通过词法分析程序的实现,我理解了计算机是怎么去识别一个个单词的,或者可以说是各种命令的。这次实验使我对c语言中文件操作更加了解,了解文件指针的运行情况,还了解了编译原理中有限自动机的概念,根据状态图写程序。

十一.源代码

#include

using namespace std;

#include

#define ASG 1

#define ADD 2

#define SUB 3

#define MUL 4

#define DIV 5

#define ID 6

#define IF 7

#define THEN 8

#define WHILE 9

#define DO 10

#define INT8 11 //八进制

#define INT10 12 //十进制

#define INT16 13

#define SLP 14 //左括号(

#define SRP 15 //右括号)

#define SEMI 16 //分号;

#define LP 17 //左花括号{

#define RP 18 //右花括号}

#define INC 19 //++

#define DECC 20 //--

#define NEQ 21 //不等于

#define EQ 22 //等于

#define JAE 23 //大于等于

#define JA 24 //大于

#define JBE 25 //小于等于

#define JB 26 //小于

struct word

{

int kind;

int value;

};

int fpoint; //文件字符指针

int num_token; //一个单词中的字符数量,主要是数字长度

char *token;

fstream file; //所要读取的文件

word handle_identifier(char *ch) //处理标识符(包括关键字){

struct word re; //返回值

//////////////////////////关键字///////////////////////////

if(strcmp(ch,"if")==0)

{

re.kind=IF;

re.value=0;

return re;

}

if(strcmp(ch,"then")==0)

{

re.kind=THEN;

re.value=0;

return re;

}

if(strcmp(ch,"while")==0)

{

re.kind=WHILE;

re.value=0;

return re;

}

if(strcmp(ch,"do")==0)

{

re.kind=DO;

re.value=0;

return re;

}

//////////////////////////标识符///////////////////////////

re.kind=ID;

re.value=0;

return re;

}

int convert(char ch) //将字符转换成数字

{

int number;

switch(ch)

{

case'0': number=0;break;

case'1': number=1;break;

case'2': number=2;break;

case'3': number=3;break;

case'4': number=4;break;

case'5': number=5;break;

case'6': number=6;break;

case'7': number=7;break;

case'8': number=8;break;

case'9': number=9;break;

case'A': number=10;break;

case'a': number=10;break;

case'B': number=11;break;

case'b': number=11;break;

case'C': number=12;break;

case'c': number=12;break;

case'D': number=13;break;

case'd': number=13;break;

case'E': number=14;break;

case'e': number=14;break;

case'F': number=15;break;

case'f': number=15;break;

default: number=-1;break; //非法字符转换成-1 }

return number;

}

word handle_number(char *ch,int TN) //处理无符号整数{

int i,j;

int number; //对应每一位上转换后的数字int dec=0,oct=0,hex=0; //最终的数值,三种进制

word re; //返回值

if(TN==1) //一位数,只能是十进制

{

number=convert(ch[0]);

if(number==-1||number>9) cout<<"Error!";

else

{

re.kind=INT10;

re.value=number;

return re;

}

}

if( (TN==2)&&(ch[0]=='0') ) //两位数,八进制

{

number=convert(ch[1]);

if( (number>=0)&&(number<=7) )

{

re.kind=INT8;

re.value=number;

return re;

}

else cout<<"Error!八进制非法"; //报错

}

if( (TN>=2)&&(ch[0]!='0') ) //两位位数(含)以上,十进制{

int *num=new int[TN];

for(i=0;i

{

number=convert(ch[i]);

num[i]=number;

if( (number==-1)||(number>9) ) cout<<"Error!十进制非法"; //报错}

for(i=0;i

{

for(j=TN-i-1;j>0;j--)

num[i]*=10;

dec+=num[i];

}

re.kind=INT10;

re.value=dec;

return re;

}

else if( (TN>=3)&&(ch[0]=='0')&&(ch[1]!='x')&&(ch[1]!='X') ) //三位数(含)以上,八进制

{

int *num=new int[TN-1];

for(i=1;i

{

number=convert(ch[i]);

num[i]=number;

if( (number==-1)||(number>7) ) cout<<"Error!八进制非法"; //报错}

for(i=1;i

{

for(j=TN-i-1;j>0;j--)

num[i]*=8;

oct+=num[i];

}

re.kind=INT8;

re.value=oct;

return re;

}

else if( (TN>=3)&&(ch[0]=='0')&&((ch[1]=='x')||(ch[1]=='X')) ) //三位数(含)以上,十六进制

{

int *num=new int[TN-2];

for(i=2;i

{

number=convert(ch[i]);

num[i]=number;

if(number==-1) cout<<"Error!十六进制非法"; //报错

}

for(i=2;i

{

for(j=TN-i-1;j>0;j--)

num[i]*=16;

hex+=num[i];

}

re.kind=INT16;

re.value=hex;

return re;

}

}

word scan(char ch)

{

word re; //返回值

while(ch==' '||ch=='\n') //空格或回车

{

fpoint++;

if(ch=='\n') fpoint++; // \n包括回车和换行所以再加1

file.get(ch);

}

num_token=0; //每次要分析一个单词的时候,都要重新对单词中的字符计数token[num_token]=ch; //单词开始的一个字符都放到存放单词的数组中

token[num_token+1]='\0';

num_token++;

if(isalpha(ch)) //第一个字符是字母的单词是标识符{

file.get(ch);

fpoint++;

while(isalnum(ch)&&!file.eof()) //读取标识符的所有字母和数字

{

token[num_token]=ch;token[num_token+1]='\0';

num_token++;

file.get(ch);

fpoint++;

}

fpoint--;

file.seekg(fpoint,ios::beg); //后退

re=handle_identifier(token); //处理标识符

return re; //返回单词信息(种别和属性值)

}

else if(isdigit(ch)) //第一个字符是数字的单词是整数{

file.get(ch);

fpoint++;

while(isalnum(ch)&&!file.eof()) //十六进制中包含字母x和X,所以整数单词中不一定只包含数字

{

token[num_token]=ch; token[num_token+1]='\0';

num_token++;

file.get(ch);

fpoint++;

}

fpoint--;

file.seekg(fpoint,ios::beg); //后退

re=handle_number(token,num_token);

return re;

}

else

switch(ch)

{

case ':': //赋值符号

file.get(ch);

fpoint++;

if(ch =='=') //以“:”开头的单词只能是赋值符号,否则出错

{

re.kind=ASG;

re.value=0;

return re;

}

else cout<<"Error!赋值出错"; //报错

break;

///////////////////////////各种运算符///////////////////////////////

case'+':

file.get(ch);

fpoint++;

if(ch=='+')

{

re.kind=INC;

re.value=0;

return re;

}

else

{

fpoint--;

file.seekg(fpoint,ios::beg); //后退

re.kind=ADD;

re.value=0;

return re;

}

break;

case'-':

file.get(ch);

fpoint++;

if(ch=='-')

{

re.kind=DECC;

re.value=0;

return re;;

}

else

{

fpoint--;

file.seekg(fpoint,ios::beg); //后退

re.kind=SUB;

re.value=0;

return re;

}

break;

case'*':

re.kind=MUL;

re.value=0;

return re ; break;

case'/':

re.kind=DIV;

re.value=0;

return re; break;

case'!': //不等号

file.get(ch);

fpoint++;

if(ch=='=') //以“!”开头的单词只能是不等号,否则出错

{

re.kind=NEQ;

re.value=0;

return re;

}

else cout<<"Error!"; //报错

break;

case'=': //等号

file.get(ch);

fpoint++;

if(ch=='=') //以“=”开头的单词只能是等号,否则出错

{

re.kind=EQ;

re.value=0;

return re;

}

else cout<<"Error!"; //报错

break;

case'>':

file.get(ch);

fpoint++;

if(ch=='=')

{

re.kind=JAE;

re.value=0;

return re;

}

else

{

fpoint--;

file.seekg(fpoint,ios::beg); //后退

re.kind=JA;

re.value=0;

return re;

}

break;

case'<':

file.get(ch);

fpoint++;

if(ch=='=')

{

re.kind=JBE;

re.value=0;

return re;

}

else

{

fpoint--;

file.seekg(fpoint,ios::beg); //后退

re.kind=JB;

re.value=0;

return re;

}

break;

case'(':

re.kind=SLP;

re.value=0;

return re; break;

case')':

re.kind=SRP;

re.value=0;

return re; break;

case'{':

re.kind=LP;

re.value=0;

return re; break;

case'}':

re.kind=RP;

re.value=0;

return re; break;

case';':

re.kind=SEMI;

re.value=0;

return re; break;

///////////////////////不是该语言所能识别的单词////////////////////////////

default:

cout<<"Error!"; //报错

}//end switch

}

////////////////////////////主程序////////////////////////////////////////

void main()

{

char ch;

word reword; //接收词法分析程序返回的单词

fpoint=0; //记录当前字符的位置,用于回退num_token=0; //记录一个单词中的字符数量

token=new char[30]; //存放每个单词

file.open("word.txt");

cout<<"\n词法程序分析结果:"<

while(1)

{

file.get(ch);

fpoint++;

if(file.eof()!=0) break;

reword=scan(ch);

if(reword.kind!=0){

switch(reword.kind)

{

case 1: cout<<"< ASG ";break;

case 2: cout<<"< ADD ";break;

case 3: cout<<"< SUB ";break;

case 4: cout<<"< MUL ";break;

case 5: cout<<"< DIV ";break;

case 6: cout<<"< ID ";break;

case 7: cout<<"< IF ";break;

case 8: cout<<"< THEN ";break;

case 9: cout<<"< WHILE ";break;

case 10: cout<<"< DO ";break;

case 11: cout<<"< INT8 ";break;

case 12: cout<<"< INT10 ";break;

case 13: cout<<"< INT16 ";break;

case 14: cout<<"< SLP ";break;

case 15: cout<<"< SRP ";break;

case 16: cout<<"< SEMI ";break;

case 17: cout<<"< LP ";break;

case 18: cout<<"< RP ";break;

case 19: cout<<"< INC ";break;

case 20: cout<<"< DECC ";break;

case 21: cout<<"< NEQ ";break;

case 22: cout<<"< DEQ ";break;

case 23: cout<<"< JAE ";break;

case 24: cout<<"< JA ";break;

case 25: cout<<"< JBE ";break;

case 26: cout<<"< JB ";break;

default: cout<<"< 非法标识";break;

}

if(reword.kind!=6)

if(reword.kind==13||reword.kind==12||reword.kind==11) cout<"<

else cout<<"_ >"<

else{

do{

cout<<*token;

token++;

}while(*token!='\0'); //输出标示符

cout<<" >"<

}

}

}

file.close();

system("pause");

}

词法分析报告程序设计与实现

实验一词法分析程序设计与实现 一、实验目的及内容 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、实验原理(状态转换图) 1、C语言子集 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符: := + – * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码

3、词法分析程序的功能 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 二、软件平台及工具 PC机以及VISUAL C++6.0软件。 三、实验方法、步骤(或:程序代码或操作过程)(1)程序代码: #include #include #include char prog[80],token[8]; char ch; int syn,p,m=0,n,row,sum=0; char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner() { for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; while(ch==' ') { ch=prog[p]; p++; }

词法分析小结

词法分析小结 词法分析是编译器工作的第一阶段,它的工作就是从输入(源代码)中取得token,以作为parser(语法分析)的输入,一般在词法分析阶段都会把一些无用的空白字符(whitespace,即空格、tab和换行)以及注释剔除,以降低下一步分析的复杂度,词法分析器一般会提供一个gettoken()这样的方法,parser可以在做语法分析时调用词法分析器的这个方法来得到下一个token,所以词法分析器并不是一次性遍历所有源代码,而是采取这种on-demand的方式:只在parser需要时才工作,并且每次只取一个token。 token和lexeme 首先,token不等于lexeme。token和lexeme的关系就类似于面向对象语言中“类”和“实例”(或“对象”)之间的关系,这个用中文不知该如何解释才好,比如语言中的变量a和b,它们都属于同一种token:identifier,而a的lexeme是”a”,b则是”b”,而每个关键字都是一种token。token可以附带有一个值属性,例如变量a,当调用词法分析器的gettoken()时,会返回一个identifier类型的token,这个token带有一个属性“a”,属性可以是多样的,例如表示数字的token

可以带有一个表示数字值的属性,它是整型的。 如下代码: intage=23; intcount=50; 可以依次提取出8个token:int(值为”int”),id(值为”age”),assign(值为”=”),number(值为整型数值23),int(值为”int”),id(值为”count”),assign(值为”=”),number(值为50) 正则表达式 正则表达式可以用来描述字符串模式,例如我们可以用digit+来表示number的token,其中digit表示单个数字(这里说正则表达式并不完全和实现的正则引擎所识别的正则表达式等价,这里只是为了描述问题而已)。 然而像c语言的的多行注释,用正则表达式来描述就比较麻烦,此时更倾向于直接用有穷自动机(finiteautomaton)来描述,因为用它来描述非常直观且很容易。

编译原理实验报告实验一编写词法分析程序

编译原理实验报告实验名称:实验一编写词法分析程序 实验类型:验证型实验 指导教师:何中胜 专业班级:13软件四 姓名:丁越 学号: 电子邮箱: 实验地点:秋白楼B720 实验成绩: 日期:2016年3 月18 日

一、实验目的 通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析 程序所用的工具自动机,进一步理解自动机理论。掌握文法转换成自动机的技术及有穷自动机实现的方法。确定词法分析器的输出形式及标识符与关键字的区分方法。加深对课堂教学的理解;提高词法分析方法的实践能力。通过本实验,应达到以下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、实验过程 以编写PASCAL子集的词法分析程序为例 1.理论部分 (1)主程序设计考虑 主程序的说明部分为各种表格和变量安排空间。 数组 k为关键字表,每个数组元素存放一个关键字。采用定长的方式,较短的关键字 后面补空格。 P数组存放分界符。为了简单起见,分界符、算术运算符和关系运算符都放在 p表中 (编程时,还应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。 id和ci数组分别存放标识符和常数。 instring数组为输入源程序的单词缓存。 outtoken记录为输出内部表示缓存。 还有一些为造表填表设置的变量。 主程序开始后,先以人工方式输入关键字,造 k表;再输入分界符等造p表。 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上 送来的一个单词;调用词法分析过程;输出每个单词的内部码。 ⑵词法分析过程考虑 将词法分析程序设计成独立一遍扫描源程序的结构。其流程图见图1-1。 图1-1 该过程取名为 lexical,它根据输入单词的第一个字符(有时还需读第二个字符),判断单词类,产生类号:以字符 k表示关键字;i表示标识符;c表示常数;p表示分界符;s表示运算符(编程时类号分别为 1,2,3,4,5)。 对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有 该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id中,将常数 变为二进制形式存入数组中 ci中,并记录其在表中的位置。 lexical过程中嵌有两个小过程:一个名为getchar,其功能为从instring中按顺序取出一个字符,并将其指针pint加1;另一个名为error,当出现错误时,调用这个过程, 输出错误编号。 2.实践部分

编译原理词法分析报告

1、实验目的 1、为初等函数运算语言构造词法分析器。 2、掌握生成词法分析器的方法,加深对词法分析原理的理解。 3、掌握设计、编制并调试词法分析程序的思想和方法 2、实验内容 一、根据下面的要求设计初等函数运算语言的词法模式,并用正则式表达出来 1、初等函数运算语言的常量为实数类型,其定义方式为实数的最一般书写方式,如: 123.321。具体要求:不支持整数部分大于。时首数字为0;不支持小数点后结尾为 0;不支持科学记数法;不支持仅为整数时有小数点;支持负数符号,不支持正数 符号。 2、初等函数运算语言的变量采用与C语言的标识符定义一样的方式:首字符为字母或 下划线;其他的为字母、数字及下划线的混合串;区分大小写;变量长度不超过32 个字符。 3、初等函数运算语言需要处理的函数仅为表一中所列举的内容。函数的格式及参数内 容也如表一所示。 4、初等函数运算语言支持四则运算,其计算的符号与C语言相同,为:+-*/。 5、初等函数运算语言的合法的分隔符包括:空格、制表符、、分行符圆括号(左、右)、 分号。其中空格、制表符、分行符可以出现在任何两个不同的单词中间;圆括号(左、右)用于表达式中,用于改变运算的优先级,以及标识函数的参数;分号用于标识一个语句的结束。 6、初等函数运算语言支持的常量还包括:PI,Eo其中,PI为圆周率,E为自然常数。 二、将正则式转化为最小DFA,给出该DFA的形式化表示和图形表示。 三、根据DFA给出状态转换表。 四、给出初等函数运算语言的记号表,即词法分析中,语言中的记号将分为多少类,每一类型的编码、类型、属性等内容是什么。 五、编写词法分析器,将输入的字符串转化成为记号流,便于后续的语法分析工作。要求词法分析器中能够识别词法错误。

编译原理 简单样本语言的词法分析器

昆明理工大学信息工程与自动化学院学生实验报告 (2012 —2013 学年第 1 学期) 课程名称:编译原理开课实验室:信自楼44 年月日 一、实验目的及内容 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。 二、实验原理及基本技术路线图(方框原理图或程序流程图) 对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。 三、所用仪器、材料(设备名称、型号、规格等或使用软件) W INDOWS下的VISUAL C++6.0; 四、实验方法、步骤(或:程序代码或操作过程) #include #include using namespace std;

#define MAX 22 char 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='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<

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

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

实验一词法分析实验报告

实验一词法分析 一、实验目的 通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示) 二、实验要求 使用一符一种的分法 关键字、运算符和分界符可以每一个均为一种 标识符和常数仍然一类一种 三、实验内容 功能描述: 1、待分析的简单语言的词法 (1)关键字: begin if then while do end (2)运算符和界符: := + –* / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义: ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码 图 1

程序结构描述: 图 2 四、实验结果 输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图3所示:

图3 输入private x:=9;if x>0 then x:=2*x+1/3; end#后经词法分析输出如下序列:(private 10)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图4所示: 图4 显然,private是关键字,却被识别成了标示符,这是因为图1中没有定义private关键字的种别码,所以把private当成了标示符。 输入private x:=9;if x>0 then x:=2*x+1/3; @ end#后经词法分析输出如下序列:(private 10)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5所示

编译原理词法分析和语法分析报告+代码(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 各种单词符号对应的种别码: 输入:所给文法的源程序字符串。 输出:二元组(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)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图: 主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,}; 图3-1 (2)程序中需要用到的主要变量为syn,token和sum 3.2 扫描子程序的算法思想: 首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

词法分析器实验报告

词法分析器实验报告 词法分析器设计 一、实验目的: 对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状 态转换图设计词法分析器的基本方法。利用该词法分析器完成对源程 序字符串的词法分析。输出形式是源程序的单词符号二元式的代码, 并保存到文件中。 二、实验内容: 1. 设计原理 词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。 理论基础:有限自动机、正规文法、正规式 词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序 2. 词法分析器的功能和输出形式 功能:输入源程序、输出单词符号 程序语言的单词符号一般分为以下五种:关键字、标识符、常数、运算符,界符 3. 输出的单词符号的表示形式: 单词种别用整数编码,关键字一字一种,标识符统归为一种,常数一种,各种符号各一种。 4. 词法分析器的结构 单词符号 5. 状态转换图实现

三、程序设计 1.总体模块设计 /*用来存储目标文件名*/ string file_name; /*提取文本文件中的信息。*/ string GetText(); /*获得一个单词符号,从位置i开始查找。并且有一个引用参数j,用来返回这个单词最后一个字符在str的位置。*/ string GetWord(string str,int i,int& j); /*这个函数用来除去字符串中连续的空格和换行 int DeleteNull(string str,int i); /*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/ bool IsBoundary(string str,int i); /*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/ bool IsOperation(string str,int i);

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

词法分析器实验报告 一、实验目的 选择一种编程语言实现简单的词法分析程序,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 : = + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 各种单词符号对应的种别码: 表各种单词符号对应的种别码 词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(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)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根

据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 主程序示意图: 主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,}; 图3-1 (2)程序中需要用到的主要变量为syn,token和sum 扫描子程序的算法思想: 首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn 用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

词法分析实验报告

词法分析器 一、实验目的: 通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 二、实验要求 如源程序为C语言。输入如下一段:Array main() { int a,b; a = 10; b = a + 20; }# 要求输出如右图。 要求: 1、将单词分为五种 识别关键字:main、if、int、for、while、do、return、break、continue; 单词种别码为1。 标识符;单词种别码为2。 常数为无符号整形数;单词种别码为3。 运算符包括:+、-、*、/、=、>、<、>=、<=、!= ; 单词种别码为4。 分隔符包括:,、;、{、}、(、);单词种别码为5。 2、使用一符一种的分法 关键字、运算符和分界符可以每一个均为一种 标识符和常数仍然一类一种 三、实验内容 1、功能描述 改程序是一个实现词法分析的功能,能识别5种单词,其他单词报错。 2、程序结构描述 int IsKey(char *Word)关键字匹配函数,查询是否为关键字,若是,返回值为1,否则为0。 int IsAlpha(char c) 查看是否为字母,若是,返回值为1,否则为0。 int IsNum(char c) 查看是否为数字,若是,返回值为1,否则为0。 void scanner(FILE *fp) 扫描函数,扫描程序中的字符串并调用上述三种函数检查是否是字母、 数字,是否是关键字,并输出。 fseek(fp,-1,1)回退一个字符。 fgetc(fp)从数据流中区下一个字符。 fopen 文件打开函数,返回指向文件第一个字符的指针 四、实验结果 测试内容为 main() {

编译原理实验报告一 简单样本语言的词法分析器

理工大学信息工程与自动化学院学生实验报告 (2012 —2013学年第一学期) 一、实验目的及容 编译技术是理论与实践并重的课程,而其实验课要综合运用所学的多门课程的容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、实验原理及基本技术路线图(框原理图或程序流程图) 1、待分析的简单语言的词法 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符: := + –* / < <= <> > >= = ; ( ) #

(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码 3、词法分析程序的功能 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 二、所用仪器、材料(设备名称、型号、规格等或使用软件)

1台PC以及VISUAL C++6.0软件。 三、实验法、步骤(或:程序代码或操作过程) (1)程序代码: #include #include #include char prog[80],token[8]; char ch; int syn,p,m=0,n,row,sum=0; char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner() { for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; while(ch==' ') { ch=prog[p]; p++; } if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) { m=0; while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) { token[m++]=ch; ch=prog[p++]; } token[m++]='\0'; p--; syn=10; for(n=0;n<6;n++)

编译原理词法分析和语法分析报告 代码(C语言版)

词法分析 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 3.1 主程序示意图: 扫描子程序主要部分流程图 其他

词法分析程序的C语言程序源代码: // 词法分析函数: void scan() // 数据传递: 形参fp接收指向文本文件头的文件指针; // 全局变量buffer与line对应保存源文件字符及其行号,char_num保存字符总数。 void scan() { char ch; int flag,j=0,i=-1; while(!feof(fp1)) { ch=fgetc(fp1); flag=judge(ch); printf("%c",ch);//显示打开的文件 if(flag==1||flag==2||flag==3) {i++;buffer[i]=ch;line[i]=row;} else if(flag==4) {i++;buffer[i]='?';line[i]=row;} else if(flag==5) {i++;buffer[i]='~';row++;} else if(flag==7) continue; else cout<<"\n请注意,第"<

东南大学编译原理词法分析器实验报告

词法分析设计 1. 实验目的 通过本实验的编程实践,了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。 2. 实验内容 用C++语言实现对C++语言子集的源程序进行词法分析。通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。 3. 实验原理 本次实验采用NFA->DFA->DFA0的过程: 对待分析的简单的词法(关键词/id/num/运算符/空白符等)先分别建立自己的FA,然后将他们用产生式连接起来并设置一个唯一的开始符,终结符不合并。 待分析的简单的词法 (1)关键字: "asm","auto","bool","break","case","catch","char","class","

const","const_cast"等 (2)界符(查表) ";",",","(",")","[","]","{","}" (3)运算符 "*","/","%","+","-","<<","=",">>","&","^","|","++","--"," +=","-=","*=","/=","%=","&=","^=","|=" relop: (4)其他单词是标识符(ID)和整型常数(SUM),通过正规式定义。 id/keywords: digit: (5)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

简单词法分析器

简单词法分析器 1、将源文件中的单词识别出来,以用'$'为首的标识符标记识别出的单词 2、单词符号及内部表示如表: 单词符号种别编码助记符内码值 DIM 1 $DOM — IF 2 $IF — DO 3 $DO — STOP 4 $STOP — END 5 $END — 标识符 6 $ID 内部字符串 常数7 $INT 标准二进制形式= 8 $ASSIGN — + 9 $PLUS — * 10 $STAR — ** 11 $POWER — ; 12 $SEMICOLON — { 13 $LBRACE — } 14 $RBRACE — /* * 词法分析:将源文件中的单词符号一一识别 * 并将其与助记符保存到文本文件 */ #include "iostream" #include "string" using namespace std; //reserve保留字 string reserve[5] = {"DIM","IF","DO","STOP","END"}; //结构体数组,保存已识别的单词 struct table { string str; string name; }table[400]; int count = 0; //判断是否为保留字

bool Reserve(string str) { bool flag = false; for(int i=0; i>filename; if((fp = fopen(filename,"r")) == NULL) { cout<<"file not found"<

词法分析课程设计

《词法分析》设计说明书 学生姓名 学 号 5011110122 5011110133 5011110128 所属学院 信息工程学院 专 业 计算机科学与技术 班 级 计算机15-1班 信息工程学院 《编译原理及实践》结课大作 业

摘要 编译,简单的说,就是把源程序转换为可执行程序。从hellow worl说程序运行机制里面简单的说明了程序运行的过程,以及一个程序是如何一步步变成可执行文件的。在这个过程中,编译器做了很多重要的工作。对于编译的内部实现,也就是编译的原理。 这篇论文主要说的是编译器前端,词法分析器的原理,最后会给出一个词法分析器的简单实现。 编译简单的说,就是把源程序转化为另一种形式的程序,而其中关键的部分就是理解源程序所要表达的意思,才能转化为另一种源程序。 可以用一个比喻来说明问题:人A和人B想要交谈,但是他们都不知道彼此的语言,这就需要一个翻译C,同时懂得A和B的语言。有了C做中间层,A和B才能正常交流。C的作用就有点像编译器,它必须能理解源程序所要表达的意思,才能把信息传递给另一个。编译器也一样,它的输入是语言的源文件(一般可以是文本文件)对于输入的文件,首先要分离出这个输入文件的每个元素(关键字、变量、符号、、),然后根据语言的文法,分析这些元素的组合是否合法,以及这些组合所表达的意思。 程序设计语言和自然语言不一样,都是用符号来描述,每个特定的符号表示特定的意思,而且程序设计语言是上下文无关的。上下文无关就是某一个特定语句所要表达的意思和它所处的上下文没有关系,只有它自身决定。 这篇论文主要说的就是词法分析,也就是把输入的符号串整理成特定的词素。 关键词:单片机;词法分析

编译原理词法分析器

一、实验目的 了解词法分析程序的两种设计方法: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’;

词法分析

词法分析器的实现 开篇 编译,简单的说,就是把源程序转换为可执行程序。从hello world 说程序运行机制里面简单的说明了程序运行的过程,以及一个程序是如何一步步变成可执行文件的。在这个过程中,编译器做了很多重要的工作。对底层该兴趣的我,自然的,也就迫切想搞清楚编译的内部实现,也就是编译的原理。 这篇文章主要说的是编译器前端,词法分析器的原理,最后会给出一个词法分析器的简单实现。 介绍 编译简单的说,就是把源程序转化为另一种形式的程序,而其中关键的部分就是理解源程序所要表达的意思,才能转化为另一种源程序。 可以用一个比喻来说明问题:人A和人B想要交谈,但是他们都不知道彼此的语言,这就需要一个翻译C,同时懂得A和B的语言。有了C做中间层,A和B才能正常交流。C的作用就有点像编译器,它必须能理解源程序所要表达的意思,才能把信息传递给另一个。 编译器也一样,它的输入是语言的源文件(一般可以是文本文件)对于输入的文件,首先要分离出这个输入文件的每个元素(关键字、变量、符号、、) 然后根据语言的文法,分析这些元素的组合是否合法,以及这些组合所表达的意思。 程序设计语言和自然语言不一样,都是用符号来描述,每个特定的符号表示特定的意思,而且程序设计语言是上下文无关的。上下文无关就是某一个特定语句所要表达的意思和它所处的上下文没有关系,只有它自身决定。 这篇博文主要说的就是词法分析,也就是把输入的符号串整理成特定的词素。 词法分析 定义: 词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常量等 (1) 关键字是由程序语言定义的具有固定意义的标识符。例如,Pascal 中的begin,en d,if,while都是保留字。这些字通常不用作一般标识符。 (2) 标识符用来表示各种名字,如变量名,数组名,过程名等等。 (3) 常数常数的类型一般有整型、实型、布尔型、文字型等。 (4) 运算符如+、-、*、/等等。 (5) 界符如逗号、分号、括号、等等。 输出:

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

实验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 do 2、根据状态图,设计词法分析函数int scan( ),完成以下功能: 1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词, 2)以二元式形式输出单词<单词种类,单词属性> 其中单词种类用整数表示: 0:标识符 1:十进制整数 2:八进制整数 3:十六进制整数 运算符和界符,关键字采用一字一符,不编码 其中单词属性表示如下: 标识符,整数由于采用一类一符,属性用单词表示 运算符和界符,关键字采用一字一符,属性为空 3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。 四、实验环境 PC微机 DOS操作系统或Windows 操作系统 Turbo C 程序集成环境或Visual C++ 程序集成环境 五、实验步骤 1、根据正规式,画出状态转换图;

相关文档
最新文档