(完整版)基于LEX的词法分析器实验报告
编译原理 利用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语言的过程中,更多的只是跟着老师说的改,至于为什么这么改并不是很清楚,这其中一个原因是对各种模式的运用和理解的欠缺。
因此需要不断进行总结。
七. 实验结果(关键源代码)单词符号输出形式(表格)如下:。
词法分析器实验报告
用户子程序:
void print() { count++; if((fpout=fopen("My.txt","a"))==NULL){
printf("cannot write the file /n"); exit(0); } if(value<=5){ //正常情况下处理方式 switch(value){ case 0:entity[count-1].idproperty="BasicKey";break; case 1:entity[count-1].idproperty="identifier";break; case 2:entity[count-1].idproperty="number";break; case 3:entity[count-1].idproperty="arithmetic-op";break; case 4:entity[count-1].idproperty="relation-op";break; case 5:entity[count-1].idproperty="boundary-op";break; } entity[count-1].idname=yytext; fprintf(fpout,"%d <符号: \"%s\" , 类型:%s > \n",count,entity[count1].idname,entity[count-1].idproperty); }else{ //wrongid时处理方式 errnum+=1; switch(value){ case 6:entity[count-1].idproperty="Mixed number and letter:";break; case 7:entity[count-1].idproperty="Unkown operator:";break; } entity[count-1].idname=yytext; fprintf(fpout,"%d [line:%d]: \"%s\" %s \n",count,linenum,entity[count1].idname,entity[count-1].idproperty); } fclose(fpout); } void main() { printf("please input the PL//0 program file: "); scanf("%s",&filename); if((fpin=fopen(filename,"r"))==NULL){ //打开文件 printf("can't open the file: %s",filename);
词法分析器实验报告
词法分析器实验报告引言:词法分析器(Lexical Analyzer)是编译器的重要组成部分,其主要任务是将源代码转化为一个个独立的词法单元,为语法分析器提供输入。
在本次实验中,我们设计并实现了一个简单的词法分析器,通过对其功能和性能的测试,评估其在不同场景下的表现。
实验目的:1. 确定词法分析器的输入和输出要求;2. 通过构建适当的正则表达式规则,匹配不同类型的词法单元;3. 实现一个高效的词法分析器,确保在处理大型源代码时性能不受影响;4. 对词法分析器的功能和性能进行测试和评估。
实验过程:1. 设计词法分析器的接口:1.1 确定输入:源代码字符串。
1.2 确定输出:词法单元流,每个词法单元包含类型和对应的字符串值。
2. 构建正则表达式规则:2.1 识别关键字:根据编程语言的关键字列表构建正则表达式规则,将关键字与标识符区分开。
2.2 识别标识符:一般由字母、下划线和数字组成,且以字母或下划线开头。
2.3 识别数字:整数和浮点数可以使用不同的规则来识别。
2.4 识别字符串:使用引号(单引号或双引号)包裹的字符序列。
2.5 识别特殊符号:各类操作符、括号、分号等特殊符号需要单独进行规则设计。
3. 实现词法分析器:3.1 读取源代码字符串:逐个字符读取源代码字符串,并根据正则表达式规则进行匹配。
3.2 保存词法单元:将匹配到的词法单元保存到一个词法单元流中。
3.3 返回词法单元流:将词法单元流返回给调用者。
4. 功能测试:4.1 编写测试用例:针对不同类型的词法单元编写测试用例,包括关键字、标识符、数字、字符串和特殊符号。
4.2 执行测试用例:将测试用例作为输入传递给词法分析器,并检查输出是否和预期一致。
4.3 处理错误情况:测试词法分析器对于错误输入的处理情况,如非法字符等。
5. 性能测试:5.1 构建大型源代码文件:生成包含大量代码行数的源代码文件。
5.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);/*此函数将一个pair数组输出到一个文件中*/void OutFile(vector<pair<int,string> > v);/*此函数接受一个字符串数组,对它进行词法分析,返回一个pair型数组*/vector<pair<int,string> > analyst(vector<string> vec);/*此函数判断传递的参数是否为关键字,是的话,返回真,反之返回假*/bool IsKey(string str);2.各模块设计(1).首先根据上面单词符号表及ID和NUM的正规定义式,构造出状态转换图;(2).定义相关的变量和数据结构。
基于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部分的实验报告09005334 顾添锦09005336 汤思彦1. 实验目的:(1)加深对编译原理及编译程序构造过程的理解(2)增强程序设计能力2.实验内容:–Lex输入文件的解析–正规表达式的解析–一个正规表达式到NFA的转换算法实现–多个NFA的合并–NFA的确定化和最小化算法实现–返回状态与返回内容的对应–SeuLex应用3.项目的分工合作和完成情况:顾添锦负责lex输入文件的解析和代码生成。
汤思彦负责从正规表达式到DFA的转换过程。
项目要求中,DFA的最小化算法没有实现。
其他功能都完成了。
4.主要的数据结构定义:NFA和DFA的结点采用自己定义的结构体Anode来存储。
Anode中包括以下成员:1.state : 记录结点的ID。
2.isTer : 标识结点是否是终结态。
3.NFAStates : 用来记录这个结点由哪些NFA状态构成。
4.transition : 用来记录结点的转移情况,即通过某一特定输入,结点状态会转换到哪个结点。
5.action : 记录终结态的动作。
NFAStates采用STL中的set来存储,transition使用multimap来存储。
NFA和DFA本身,通过deque(双端队列)来存储,队列成员是Anode*。
为这个双端队列起别名为Automata.5.主要算法流程描述:1.逐行扫描文件,将用户自定义的类型替换为相应正规式,并返回相应动作。
2.正规式首先经过预处理,将[ ]运算符替换为( ) 和| 结合的形式。
然后第二遍扫描,加入连接符号@3.将正规式转换为后缀表达式。
该算法可以在数据结构书中找到。
4.后缀表达式按照类似算术表达式的方法,采用Thompson算法扫描表达式进行计算,生成子自动机,并且最后得到一个完整的自动机,对应此正规式。
将它的最后一个状态设置为终结态。
5.NFA每生成一个都存储起来。
全部完成后,用一个状态通过空边来连接他们的头结点,完成NFA合并。
(完整版)基于LEX的词法分析器实验报告
定义识别标识符规则
{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}
词法分析器实验报告
词法分析器实验报告班级:12 姓名:郭金龙学号:45一、问题描述设计并实现C语言的词法分析程序,要求如下。
(1)、可以识别出用C语言编写的源程序中的每个单词符号,并以记号的形式输出每个单词符号。
(2)、可以识别并读取源程序中的注释。
(3)、可以统计源程序汇总的语句行数、单词个数和字符个数,其中标点和空格不计算为单词,并输出统计结果(4)、检查源程序中存在的错误,并可以报告错误所在的行列位置。
(5)、发现源程序中存在的错误后,进行适当的恢复,使词法分析可以继续进行,通过一次词法分析处理,可以检查并报告源程序中存在的所有错误。
实验要求:方法1:采用C/C++作为实现语言,手工编写词法分析程序。
—方法2:通过编写LEX源程序,利用LEX软件工具自动生成词法分析程序二、算法思想及实现首先从主题上来看是一个大概的字符/字符串匹配过程,然后在这其中细化到分类包括标识符,关键字,标点符号,数字等等。
这其中在计算一下几个方面的时候比较简单:(1)行数:每次读到回车的时候行数加一(2)单词数:在读标识符和关键字的时候每读到一个计数器加一(3)字符数:除了标点符号和空格以外,每读到一个字符都计数器加一剩下的在判断各种符号的时候以及是否是关键字和标识符的时候,在程序中严格遵守书上给的流程图如下并且输出形式也严格按照书上给的表格如下:三、\四、设计描述主要说说这其中几个比较关键的地方(1)首先要判断是否读到文件末尾,如果是的话要跳出并关闭文件,否则会导致内存泄露(2)考虑需要超前判断的几个字符包括<>,<=,>=等等,这下如果读到第一个字符而下一个字符不是预想中的字符时候要指针回退一个字符,但是要考虑到如果这个字符是在文件末尾的话会出现循环的情况,这也是其中的一个问题(3)关键字的判断上,首先要定义一个关键字数组或者容器,然后通过token里面临时存储的字符串来进行匹配,最后如果匹配成功或者失败要有相应的措施并且每次匹配后一定要清空token。
词法分析器Lex实验报告
实验内容(算法、程序、步骤和方法)
1.基于Lex构造词法分析器的方法
1.1Lex文件格式
Lex文件分成三个部分,分别为definitions、rules以及auxiliary routines,中间用%%分割开。
Definitions包括要加入到生成的C程序的头部的代码,包括#include语句、#define语句及一些全局变量的定义。同时,正则表达式可以在这个部分定义,如identifier的定义:
{LCURVE, '{'} {INT, 'int'} {ID, 't'} {SEMICOLON, ';'}
{ID, 'k'} {ASSIGN, '='} {ID, 'minloc'} {LPARENTHESIS, '('} {ID, 'a'} {COMMA, ','} {ID, 'i'} {COMMA, ','} {ID, 'high'}{RPARENTHESIS, ')'} {SEMICOLON, ';'}
{LCURVE, '{'} {INT, 'int'} {ID, 'i'} {SEMICOLON, ';'} {INT, 'int'} {ID, 'k'} {SEMICOLON, ';'}
{ID, 'i'} {ASSIGN, '='} {ID, 'low'} {SEMICOLON, ';'}
设计2词法分析之基于Lex实现词法分析报告
词法分析程序一、设计目的通过编写并上机调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将其分解成各类单词的词法分析方法。
二、设计要求要求将用模拟语言书写的源程序进行词法分析,输出源程序清单,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);}//标识符定义识别错误的字符串规则当开头为数字的后面为字母的字符串时,是错误的标识符。
词法分析器实验报告[通用]
编译原理实验报告班级:学号:姓名:一、实验题目:词法分析程序二、实验内容:1、主程序设计考虑:主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。
id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。
主程序的工作部分建议设计成便于调试的循环结构。
每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。
2)词法分析过程考虑该过程取名为lexical,它根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词类,产生类号。
对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id 中,将常数存入数组中ci 中,并记录其在表中的位置。
三、程序源代码:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#define LEN sizeof(struct Node)#define NULL 0struct Node{char data;struct Node *next;};void Output1(struct Node*);void Scaner(); /*词法分析*/void Scaner1();void GetBC();void GetChar();void Concat();int IsLetter(char ch);int IsDegit(char ch);int Reserve();void Retract();struct Node *head,*p;char ch; /*全局变量*/char*key[]={"int","char","float","void","const","if","else","do","while","scanf","printf","retu rn","main"}; /*关键字表*/char Token[20]; /*字符数组,存放构成单词的符号串*/char *id[256];int ci [256];int i=0;int j=0;int opt;void main(){head=(struct Node *)malloc(LEN); /*分配头节点存储空间*/if(!head){printf("error");exit(1);}head->next=NULL;head->data=' ';p=head;printf("如果想结束输入就在新的一行的开始输入’$’!\n输入结束后屏幕上会输入你刚输入的代码\n");printf("请输入你的代码:\n");while(1){int i=0;char temp[256];/*每行长度不超过256个字符*/gets(temp); /*输入源程序,以行为单位*/if(temp[0]=='$') break;/*当输入的第一个字符为$时表示输入源代码结束*/p->next=(struct Node *)malloc(LEN);if(!(head->next)){printf("error");exit(1);}// p=head;p=head->next;while(temp[i]!='\0' && i<256) /*将输入的代码以行为单位存入缓冲区*/{p->next=(struct Node *)malloc(LEN);if(!(p->next)){printf("error");exit(1);}p=p->next;i++;}p->data='\n';p->next=NULL; /*尾结点*/}printf("你刚才输入的是代码为:\n");Output1(head); /*扫描缓冲区,输出结果*/p=head->next;printf("经该词法分析器程序处理后输出结果为:\n");printf("注:第一个无素1,2,3,4,5分别表关键字、表标识符、表常数、表运算符、表界符\n");printf(" 第二无素为该单词在各自表中的指针或内部码值\n");// printf("有两种输出格式,可通输入0或1 进行选择");//opt=(int)getchar();while(p->next!=NULL){Scaner();}system("pause");//return 0;}void Output1(struct Node *head) /*扫描缓冲区函数*/{if(!(head)) {printf("error");exit(1);}p=head->next;while(p->next!=NULL){printf("%c",p->data);p=p->next;}printf("\n");}void GetBC() /*若ch中是空白字符,则不停调用getch()直到读入的不是空白字符为止*/{while (ch==' ')GetChar();void GetChar() /*从缓冲区读入一字符*/{ch=p->data;p=p->next;}void Concat() /*将ch中的字符连接到token的后面*/{unsigned int i;i=strlen(Token);if(ch!=' '){Token[i]=ch;Token[i+1]='\0';}}int IsLetter(char ch){return isalpha((int)ch);}int IsDigit(char ch) /*判断ch中的是否是数字*/{return isdigit((int)ch);}int Reserve() /*判断token中的字符串是否是关键字或是标识符*/ {int k;for(k=0;k<13;k++){if(strcmp(key[k],Token)==0)return (k+1);}return 0;}void Retract() /*指针回退一个字符*/{struct Node *Q;Q=head->next;while(Q->next!=p)Q=Q->next;p=Q;void Back(char *a,char *b){printf("(%s,%s)\n",a,b);}void Scaner(){int c;Token[0]=NULL;GetChar();GetBC();if(IsLetter(ch)){while(IsLetter(ch)||IsDigit(ch)) {Concat();GetChar();}Retract();c=Reserve();if(c!=0){printf("<1,%d>\n",c);}else{printf("<2,%d>\n",i);id[i]=Token;i++;}}else if(IsDigit(ch)){while(IsDigit(ch)){Concat();GetChar();}Retract();printf("<3,%d>\n",j);ci[j]=atoi(Token);j++;}elseswitch(ch)case'+': GetChar();if(ch=='+'){printf("<4,39>\n");}Retract();printf("<4,15>\n");break;case'-': GetChar();if(ch=='-'){printf("<4,40>\n");}Retract();printf("<4,16>\n");break;case'&':GetChar();if(ch=='&'){printf("<4,27>\n");}printf("error\n");Retract();case'|':GetChar();if(ch=='|'){printf("<4,28>\n");}Retract();break;case'*':printf("<4,17>\n");break;case'/':printf("<4,18>\n");break;case'%':printf("<4,19>\n");break;case'<': GetChar();if(ch=='='){printf("<4,26>\n");}Retract();break;case'>': GetChar();if(ch=='='){printf("<4,25>\n");}Retract();printf("<4,22>\n");break;case';':printf("<5,35>\n");break;case',': printf("<5,36>\n");break;case'"': printf("<5,37>\n");break;case'{': printf("<5,33>\n");break;case'}':printf("<5,34>\n");break;case'(':printf("<5,31>\n");break;case')':printf("<5,32>\n");break;case'=':GetChar();if(ch=='='){printf("<4,21>\n");}Retract();printf("<5,20>\n");break;case'!':GetChar();if(ch=='='){printf("<5,24>\n");}Retract();printf("<5,29>\n");break;case'\n': break;default: printf("error\n");break;}}四、测试结果:五、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)注:内容一律使用宋体五号字,单倍行间距1、通过这次实验我对词法分析器有了进一步的了解,把理论知识应用于实验中。
编译原理 实验报告(词法分析器)
实验LEX词法分析器自动生成器一、实验内容:用词法分析自动生成器LEX构造一个简单词法分析器,它能识别文件新行并为其添加行号,并将分析结果发送到屏幕上。
二、实验目的:1.掌握LEX源程序的编写方法。
2.掌握自动生成词法分析器LEX的使用方法和工作原理。
LEX源程序*.L通过LEX编译程序,产生一个C语言版本的词法分析程序*.C。
然后通过C语言编译器,将词法分析程序*.C转换成一个可执行文件*.EXE。
再编制一个测试文本文件*.TXT。
用生成的词法分析程序的可执行文件,对测试程序进行词法分析.三、实验要求1.写好实验预习报告;2.编写上机源程序和测试程序;3.写出实验结果;4.实验完后要上交实验报告;四、相关说明LEX上机过程部分:1)利用编辑器如EDIT编写LEX源程序和测试程序,如SHIYAN11.L和TEST.TXT;2)用LEX编译器编译LEX源程序SHIYAN11.L,格式为:LEX SHIYAN11.L↙如果LEX源程序没有语法错误,将得到一个用C语言描述的没有语法错误词法分析器SHIYAN11.C;3)在TC环境下,对SHIYAN11.C进行编译、连接,从而得到可执行的词法分析器SHIYAN11.EXE;4)利用SHIYAN11.EXE对TEST.TXT进行词法分析,格式为:SHIYAN0.EXE<TEST.TXT↙如果没有写测试程序TEST.TXT,则可测试其他某个程序如SHIYAN11.L。
LEX上机过程如下图所示(alt+c):五、实验器材硬件:PC机一台软件:Turbo C、LEX.EXE六、参考程序1.LEX源程序:shiyan11.L%{#include "stdio.h"int lineno=1;()%}line .*\n%%{line} {printf("%2d %s",lineno++,yytext);}%%main(){yylex();return 0;}2.shiyan11.EXE分析shiyan11.L的实验效果如下图所示:。
实验四 Lex词法分析
实验四Lex词法分析1、实验目的和要求通过编制词法分析程序,分析理解一个教学型编译程序的基础上,对其词法分析程序进行部分修改扩充,以加强课堂学习的有关概念和方法,并真正了解词法分析的实质内容。
要求择一种熟悉的高级语言,编制词法分析程序。
2、实验内容定义模拟的简单语言的词法构成,编制词法分析程序,要求将用模拟语言书写的源程序进行词法分析,输出源程序清单,Token文件和错误信息文件,若有错误,必须输出错误在源程序中行号和列号,并将符号表和字符串以文件的形式写出来。
3、实验仪器4、实验学时学习工具flex有详细的使用说明。
想查的话在Linux/Cygwin的控制台里敲man flex 不过在控制台里一页一页的看很烦人,不如敲man flex>flextut.txt 然后用UltraEdit慢慢看。
另外,网上关于flex使用的文章很多。
至于C#Lex,相关的文章不多,遇到问题可以找有关JLex的文档。
写脚本把代码转成Html源文件的第一步应该是替换特殊字符,看看用flex怎么写。
%option noyywrap%%" " {printf(" ");}"<" {printf("<");}">" {printf(">");}"\n" {printf("<br>");}"\t" {printf(" ");}%%int main(){printf("<FONT face=\"Courier New\" size=2>");yylex();printf("</FONT>");}flex的输入文件(.l)文件由%%分成了三部分,大致上可以把他们看作是函数(yylex( ))前,函数内和函数后。
词法分析器(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。
词法分析实验
词法分析实验一、实验题目编写Tiny语言的词法分析程序。
二、实验目的1,构造Tiny词法分析程序,程序要求能对输入的字符串流进行词法分析。
2,在实验的过程中,学会应用单词分析的方法——构造NFA(非确定有穷自动机)和DFA(确定有穷自动机)。
3,使用Lex工具分析词法。
三、实验要求1、独立完成实验2、由老师现场检查程序代码和运行结果3、提交代码实验报告:包含程序代码和运行结果截图四、实验环境操作系统:Windows/Linux开发语言:C/C++开发工具:Cygwin (在windows平台上运行的UNIX模拟环境);Lex词法分析工具。
五、实验内容采用下面两种方式对给定的样本语言Tiny实现一个扫描程序:1、使用Lex自动生成词法分析程序,2、自己编写一个Tiny词法分析程序。
输出结果包含1、打印出符号(Token)所在的源代码中的行数,2、以二元组方式打印符号,例如<1, IF>,3、打印该符号的类型:(保留字(Reserved word)、特殊符号(Special Symbol)和“其他”(Other))。
Tiny语言介绍Tiny语言在语法上是一个由分号分隔开的语句序列。
没有过程,没有声明,所有变量都是整形变量。
Tiny语言有两个控制语句,分别是if语句和repeat语句。
Tiny的记号分为3个典型类型:保留字、特殊符号和“其他”记号。
1,保留字if、then、else、end、repeat、until、read、write2,特殊符号+ - * / = < ( ) ; :=3,其他数(NUM)和标识符(ID),ID和NUM通过以下正则表达式表示:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9除了记号之外,Tiny程序还要遵循以下的词法惯例:注释应放在花括号{...}中,且不可嵌套;代码应是自由格式;空白格由空格、换行符和制表符组成。
实验一词法分析器设计和Lex工具的使用
实验一词法分析器设计和Lex工具的使用一.实验目的:1、掌握词法分析器设计方法。
2、熟悉LEX工具的使用,理解LEX工具的工作原理和利用LEX工具设计词法分析器的方法。
二.实验内容(按以下实验内容完成1、3项中任意一项即可):1、在VC下打开阅读附件一mlex.dsw,阅读工程一mlex和mlex2源程序,mlex为课本P45词法分析器的实现,工程二mlex2采用另一种方式实现P45的状态转换图。
通过该例了解状态自动机的实现方法和手工编写词法分析器的基本方法。
Mlex词法分析器简单说明:功能:从左至右逐个字符地对c语言子集源程序src.txt进行扫描,产生单词符号流token.txt(参见课本,单词用二元组<单词种别,单词值>表示)。
程序框图:输入c语言子集源程序,为文本文件。
注意读到文件结束符EOF意味着分析结束。
输出词法分析程序的运行结果是:输出一个单词序列(屏幕显示或保存在文件中)和一个常数表、一个符号表(保存在文件中)、一个常数表(保存在文件中),并输出错误信息。
说明:单词序列:读入源程序,每从源程序中发现一个符号串构成一个单词,即输出一个二元式(单词种别,单词值)。
其中单词种别用整数说明。
标识符的单词值为其在符号表中的记录号。
非负整常数的单词值为其在常数表中的记录号。
符号表:存放标识符的具体信息,记录格式为(记录号,构成标识符的字符串)。
相同的标识符在符号表中只登录一个记录。
常数表:存放非负整数的具体信息,记录格式为(记录号,构成非负整数的字符串)。
相同的非负整数在符号表中只登录一个记录。
标识符的识别:见下例,分析abc后,应在符号表中登录一项(1,abc),并往单词序列中加一项(6,1),表示单词种别为标识符<6>,单词的具体信息见符号表第1个记录。
常数的识别:见下例,分析134后,应在常数表中登录一项(1,134),并往单词序列中加一项(7,1),表示单词种别为常数<7>,单词的具体信息见常数表第1个记录。
实验二 词法分析lex实验报告
void main() { yylex(); return 0; } int yywrap() { return 1;
/* start the analysis*/
}Leabharlann 编制一个读单词过程从输入的源程序中识别出各个具有独立意义的单词token即基本保留字标识符常量运算符分隔符五大类并依次输出各个单词的内部编码及单词符号自身值
《实验一
词法分析》实验报告
题目
词法分析
日期 2012-10-28
姓名及 (组长)康黎明 swe10029 分工
组员: 陈俊杰 swe10031 组员: 许冬青 swe10033 组员:王吉 swe10028
四、源程序:
%{ 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|main)
《C-语言的词法分析器(基于Lex)》课程设计报告
《C-语⾔的词法分析器(基于Lex)》课程设计报告《编译原理与实践》课程报告课题名称: C-语⾔的词法分析器实现(基于Lex)课题负责⼈名(学号):李恒(0643111198)同组成员名单(⾓⾊):⽆指导教师:于中华评阅成绩:评阅意见:提交报告时间:2007 年12 ⽉31⽇1. ⽬的与意义词法分析是编译原理中⼀个重要的部分。
它可将源程序读作字符⽂件并将其分为若⼲个记号,每⼀个记号都是表⽰源程序中信息单元的字符序列。
词法分析器是翻译步骤的第⼀步,它对于编译器接下来要进⾏的⼯作起着开头的作⽤,因此要想实现对C-语⾔的编译器,词法分析器必不可少。
2. 基于Parser Generator的词法分析器构造⽅法利⽤Parser Generator构造词法分析器规则,⽣成对应的c语⾔及其头⽂件。
然后进⾏编译。
3. C-语⾔词法分析的设计重要数据类型:关键字枚举:typedef enum{ENDFILE, ERROR,/* reserved words */ELSE, IF, INT, RETURN, VOID, WHILE,/* multicharacter tokens */ID, NUM,/* special symbols */PLUS, MINUS, TIMES, OVER, LT, LE, GT, GE, EQU, NEQU,ASSIGN, SEMI, COMMA, LPAREN, RPAREN, LBRKT, RBRKT, LBRC, RBRC, LCOM, RCOM}TokenType;关键字声明:digit [0-9]number {digit}+letter [a-zA-Z]identifier {letter}+newline \nwhitespace [ \t]+c-语⾔的词法规则:"else" {return ELSE;} "if" {return IF;}"int" {return INT;} "return" {return RETURN;} "void" {return VOID;} "while" {return WHILE;} "+" {return PLUS;} "-" {return MINUS;} "*" {return TIMES;} "/" {return OVER;} "<" {return LT;}"<=" {return LE;} ">" {return GT;}">=" {return GE;}"==" {return EQU;}"!=" {return NEQU;} "=" {return ASSIGN;} ";" {return SEMI;} "," {return COMMA;} "(" {return LPAREN;} ")" {return RPAREN;} "[" {return LBRKT;} "]" {return RBRKT;} "{" {return LBRC;} "}" {return RBRC;} {number} {return NUM;} {identifier} {return ID;} {newline} {lineNo++} {whitespace} {/* skip */} "/*" { char c;do{ c = input();if (c == EOF ) break;if (c == '\n' ) lineNo++;} while ( c != '/*');}{return ERROR;}重要处理程序设计:⽂件util.c执⾏输出结果的打印:void printToken(TokenType token, const char* tokenString) { switch (token){case ELSE:case IF:case INT:case RETURN:case VOID:case WHILE:fprintf(listing, "reserved word: %s\n", tokenString);break;case PLUS:fprintf(listing, "+\n");break;case MINUS:fprintf(listing, "-\n");break;case TIMES:fprintf(listing, "*\n");break;case OVER:fprintf(listing, "/\n");break;case LT:fprintf(listing, "<\n");break;case LE:fprintf(listing, "<=\n");break;fprintf(listing, ">\n"); break;case GE:fprintf(listing, ">=\n"); break;case EQU:fprintf(listing, "==\n"); break;case NEQU:fprintf(listing, "!=\n"); break;case ASSIGN: fprintf(listing, "=\n"); break;case SEMI:fprintf(listing, ";\n"); break;case COMMA: fprintf(listing, ",\n"); break;case LPAREN: fprintf(listing, "(\n"); break;case RPAREN: fprintf(listing, ")\n"); break;case LBRKT: fprintf(listing, "[\n"); break;case RBRKT: fprintf(listing, "]\n"); break;case LBRC:fprintf(listing, "{\n");case RBRC:fprintf(listing, "}\n");break;case LCOM:fprintf(listing, "/*\n");break;case RCOM:fprintf(listing, "*/\n");break;case ENDFILE:fprintf(listing,"EOF\n");break;case NUM:fprintf(listing, "NUM,val=%s\n",tokenString); break;case ID:fprintf(listing, "ID, name=%s\n",tokenString); break;case ERROR:fprintf(listing, "ERROR: %s\n",tokenString); break;default:break;}}函数getToken获取下⼀个token:TokenType getToken(void){ static int firstTime = TRUE; TokenType currentToken;if (firstTime){ firstTime = FALSE;lineNo++;yyin = source;yyout = listing;}currentToken = yylex();strncpy(tokenString,yytext,MAXTOKENLEN);if (TraceScan) {fprintf(listing, "\t%d: ", lineNo);printToken(currentToken,tokenString);}return currentToken;}4. 运⾏结果及分析输⼊⽂件如果所⽰:输出结果如图:对于输⼊的每⼀⾏进⾏词法分析,表⽰出保留字,标识符,以及终结符。
(完整)编译原理实验报告(词法分析器 语法分析器)
编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的: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 〈stdio.h〉#include <math.h>#include <string。
h>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]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理课程实验报告实验名称:基于LEX的词法分析器学生姓名:**学生学号: ********** 指导教师毛静一、实验目标自动构造C-语言的的词法分析器,要求能够掌握编译原理的基本理论,,理解编译程序的基本结构,掌握编译各阶段的基本理论和技术,掌握编译程序设计的基本理论和步骤.,增强编写和调试高级语言源程序的能力,掌握词法分析的基本概念和实现方法,熟悉C-语言的各种Token。
二、实验原理及方法Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。
这三个部分由位于新一行第一列的双百分号分开,因此,Lex输入文件的格式如下{definitions}%%{rules}%%{auxiliary routines}而且第一部分用“%{”和“%}”括起来。
第一和第三个部分为C语言的代码和函数定义,第二个部分为一些规则。
定义正则表达式如下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]+构造DFA图三、实验内容●Win7下lex 与 yacc的安装配置;●利用Parser Genarator的词法分析器构造四、实验步骤1)Win7下lex 与 yacc的安装配置1、lex的安装首先,下载下载flex和bison.其次,安装完毕后,将c:\gnuwin32\lib里面的libfl.a和liby.a复制到C:\MinGW\lib 里面。
再者,设置环境变量。
最后,测试安装是否成功。
2、使用lex生成此法分析器:新建文本文件,更改名称为a.lex,敲入下面代码-------词法分析器的源代码%{int wordCount = 0;int numcount = 0;%}chars [A-Za-z\_\'\.\"]numbers ([0-9])+delim [" "\n\t]whitespace {delim}+words {chars}+%%while {ECHO; printf("%s\n",yytext);}{words} { wordCount++;/* increase the word count by one*/ }{whitespace} { /* do nothing*/ }([0-9])+ { numcount++; /* one may want to add some processing here*/ } %%void main(){printf("ok1\n");yylex(); /* start the analysis*/printf("ok2\n");printf(" No of words: %d\n number: %d\n", wordCount, numcount);return 0;}int yywrap(){return 1;}2、新建文本文件,更名为b.c,敲入下面代码 --------此为输入源代码asd asdf 23 qa1b2!#@while3、打开菜单,运行,输入cmd。
输入:cd 文件夹路径输入:flex a.lex 回车后生成一个 lex.yy.c文件输入:gcc -o a lex.yy.c -lfl 回车后生成一个a.exe文件,现在我们已得到了一个简易的词法分析器,下面就是运用次词法分析器,分析下b.c文件输入:a.exe <b.c> a.txt 回车后生成一个a.txt文件2)利用Parser Genarator的词法分析器构造在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++;}//遇到回车自动加行号忽略●辅助程序集中包括主函数main ()和辅助函数toupper()。
●程序代码实现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();}五、测试过程及结果(1)Win7下lex 与 yacc的安装配置测试安装是否成功,测试结果如图所示,当前文件夹多了两个文件,安装成功:(2)利用Parser Genarator的词法分析器构造六、实验总结:通过本实验,我了解了Lex的用法,并构造了Parser Genarator编译器。