利用LEX自动生成词法分析程序

合集下载

编译原理 利用lex生成c语言的词法分析程序 实验报告

编译原理 利用lex生成c语言的词法分析程序 实验报告

《编译原理》课程实验报告题目利用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语言的过程中,更多的只是跟着老师说的改,至于为什么这么改并不是很清楚,这其中一个原因是对各种模式的运用和理解的欠缺。

因此需要不断进行总结。

七. 实验结果(关键源代码)单词符号输出形式(表格)如下:。

lex工具实例

lex工具实例

翻译规则部分(续)


为避免二义性,在Ri中 若需出现空格、回车或 制表符,则应用‘\s’, ‘\n’,‘\t’表示。 每个代码段Actioni可 引用已定义的常量、全 局变量和外部变量,也 可以调用在辅助函数部 分定义的函数。
注意:Actioni中的C
程序语句多于一条时, 必须用花括号{ }将 它们括起来,否 则,LEX将会报错
词法分析程序的使用



用户可通过调用函数yylex()使用词法分析程序。每调 用yylex()函数一次,yylex()将从输入流中识别一个单词, 并返回一个整型值(被识别出的单词之内部码)。 所谓单词的内部码是指词法分析程序在识别出某一类 单词时所返回的整型数值(也称为类别码),它由用 户自行定义其取值。 例如,用户可定义标识符Id的内部码为300,实型数 RealNo的内部码为450等等。一般说来,用户自定义的 单词类别码应大于256,而小于256的内部码值可用于 字符单词的类别码,用其ASCII码值来表示。如单词 '+'的内部码可定义为‘+’的ASCII码值43。
LEX的命令格式及选项
格式:lex [-ctvn -V -Q[y|n]] [files] 选项: -c 指明动作为C语句(缺省设置). -t 输出到stdout 而不是 lex.yy.c(缺省设置); -v 提供一个两行的统计概述 -n 不输出-v的概述 -V 在stderr上输出lex的版本信息. -Q[y|n] y:在输出文件lex.yy.c上打印版本信息. n:不打印(缺省设置). 若files为多个文件,则被视为一个,若files为空,则使用stdin.
1.声明(declaration)
LEX的声明又可以分两个

LEX和YACC的使用(例子)

LEX和YACC的使用(例子)

