设计词法分析之基于lex实现词法分析
- 格式:doc
- 大小:22.00 KB
- 文档页数:5
《编译原理》课程实验报告题目利用lex生成c语言的词法分析程序专业班级学号姓名一. 实验题目利用lex生成c语言的词法分析程序二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C语言四. 实验内容(实验要求)利用flex,仿教材p227的pascal语言的词法分析程序,经过适当修改后,遵照教材p48-图4.1和p50-表4.1编写自己的类别码。
要求:1.生成的词法分析程序要求能够对给定的任意c程序进行词法分析,并生成文档输出。
2.词法分析程序能够识别关键字、运算符、分界符、标识符、常量(至少是整形常量,可以自己扩充识别其它常量)等,并能处理注释、部分复合运算符(如>=等)。
3.交 .l 文件,c源文件、输出分析结果文件及实验报告。
五. 实验步骤(1)遵照教材p48-图4.1和p50-表4.1,自己编写自己的类别编码。
(2)仿教材p227,pascal语言的词法分析程序,经过适当的修改后输入记事本中,保存格式为.l文件。
(3)在DOS环境下,利用flex运行.l文件,生成lex.yy.c文件。
(4)用c-free打开lex.yy.c文件,检查是否有错误并运行,生成lex.yy.exe 文件。
(5)可利用此程序运行任意的c程序进行词法分析。
六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)1.此次实验让我进一步熟悉了词法分析程序lex的运用,熟悉了模式的运用方法及其格式的运用。
2.要使词法分析程序能够识别c程序中任意的关键字、运算符、分界符、标识符、常量,必须对这五类单词符号非常熟悉,因此还需要加强巩固c语言这方面的知识。
3.由于对pascal语言的陌生,在将代码修改为c语言的过程中,更多的只是跟着老师说的改,至于为什么这么改并不是很清楚,这其中一个原因是对各种模式的运用和理解的欠缺。
因此需要不断进行总结。
七. 实验结果(关键源代码)单词符号输出形式(表格)如下:。
题目:词法分析器的设计与实现一、引言................................ 错误!未定义书签。
二、词法分析器的设计 (3)2.1词的内部定义 (3)2.2词法分析器的任务及功能 (3)32.2.2 功能: (4)2.3单词符号对应的种别码: (4)三、词法分析器的实现 (5)3.1主程序示意图: (5)3.2函数定义说明 (6)3.3程序设计实现及功能说明 (6)错误!未定义书签。
77四、词法分析程序的C语言源代码: (7)五、结果分析: (12)摘要:词法分析是中文信息处理中的一项基础性工作。
词法分析结果的好坏将直接影响中文信息处理上层应用的效果。
通过权威的评测和实际应用表明,IRLAS是一个高精度、高质量的、高可靠性的词法分析系统。
众所周知,切分歧义和未登录词识别是中文分词中的两大难点。
理解词法分析在编译程序中的作用,加深对有穷自动机模型的理解,掌握词法分析程序的实现方法和技术,用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。
Abstract:lexical analysis is a basic task in Chinese information processing. The results of lexical analysis will directly affect the effectiveness of the application of Chinese information processing. The evaluation and practical application show that IRLAS is a high precision, high quality and high reliability lexical analysis system. It is well known that segmentation ambiguity and unknown word recognition are the two major difficulties in Chinese word segmentation. The understanding of lexical analyse the program at compile, deepen of finite automata model for understanding, master lexical analysis program implementation method and technology, using C language subset of a simple language compilation of a scanned again compiler, to deepen to compile the principle solution, master compiler implementation method and technology.关键词:词法分析器?扫描器?单词符号?预处理Keywords: lexical analyzer word symbol pretreatment scanner一、引言运用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]+`表示忽略空格和换行符;`.`表示匹配到了其他未定义的字符,就打印出异常信息。
词法分析程序的设计与实现方法1:采用C作为实现语言,手工编制一.文法及状态转换图1.语言说明:C语言有以下记号及单词:(1)标识符:以字母开头的、后跟字母或数字组成的符号串。
(2)关键字:标识符集合的子集,该语言定义的关键字有32个,即auto,break,case,char,const,continue,default,do,double,else,enum, extern,float,for,goto,if,int,long,register,return,short,signed,static, sizeof,struct,switch,typedef ,union,unsigned ,void, volatile和while。
(3)无符号数:即常数。
(4)关系运算符:<,<=,==,>,>=,!=。
(5)逻辑运算符:&&、||、!。
(6)赋值号:=。
(7)标点符号:+、++、-、--、*、:、;、(、)、?、/、%、#、&、|、“”、,、.、{}、[]、_、^等(8)注释标记:以“/*”开始,以“*/”结束。
(9)单词符号间的分隔符:空格。
2.记号的正规文法:仅给出各种单词符号的文法产生式(1)标识符的文法id->letter ridrid->ε|letter rid|digit rid(2)无符号整数的文法digits->digit remainderremainder->ε|digit remainder(3)无符号数的文法num->digit num1num1->digit num1|. num2|E num4|εnum2->digit num3num3->digit num3|E num4|εnum4->+digits|-digits|digit num5digits->digit num5num5->digit num5|ε(4)关系运算符的文法relop-> <|<=|==|>|>=|!=(5)赋值号的文法assign_op->=(6)标点符号的文法special_symbol->+|-|*|%|#|^|(|)|{|}|[|]|:|;|”|?|/|,|.& (7)逻辑运算符的文法logic->&&| || | !(8)注释头符号的文法note->/starstar->*3.状态转换图其中,状态0是初始状态,若此时读入的符号是字母,则转换到状态1,进入标识符识别过程;如果读入的是数字,则转换到状态2,进入无符号数识别过程;……;若读入的符号是/,转换到状态11,再读入下一个符号,如果读入的符号是*,则转换到状态12,进入注释处理状态;如果在状态0读入的符号不是语言所定义的单词符号的开始字符,则转换到状态13,进入错误处理状态。
词法分析程序一、设计目的通过编写并上机调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将其分解成各类单词的词法分析方法。
二、设计要求要求将用模拟语言书写的源程序进行词法分析,输出源程序清单,Token文件和错误信息文件,若有错误,必须输出错误在源程序中行号和列号,并将符号表和字符串以文件的形式写出来。
三、设计说明基于Parser Genarator的词法分析器构造方法。
Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。
这三个部分由位于新一行第一列的双百分号分开,因此,Lex输入文件的格式如下{definitions}%%{rules}%%{auxiliary routines}而且第一部分用“%{”和“%}”括起来。
第一和第三个部分为C语言的代码和函数定义,第二个部分为一些规则。
3.1正规式定义定义正则表达式如下ID = letter letter*NUM = digit digit*Letter = a|…|z|A|…|ZDigit = 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]+3.2转换规则定义在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);}//标识符定义识别错误的字符串规则当开头为数字的后面为字母的字符串时,是错误的标识符。
词法分析程序
一、设计目的
通过编写并上机调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将其分解成各类单词的词法分析方法。
二、设计要求
要求将用模拟语言书写的源程序进行词法分析,输出源程序清单,Token文件和错误信息文件,若有错误,必须输出错误在源程序中行号和列号,并将符号表和字符串以文件的形式写出来。
三、设计说明
基于Parser Genarator的词法分析器构造方法。
Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。
这三个部分由位于新一行第一列的双百分号分开,因此,Lex输入文件的格式如下
{definitions}
%%
{rules}
%%
{auxiliary routines}
而且第一部分用“%{”和“%}”括起来。
第一和第三个部分为C语言的代码和函数定义,第二个部分为一些规则。
3.1正规式定义
定义正则表达式如下
ID = letter letter*
NUM = digit digit*
Letter = a|…|z|A|…|Z
D igit = 0|…|9
Keyword = else|if|int|return|void|while
Special 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]+
3.2转换规则定义
在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);}//标识符
定义识别错误的字符串规则
当开头为数字的后面为字母的字符串时,是错误的标识符。
{error_id}
{printf("error:%s\n",yytext);}//以数字开头的字符自动报错
定义忽略空格规则
{whitespace}
{/* skip whitespace */}//忽略空格
定义忽略回车规则
{enter}
{lineno++;}//遇到回车自动加行号忽略
3.3辅助程序
辅助程序集中包括
主函数main ()和辅助函数toupper()。
3.3程序代码实现
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int yywrap();
int lineno=1;
%}
delim [ \t]
ws {delim}+
letter [A-Za-z]
digit [0-9]
id {letter}({letter}|{digit})*
number {digit}+
error_id ({digit})+({letter})+
enter [ \n]
spchar ("{"|"}"|"["|"]"|"("|")"|";"|"="|",")
ariop ("+"|"-"|"*"|"/")
relop ("<"|"<="|">"|">="|"=="|"!=")
comment \/\*(\*[^/]|[^*])*\*\/
reswd (int|else|return|void|if|while)
%%
{ws} {}
{comment} {}
{enter} {lineno++;}
{reswd} {fprintf(yyout,"%d行\tkeywod\t%s\n",lineno,yytext);} {spchar} {fprintf(yyout,"%d行\tspchar\t%s\n",lineno,yytext);} {id} {fprintf(yyout,"%d行\tidentifier\t%s\n",lineno,yytext);} {number} {fprintf(yyout,"%d行\tnumber\t%s\n",lineno,yytext);} {error_id} {fprintf(yyout,"%d行\terror_id\t%s\n",lineno,yytext);} {ariop} {fprintf(yyout,"%d行\tari_op\t%s\n",lineno,yytext);} {relop} {fprintf(yyout,"%d行\trel_op\t%s\n",lineno,yytext);}
%%
int yywrap() {return 1;}
int main(void)
{
char infilename[100];
printf("输入文件名:");
scanf("%s",infilename);
yyin = fopen(infilename,"r");
yyout = fopen("out","w");
yylex();
return 0;
}
四、运行结果及分析
测试的C语言代码:
测试结果:
测试的C语言代码:
测试结果:
测试代码:
测试结果:
五、总结
通过本次课程设计的练习,学会运用Lex自动构造词法分析器,学会了基于Parser Genarator的词法分析器构造方法。
掌握了词法分析器的原理以及功能。
词法分析是编译过程中的一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
词法分析程序的主要任务:读源程序,产生单词符号。
词法分析程序的其他任务:滤掉空格,跳过注释、换行符追踪换行标志,复制出错源程序,宏展开,等等等等。
词法分析工作从语法分析工作独立出来的原因:简化设计,改进编译效率,增加编译系统的可移植性。
而且从划分关键字,运算符,界符,标识符和常量,才发现数字,字母及符号组合有很多很多,无法全部枚举,所以在新建的文本文档中只象征性的列出几种符号,但这并不影响此法分析结果的完成。
总之,通过本次实验,一点点分析词法分析器的功能,并努力实现它,掌握了课程设计内容的
同时也锻炼了自己分析解决问题的能力以及编程能力,收获颇丰!。