LEX和YACC的使⽤(例⼦)1、简单C语⾔的词法分析程序;%{#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<string.h>%}digit [0-9]letter [A-Za-z]other_char [!-@\[-~]id ({letter}|[_])({letter}|{digit}|[_])*string {({letter}|{digit}|{other_char})+}int_num {digit}+%%[ |\t|\n]+ "auto"|"double"|"int"|"struct"|"break"|"else"|"long"|"switch"|"case"|"enum"|"register"|"typedef"|"char"|"extern"|"return"|"union"|"const"|"float"|"short"|"unsigned"|"continue"|"for"|"signed"|"void"|"default"|"go \"([!-~])*\" {printf("CONST_string,%s\n",yytext);}-?{int_num}[.]{int_num}?([E][+|-]?{int_num})? {printf("CONST_real,%s\n",yytext);}"0x"?{int_num} {printf("CONST_int,%s\n",yytext);}","|";"|"("|")"|"{"|"}"|"["|"]"|"->"|"."|"!"|"~"|"++"|"--"|"*"|"&"|"sizeof"|"/"|"%"|"+"|"-"|">"|"<"|">="|"<="|"=="|"!="|"&"|"^"|"|"|"&"|"||"|"+="|"-="|"*="|"/="|"%="|">>="|"<<="|"&="|"^="|"|="|"=" {printf("%s,NULL\n",yytext);}{id} {printf("ID,%s\n",yytext);}{digit}({letter})+ {printf("error1:%s\n",yytext);}%%#include <ctype.h>Upper(char *s,int l){int i;for(i=0;i<l;i++){s[i]=toupper(s[i]);}}yywrap(){return 1;}注意:要得到输出信息,需要⾃⾏添加main函数,lex默认的main函数没有输出的。

基于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]+`表示忽略空格和换行符;`.`表示匹配到了其他未定义的字符,就打印出异常信息。

(完整版)基于LEX的词法分析器实验报告

(完整版)基于LEX的词法分析器实验报告
printf("%s special symbol\n",yytext);}//特殊符号
定义识别标识符规则
{id}
{printf("%d行",lineno);
printf("%s ID\n",yytext);}//
定义识别错误的字符串规则当开头为数字的后面为字母的字符串时,是错误的标识符。{error_id}
yylex();/*start the analysis*/
printf("ok2\n");
printf(" No of words: %d\n number: %d\n", wordCount, numcount);
return0;
}
int yywrap()
{
return1;
}
2、新建文本文件,更名为b.c,敲入下面代码此为输入源代码
{printf("error:%s\n",yytext);}//以数字开头的字符自动报错定义忽略空格规则
{whitespace}{/*skip whitespace*/}//忽略空格定义忽略回车规则
{enter}
{lineno++;}//遇到回车自动加行号忽略辅助程序集中包括
主函数main()和辅助函数toupper()。程序代码实现
二、实验原理及方法
Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。这三个部分由位于新一行第一列 的双百分号分开,因此,Lex输入文件的格式如下
{definitions}

编译原理实践10—词法分析程序的自动生成器LEX

编译原理实践10—词法分析程序的自动生成器LEX

LEX简单的介绍
• LEX能根据给定的正则表达式自动生成 相应的词法分析程序 • 输入:是用LEX 语言写的源程序 • 生成:用C语言描述的词法分析程序 • LEX生成的目标程序包含一个状态转换 矩阵和一个控制执行程序.
LEX使用流程
使用LEX的流程如图:
LEX源程序 YYLEX.C 字符串源程序 LEX C编译器 YYLEX.EXE YYLEX.C YYLEX.EXE 符号串源程序
LEX源程序结构:辅助过程
3辅助过程
给出用户所需要的其他操作,它是识别部分某些动作需要调 用的过程。如果不是C语言的库函数,则要在此给出具体的定 义。这些程序也可以存入另外的程序文件中,单独编译,最 后和词法分析程序连接装配到一起。
例如:下段辅助过程:
%% main() {yylex(); return 0; }
用LEX语言表达正则表达式
例: 1)二进制数 (0|1)* 2)以aa或bb开头的由a和b任意组成的字符串 (aa|bb)(a|b)*或(aa|bb)[ab]*
3) 任何一个从0~9的数字:
[0-9] 4)长度不超过8的小写字符串 [a-z]{1,8}
用LEX语言表达正则表达式
5) 无符号整数
[0-9]+
编译原理实践 --词法分析程序的自动生成器LEX
由于各种高级程序设计语言的单词形式 基本上可以用一组正规式来描述,人们 就希望能否构造一个自动生成系统,只 要给出程序设计语言的各类单词描述以 及识别出各类单词后应输出的结果,这 种自动系统便能自动产生此程序设计语 言的词法分析程序 Lex就是这样一个工具,他将正规式转换 为一个NFA,进而转换为相应的DFA, 这个DFA可以识别该正规式所表示的语 言的句子

实验一词法分析程序开发

实验一词法分析程序开发

实验一词法分析程序开发【实验目的】•深入理解有限自动机及其应用•掌握根据语言的词法规则构造识别其单词的有限自动机的方法•深入理解词法分析程序自动生成原理•掌握词法分析程序的开发。

【实验学时】4学时【实验要求】•掌握词法分析程序自动生成工具LEX的使用。

•掌握各类单词的形式描述•学会用数据中心法实现有限自动机•学会用直接转向法实现有限自动机•独立完成SNL语言的词法分析器【实验原理】词法分析是编译过程的第一阶段。

它的任务就是对输入的字符串形式的源程序按顺序进行扫描,根据源程序的词法规则识别具有独立意义的单词(符号),并输出与其等价的Token序列。

有限自动机是描述程序设计语言单词构成的工具,而状态转换图是有限自动机的比较直观的描述方法。

我们使用确定的有限状态自动机,简记为DFA。

下面给出能够识别SNL中各类单词的DFA:识别SNL单词的DFA表示根据语言的词法规则构造出识别其单词的确定有限自动机DFA, 仅仅是词法分析程序的一个形式模型,距离词法分析程序的真正实现还有一定的距离。

状态转换图的实现通常有两种方法,一种是用状态转换表T;另一种是直接转向法。

状态转换表法又称数据中心法,是把状态转换图看作一种数据结构(状态转换表),由控制程序控制字符在其上运行,从而完成词法分析。

用转换表的优点是程序短,但占存储空间多,直接转向法的优缺点正好与此相反。

直接转向法又称程序中心法,是把状态转换图看成一个流程图,从状态转换图的初态开始,对它的每一个状态结点都编一段相应的程序。

【实验步骤】一、构造识别单词的自动机1.根据构成规则对程序语言的单词按类构造出相应的状态转换图。

2. 对各类单词的状态转换图合并,构成一个能识别语言所有单词的状态转换图。

合并步骤为:(1) 将各类单词的状态转换图的初始状态合并为一个唯一的初态;(2) 化简调整状态冲突和对冲突状态重新编号;(3) 如有必要,增加出错状态。

二、(a)用数据中心法实现有限自动机,生成词法分析程序。

词法分析程序的设计与实现

词法分析程序的设计与实现

词法分析程序的设计与实现方法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,进入错误处理状态。

词法分析程序自动工具使用说明

词法分析程序自动工具使用说明

词法分析程序自动工具使用说明1.建立工作文件夹如D:\LEX2.将词法分析工具flex.exe 拷入到该文件夹3.建立LEX源文件如:用文本编辑器建立lextemp.txt源文件%{#include <stdio.h>#define BEGIN 101#define END 202%}digit [0-9]alpha [a-z]alnum [a-z0-9]%%begin {out(BEGIN,"begin");}end {out(END,"end");}"*" {out(303,"*");}"+" {out(404,"+");}{alpha}{alnum}* {out(505,yytext);}"=" {out(606,"=");}%%out(int c,char *val){printf("word:%d, %s\n",c,val);}4.建立简单语言的源程序文件如:用文本编辑器建立data.txt文件beginabcd=100efg=200gh123=300abcd=abcd*efgh+gh123end5.在DOS运行flex 生成目标文件lex.yy.c flex lex源文件名如:d:\lex\flex lextemp.txt6.进入VC,对lex.yy.c进行修改(1)增加或修改main()函数增加打开程序文件的语句int main(void){int c;if ((yyin=fopen("data.txt","r"))==NULL){printf("can’t open the file\n");exit(0);}yylex();return 0;}(2)增加函数int yywrap(){return 0;}(3)尾部这二行屏蔽// #if YY_MAIN// #Endif7.运行得到结果识别出的单词将在屏幕输出,通过修改out 函数可改为输出到一文件中。

lex用法

lex用法

lex用法
"lex"是一种文本分析工具,主要用于编写词法分析器。

它能够根据用户所定义的模式匹配规则,自动生成C语言代码实现词法分析功能。

具体来说,使用"lex"需要以下几个步骤:
1. 编写"lex"文件:该文件包含"lex"语法及模式匹配规则,决定了如何从输入的字符流中识别
和提取出各种符号和单词。

2. 使用"lex"命令编译生成C程序:命令格式为: `lex -o output.c input.l`,其中"output.c"为生成
的C源程序文件,"input.l"为"lex"文件名。

3. 编译并链接生成的C程序:使用C语言编译器(如gcc)编译生成的C源程序文件,并将其与主程序进行链接,形成可执行文件。

4. 运行程序并测试:将待分析的文本输入到程序中,程序会按照模式匹配规则进行词法分析,并输出分析结果。

"lex"的优点在于可以大大简化词法分析器的编写和维护工作,同时也增强了程序的可读性和
可移植性。

它常被用于编写编译器、解释器、文本编辑器等需要对文本内容进行识别和分析的应
用程序中。

Lex使用指南

Lex使用指南

Lex使用指南Lex是由美国Bell实验室等人用C语言开发的一种词法分析器自动生成工具,它提供一种供开发者编写词法规则(正规式等)的语言(Lex语言)以及这种语言的翻译器(这种翻译器将Lex语言编写的规则翻译成为C语言程序)。

Lex是linux下的工具,本实验使用的编译工具是cygwin(cygwin在windows下模拟一个linux环境)下的flex,它与lex的使用方法基本相同,只有很少的差别。

一、Lex的基本原理和使用方法Lex的基本工作原理为:由正规式生成NFA,将NFA变换成DFA,DFA经化简后,模拟生成词法分析器。

其中正规式由开发者使用Lex语言编写,其余部分由Lex翻译器完成.翻译器将Lex源程序翻译成一个名为的C语言源文件,此文件含有两部分内容:一部分是根据正规式所构造的DFA状态转移表,另一部分是用来驱动该表的总控程序yylex()。

当主程序需要从输入字符流中识别一个记号时,只需要调用一次yylex()就可以了。

为了使用Lex所生成的词法分析器,我们需要将程序用C编译器进行编译,并将相关支持库函数连入目标代码。

Lex的使用步骤可如下图所示:生成词法分析器的过程:使用所生成的词法分析器的过程:二、lex源程序的写法:Lex源程序必须按照Lex语言的规范来写,其核心是一组词法规则(正规式)。

一般而言,一个Lex源程序分为三部分,三部分之间以符号%%分隔。

`[第一部分:定义段]%%第二部分:词法规则段[%%第三部分:辅助函数段]其中,第一部分及第三部分和第三部分之上的%%都可以省略(即上述方括号括起的部分可以省略)。

以%开头的符号和关键字,或者是词法规则段的各个规则一般顶着行首来写,前面没有空格。

Lex源程序中可以有注释,注释由/*和*/括起,但是请注意,注释的行首需要有前导空白。

1. 第一部分定义段的写法:定义段可以分为两部分:第一部分以符号%{和%}包裹,里面为以C语法写的一些定义和声明:例如,文件包含,宏定义,常数定义,全局变量及外部变量定义,函数声明等。

2.5 词法分析器的自动生成

2.5 词法分析器的自动生成

2014-9-30
12
/* 用户子程序 */





void main() { yylex(); /* start the analysis*/ printf(" No of words: %d\n ", wordCount); } int yywrap() { return 1; }
2014-9-30
3
LEX是美国Bell实验室研制的一个词 法分析程序的自动生成工具。对任一高 级程序语言,用户必须用正规式描述该 语言的各个词法类(LEX的源程序),LEX 就可自动生成该语言的词法分析程序。 LEX及其编译系统的作用如下:
LEX源程序 输入串
2014-9-30
LEX编译系统 词法分析程序L

2014-9-30 5
Lex 的常规表达式: 常规表达式是一种使用元语言的模式描 述。表达式由符号组成,符号一般是字 符和数字,但是 Lex 中还有一些具有特 殊含义的其他标记。


下面定义了 Lex 中使用的一些标记并给 出了几个典型的例子。
2014-9-30
6


2014-9-30 16
6{ 7} 8( 9) 10 + 11 − 12 * 13 / 14 = 15 ;
2014-9-30
{return (6,null)} {return (7,null)} {return (8,null)} {return (9,null)} {return (10,null)} {return (11,null)} {return (12,null)} {return (13,null)} {return (14,null)} {return (15,null)}

编译原理实验——flex语法实现简单词法分析器

编译原理实验——flex语法实现简单词法分析器
可以看到结果是正确的。
flex提供的2个全局变量:
yytext:刚刚匹配到的字符串 yyleng:刚刚匹配到的字符串的长度
代码段如下(注意:规则行务必没有缩进,且对应的动作必须在同一行开始):
%{ #include <stdio.h> #include <string.h>
%}
ALPHA [a-zA-Z] ID {ALPHA}+[a-zA-Z0-9_]* KEY begin|if|then|while|do|end NUM [\-]?[1-9][0-9]*|0
四、实验结果
1. 用管理员身份打开cmd窗口 2. 进入到该代码文本文件所在的文件夹内 3. 然后输入下面两行命令,完成对代码的编译生成。
flex test.l //此后会生成C文件lex.yy.c gcc lex.yy.c //使用gcc编译成可执行文件 4. 我这里生成的是a.exe文件,在窗口中输入a.exe或a回车,运行该文件 即可输入字符串来验证结果。
2.3 词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或num)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; num为整型常数。 例如:对源程序begin x:=9; if x>9 then x:=2*x+1/3; end #的Pascal源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…
printf("(4,%s)",yytext);
else if(yytext[0]=='d')
printf("(5,%s)",yytext);

CH03--词法分析-LEX

CH03--词法分析-LEX

a
2 b b
abb
开始
3
a
4 a
5
6
b b 8
{a}*b{b}*
Wensheng Li BUPT
开始
7
15
合并为一个NFA M

开始
1 3 7
a a a b
2 4 b 8 b
0

5
b
6
Wensheng Li BUPT
16
将该NFA M确定化为DFA D
DFA D=({a,b},{A,B,C,D,E,F},A,{B.C.E.F},) 其中:A={0,1,3,7} B={2,4,7} C={8} D={7} E={5,8} F={6,8}
Wensheng Li BUPT
18

Wensheng Li BUPT
4
2.翻译规则

形式:
P1 P2 … Pn { 动作1 } { 动作2 } { 动作n }

Pi 是一个正规表达式,描述一种记号的模式。 动作i 是C语言的程序语句,表示当一个串匹配模式 Pi时,词法分析器应执行的动作。
5

Wensheng Li BUPT
3.辅助过程
Wensheng Li BUPT
7
相应的 LEX 源程序 框架
/* 说明部分 */ %{ #include <stdio.h> /* C语言描述的标识符常量的定义,如 LT、LE、EQ、NE、GT、 GE、IF、THEN、ELSE、ID、NUMBER、RELOP */ extern yylval; %} /* 正规定义式 */ delim [ \t\n] ws {delim}+ letter [A-Za-z] digit [0-9] id {letter}({letter}|{digit})* num {digit}+(\.{digit}+)?(E[+\-]?{digit}+)? %%

编译原理实验:C语言的Lex词法分析程序

编译原理实验:C语言的Lex词法分析程序

%{#include <stdlib.h>#include <stdio.h>int ID = 0;intNumber_float = 0;int Number = 0;int STRING = 0;int CHAR = 0;int ERROR = 0;int OPERATOR = 0;intReserved_word = 0;int b = 0;int f = 0;%}hulue [\t\n ]capitalLetter [A-Z]smallLetter [a-z]writespace {hulue}+letter ({capitalLetter}|{smallLetter})digit [0-9]id (_|{letter})(_|{letter}|{digit})*number {digit}+float {digit}*(\.{digit}+)(E[+\-]?{digit}+)?tempChar1 [ -!#-~]tempChar2 [ -&(-~]char \'((\\{smallLetter})|({tempChar2}|(\\\')))\'string \"({tempChar1}|(\\\"))*\"%%{writespace} {}include {++Reserved_word; printf(" reserved word : %s\n", yytext);} stdio.h {++Reserved_word; printf(" reserved word : %s\n", yytext);} stdlib.h {++Reserved_word; printf(" reserved word : %s\n", yytext);} main {++Reserved_word; printf(" reserved word : %s\n", yytext);} auto {++Reserved_word; printf(" reserved word : %s\n", yytext);} break {++Reserved_word; printf(" reserved word : %s\n", yytext);} case {++Reserved_word; printf(" reserved word : %s\n", yytext);} char {++Reserved_word; printf(" reserved word : %s\n", yytext);} continue {++Reserved_word; printf(" reserved word : %s\n", yytext);}default {++Reserved_word; printf(" reserved word : %s\n", yytext);} const {++Reserved_word; printf(" reserved word : %s\n", yytext);} do {++Reserved_word; printf(" reserved word : %s\n", yytext);} double {++Reserved_word; printf(" reserved word : %s\n", yytext);} else {++Reserved_word; printf(" reserved word : %s\n", yytext);} enum {++Reserved_word; printf(" reserved word : %s\n", yytext);} extern {++Reserved_word; printf(" reserved word : %s\n", yytext);} float {++Reserved_word; printf(" reserved word : %s\n", yytext);}for {++Reserved_word; printf(" reserved word : %s\n", yytext);} goto {++Reserved_word; printf(" reserved word : %s\n", yytext);}if {++Reserved_word; printf(" reserved word : %s\n", yytext);}int {++Reserved_word; printf(" reserved word : %s\n", yytext);} long {++Reserved_word; printf(" reserved word : %s\n", yytext);} register {++Reserved_word; printf(" reserved word : %s\n", yytext);} return {++Reserved_word; printf(" reserved word : %s\n", yytext);} short {++Reserved_word; printf(" reserved word : %s\n", yytext);} signed {++Reserved_word; printf(" reserved word : %s\n", yytext);} sizeof {++Reserved_word; printf(" reserved word : %s\n", yytext);} static {++Reserved_word; printf(" reserved word : %s\n", yytext);} struct {++Reserved_word; printf(" reserved word : %s\n", yytext);} switch {++Reserved_word; printf(" reserved word : %s\n", yytext);} typedef {++Reserved_word; printf(" reserved word : %s\n", yytext);} union {++Reserved_word; printf(" reserved word : %s\n", yytext);} unsigned {++Reserved_word; printf(" reserved word : %s\n", yytext);} void {++Reserved_word; printf(" reserved word : %s\n", yytext);} volatile {++Reserved_word; printf(" reserved word : %s\n", yytext);} while {++Reserved_word; printf(" reserved word : %s\n", yytext);} scanf {++Reserved_word; printf(" reserved word : %s\n", yytext);} printf {++Reserved_word; printf(" reserved word : %s\n", yytext);}"(" { ++f; printf(" fengehao : %s\n", yytext);}")" { ++f; printf(" fengehao : %s\n", yytext);}":" { ++f; printf(" fengehao : %s\n", yytext);}";" { ++f; printf(" fengehao : %s\n", yytext);}"[" { ++f; printf(" fengehao : %s\n", yytext);}"]" { ++f; printf(" fengehao : %s\n", yytext);}"{" { ++f; printf(" fengehao : %s\n", yytext);}"}" { ++f; printf(" fengehao : %s\n", yytext);}"." {++OPERATOR; printf(" operator : %s\n", yytext);}"->" {++OPERATOR; printf(" operator : %s\n", yytext);}"++" {++OPERATOR; printf(" operator : %s\n", yytext);}"--" {++OPERATOR; printf(" operator : %s\n", yytext);}"~" {++OPERATOR; printf(" operator : %s\n", yytext);}"!" {++OPERATOR; printf(" operator : %s\n", yytext);}"-" {++OPERATOR; printf(" operator : %s\n", yytext);}"+" {++OPERATOR; printf(" operator : %s\n", yytext);}"*" {++OPERATOR; printf(" operator : %s\n", yytext);}"&" {++OPERATOR; printf(" operator : %s\n", yytext);}"/" {++OPERATOR; printf(" operator : %s\n", yytext);}"%" {++OPERATOR; printf(" operator : %s\n", yytext);}"<<" {++OPERATOR; printf(" operator : %s\n", yytext);}">>" {++OPERATOR; printf(" operator : %s\n", yytext);}">" {++OPERATOR; printf(" operator : %s\n", yytext);}"<" {++OPERATOR; printf(" operator : %s\n", yytext);}"<=" {++OPERATOR; printf(" operator : %s\n", yytext);}">=" {++OPERATOR; printf(" operator : %s\n", yytext);}"=" {++OPERATOR; printf(" operator : %s\n", yytext);}"==" {++OPERATOR; printf(" operator : %s\n", yytext);}"!=" {++OPERATOR; printf(" operator : %s\n", yytext);}"&&" {++OPERATOR; printf(" operator : %s\n", yytext);}"^" {++OPERATOR; printf(" operator : %s\n", yytext);}"|" {++OPERATOR; printf(" operator : %s\n", yytext);}"||" {++OPERATOR; printf(" operator : %s\n", yytext);}"," {++OPERATOR; printf(" operator : %s\n", yytext);}"*=" {++OPERATOR; printf(" operator : %s\n", yytext);}"-=" {++OPERATOR; printf(" operator : %s\n", yytext);}"+=" {++OPERATOR; printf(" operator : %s\n", yytext);}"&=" {++OPERATOR; printf(" operator : %s\n", yytext);}"/=" {++OPERATOR; printf(" operator : %s\n", yytext);}"<<=" {++OPERATOR; printf(" operator : %s\n", yytext);}"|=" {++OPERATOR; printf(" operator : %s\n", yytext);}">>=" {++OPERATOR; printf(" operator : %s\n", yytext);}"^=" {++OPERATOR; printf(" operator : %s\n", yytext);}"#" {++OPERATOR; printf(" operator : %s\n", yytext);}"/*"[^*]*[*]+([^*/][^*]*[*]+)*[*]*"/" {++b; printf(" C declaration : %s\n", yytext);}{number} {++Number; printf(" number : %s\n", yytext);}{float} {++Number_float; printf("float : %s\n", yytext);}{string} {++STRING; printf(" string : %s\n", yytext);}{char} {++CHAR; printf(" char : %s\n", yytext);}{id} {++ID; printf(" id : %s\n", yytext);}. {++ERROR; printf(" error : %s\n", yytext);}%%int main(){printf("----------------------press Ctrl + D to end input------------------------\n"); yylex();printf("-------------------------------------------------------------------------\n"); printf("number of reserved word : %d\n",Reserved_word);printf("number of id : %d\n",ID);printf("number of number : %d\n",Number);printf("number of float : %d\n",Number_float);printf("number of string : %d\n",STRING);printf("number of char : %d\n",CHAR);printf("number of error symbol : %d\n",ERROR);printf("number of operator : %d\n",OPERATOR);printf("number of fengefuhao : %d\n",f);printf("number of declaration : %d\n",b);return 0;}intyywrap(){return 1;}。

词法分析器(lex实现)

词法分析器(lex实现)

院系:计算机学院实验课程:编译原理实验项目:C++源代码单词扫描程序(词法分析)指导老师:陈寅开课时间:2014~2015年度第1学期专业:数据库班级:2班学生:雷楚楚学号:20122100158C++源代码单词扫描程序(词法分析)一、实验目的设计并实现一个词法分析器,深刻理解编译原理中词法分析器的原理。

二、实验内容1、C++源代码扫描程序识别C++记号。

C++语言包含了几种类型的记号:标识符,关键字,数(包括整数、浮点数),字符串,注释,特殊符号(分解符)和运算符号等。

2、打开一个C++源文件,打印出所有以上的记号。

3、选作部分:为了提高C++源程序的可读性,C++程序在书写过程中加入了空行、空格、缩进、注释等。

假设你想牺牲可读性,以节省磁盘空间,那么你可以存贮一个删除了所有不必要空格和注释的C++源程序的压缩文本。

因此,程序中还看可以有这样的压缩功能。

4、进一步实现减少源文件大小的压缩功能。

5、完善软件文档。

二、实验过程1、对C++文法中的各类单词分类(1)保留字:asm、do、if、return、typedef、auto、double、inline、short、typeid、bool、try、include、long、sizeof、union、case、enum、mutable、static、unsigned、long、sizeof、union、case、enum、mutable、static、unsigned、catch、explicit、namespace、using、char、export、int、signed、break、else、new、struct、virtual、class、extern、operator、switch、void、const、false、private、template、volatile、float、protected、this、continue、for、public、throw、while、default、friend、register、true、delete、goto、try、include、std、iomanip、setw、setprecision、endl、setiosflags、ios (2)数字:包括整数和浮点数(3)标识符:由字母打头的字母和数字的字符串,可包含下划线(4)运算符:"&="、"^="、"、="、"<<="、">>="、"*="、"/="、"%="、"+="、"-="、"="、"?:"、"、、"、"&&"、"、"、"^"、"&"、"=="、"!="、">"、">="、"<"、"<="、"<<"、">>"、"+"、"-"、"*"、"/"、"%"、".*"、"->*"、"&"、"+"、"-"、"++"、"--"、"->"、"::"(5)界符:"{"、"}"、"("、")"、"#"、","、":"、";"、"."、"\""(6)注释:包括//和/**/两种类型的注释(7)字符串:包含在“”里面的内容2、将各类单词对应到Flex中:(1)保留字:asm|do|if|return|typedef|auto|double|inline|short|typeid|bool|try|include|long|sizeof|union|case|enum|mutable|static|unsigned|long|sizeof|union|case|enum|mutable|static|unsigned|catch|explicit|namespace|using|char|export|int|signed|break|else|new|struct|virtual|class|extern|operator|switch|void|const|false|private|template|volatile|float|protected|this|continue|for|public|throw|while|default|friend|register|true|delete|goto|try|include|std|iomanip|setw|setprecision|endl|setiosflags|ios(2)数字:包括整数和浮点数(正负)[+-]?([0-9]*|0|([0-9]*\.[0-9]*))(3)标识符:由字母打头的字母和数字的字符串,包含下划线[A-Za-z]([A-Za-z]|[0-9]|_)*(4)运算符:"&="|"^="|"|="|"<<="|">>="|"*="|"/="|"%="|"+="|"-="|"="|"?:"|"||"|"&&"|"|"|"^"|"&"|"=="|"!="|">"|">="|"<"|"<="|"<<"|">>"|"+"|"-"|"*"|"/"|"%"|".*"|"->*"|"&"|"+"|"-"|"++"|"--"|"->"|"::"(5)界符:"{"|"}"|"("|")"|"#"|","|":"|";"|"."|"\""(6)注释:包括//和/**/两种类型的注释\/\*(\s|.)*?\*\/(/**/)\/\/[^\n]*(//)(7)字符串:包含在“”里面的内容'[^'\n]*'|\"[^\"]*\"(8)除其他情况之外判断为出错3、跳过空行和空格[\t]+{}/*空格*/ \n|.{}/*空行*/4、为lex制定一些规则5、写子程序让用户输入要进行词法扫描的文件,当lex读完输入文件之后就会调用函数yywrap。

编译原理 lex使用

编译原理 lex使用

编译原理 lex使用
Lex是一种常用的词法分析工具,它可以解析输入字符串并将其分解为标记(token)。

在编译原理课程中,我们经常需要使用lex来生成词法分析器,以便将源代码转换为可执行代码。

使用Lex的基本步骤如下:
1. 编写一个类似于正则表达式的规则文件,描述如何匹配输入的字符串。

2. 使用lex工具将规则文件转换为C语言代码。

3. 编写一个main函数,调用生成的词法分析器来读取输入文件并解析出标记。

4. 在解析出的标记中执行语法分析,并将其转换为可执行代码。

需要注意的是,Lex的规则文件是基于正则表达式的,因此熟悉正则表达式的语法和特性是非常重要的。

在编写规则文件时,可以使用一些特殊的符号来描述字符类、重复次数、分组等特性,例如:
- []表示字符类,例如[0-9]表示匹配所有数字字符。

- {}表示重复次数,例如{1,3}表示重复1到3次。

- ()表示分组,例如(a|b)表示匹配a或b。

除了这些基本特性之外,Lex还提供了一些高级功能,例如:
- 跳过某些特定的字符,例如空格、注释、预处理指令等。

- 可以对不同的输入文件使用不同的规则文件。

- 可以为不同的标记指定不同的操作,例如输出、转换等。

总之,使用Lex可以大大简化词法分析的过程,提高代码的可维
护性和可读性。

如果你正在学习编译原理或者需要开发一个编译器,那么掌握Lex的使用是必不可少的。

词法分析器生成工具lex使用

词法分析器生成工具lex使用

模式:letter {动作 letter的数目加一}
辅助函数:
%% void main() {
yylex(); /* start the analysis*/ printf("no of letter:%d",id_num); }
int yywrap(请刷新页面重试持续报错请尝试更换浏览器或网络环境
词法分析器生成工具 lex使用
一个lex程序具有如下形式:
声明部分:包括变量和明示常量,可以将一些c语言的东西写在%{....... %},并且可以在转换规则中调用
%{ #include <stdio.h> int id_num; /*常量量*/
%}
letter [A-Za-z] /*正则变量*/
start start
/*正则变量*/
stop stop /*正则变量*/
转换规则:通过在声明部分的正则变量,识别输入流中的单词,并可以执行一些动作
lex程序中的每个转换规则具有如下形式:
模式 {动作}
%% letter {id_num++;} start {printf("start received");} stop {printf("stop received");}
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

利用LEX自动生成词法分析程序摘要:《编译原理》是国内外各高等院校计算机科学技术类专业,特别是计算机专业的一门重要专业课程。

该课程系统地向学生介绍编译程序的结构、工作流程及编译程序各组成部分的设计原理和实现技术编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。

词法分析阶段是编译过程的第一个阶段,是编译的基础。

这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。

词法分析程序实现这个任务。

词法分析程序可以使用Lex等工具自动生成。

本课设是用lex自动生成简单的c语言词法分析程序。

关键字:lex c语言词法分析程序引言词法分析程序是对代码中单词的分析,是编译过程的第一阶段,在这个阶段中从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。

Lex是一个广泛的使用工具,UNIX系统中使用lex命令调用。

它用于构造各种各样的语言词法分析程序。

词法分析是所有分析优化的基础,涉及的知识较少,如状态转换图等,易于实现。

下面将论述lex构造简单C语言的词法分析程序,深刻地去理解词法分析。

1概述1.1设计目标对C语言设计并实现一个简单的词法分析器,要求能够掌握编译原理的基本理论,,理解编译程序的基本结构,掌握编译各阶段的基本理论和技术,掌握编译程序设计的基本理论和步骤.,增强编写和调试高级语言源程序的能力,掌握词法分析的基本概念和实现方法,熟悉C语言的各种Token。

1.2设计内容用lex对C语言设计并实现一个简单的词法分析器,并用C语言代码进行测试,用二元式的方式给出测试结果。

2设计原理基于Parser Genarator的词法分析器构造方法。

Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。

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

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

2.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]+2.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++;}//遇到回车自动加行号忽略2.3辅助程序辅助程序集中包括主函数main ()和辅助函数toupper()。

3程序代码实现Lex代码//定义集,包括头文件和变量定义%{#include <ctype.h>#include <stdio.h>#include <string.h>#include <stdlib.h>int lineno=1;//定义行号%}//定义正则表达式letter [A-Za-z] //字母digit [0-9] //数字id ({letter}|[_])({letter}|{digit}|[_])* //开头为字母的标识符error_id ({digit})+({letter})+ //开头为数字的错误标识符num {digit}+ //数字集合whitespace [ \t]+ //空格enter [\n]+ //回车//定义识别规则%%//识别保留字"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("%d 行",lineno);printf("error: %s\n",yytext);}//以数字开头的字符自动报错//识别空格{whitespace}{/* skip whitespace */}//忽略空格//识别回车{enter}{lineno++;}//遇到回车自动加行号忽略%%//转换大小写Upper(char *s,int l){int i;for(i=0;i<l;i++){s[i]=toupper(s[i]);}}//将保留字变为大写//主函数main(void){//定义输入文件名变量char infilename[400];printf("输入文件名:");scanf("%s",&infilename);yyin = fopen(infilename,"r");//读取文件printf("开始词法分析:\n");return yylex();}4测试结果测试的C语言代码词法分析程序分析的结果5总结通过本次课程设计的练习,学会运用Lex自动构造词法分析器,学会了基于Parser Genarator的词法分析器构造方法。

掌握了词法分析器的原理以及功能。

词法分析是编译过程中的一个阶段,在语法分析前进行。

也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。

词法分析程序的主要任务:读源程序,产生单词符号。

词法分析程序的其他任务:滤掉空格,跳过注释、换行符追踪换行标志,复制出错源程序,宏展开,等等等等。

词法分析工作从语法分析工作独立出来的原因:简化设计,改进编译效率,增加编译系统的可移植性。

而且从划分关键字,运算符,界符,标识符和常量,才发现数字,字母及符号组合有很多很多,无法全部枚举,所以在新建的文本文档中只象征性的列出几种符号,但这并不影响此法分析结果的完成。

总之,通过本次实验,一点点分析词法分析器的功能,并努力实现它,掌握了课程设计内容的同时也锻炼了自己分析解决问题的能力以及编程能力,收获颇丰!参考文献《编译原理》(第2版)张素琴清华大学出版社。

相关文档
最新文档