编译原理实验-用LEX(FLEX)生成PL语言的词法分析器

实训前面有的知识点就不讲了,大家仔细看一下。

第一关:什么是lex/flex?

        测试集内容已经告知了,所以已通关为目的的话,我们可以面向答案进行编程。

        测试集给出的字符串是"Hello", "G"  ,"" ,"FA21", 'FA',题目需要识别的字符串是前三个,首先可以在要识别的正规集对应的正规式中排除 FA21,因此可以构造出 [a-zBCDEG-Z]*,可以不包含数字,反正测试集中没有。但是这样识别不出 ‘ ’ “ ”,打印出的结果里面有,我们可以在行动中加上,也就是printf里面加上,不过要用到转移字符。

        接下来就是对 “” 的识别,我们可以把这个单独搞一个出来。(其实这三个字符串都可以直接这样)。代码如下:

[a-zBCDEG-Z]*      {printf("\"%s\": Hit!\n",yytext);}
"\"\""             {printf("%s: Hit!\n",yytext);}

直接一点就是这样:(只写了两个试试)

"Hello"      {printf("\"%s\": Hit!\n",yytext);}
"\"\""             {printf("%s: Hit!\n",yytext);}

第二关:用flex生成PL语言的词法分析器

 参考文章http://t.csdn.cn/KJk89

        这一关我们需要把那个表上的所有字符都要识别,个人认为第三个正规式就特别有技巧,比较难。

INTCON			[\-]?[0-9][0-9]*
IDENT			[A-Za-z][A-Za-z0-9]*
CHARCON			['][^']*[']
OFSYM			of
ARRAYSYM		array
MODSYM			mod
ANDSYM			and
ORSYM			or
NOTSYM			not
PROGRAMSYM		"program"
BEGINSYM		begin
ENDSYM			end
IFSYM			if
THENSYM			then
ELSESYM			else
WHILESYM		while
DOSYM			do
CALLSYM			call
CONSTSYM		const
TYPESYM			type
VARSYM			var
PROCSYM			procedure
ERROR			[~!@#$%^&_]?|\\

PLUS			\+
MINUS			\-
TIMES			\*
DIVSYM			\/
BECOME			:=
EQL				\=
NEQ				<>
LEQ				<=
LSS				\<
GEQ				>=
GTR				\>
LBRACK			\[
RBRACK			\]
LPAREN			\(
RPAREN			\)
COMMA			\,
SEMICOLON		\;
PERIOD			\.
COLON			\:

识别后的动作可以根据答案反馈进行修改都是一些简单的调整:


{OFSYM}			{printf("%s: OFSYM NULL\n", yytext);}
{ARRAYSYM}		{printf("%s: ARRAYSYM NULL\n", yytext);}
{MODSYM}		{printf("%s: MODSYM NULL\n", yytext);}
{ANDSYM}		{printf("%s: ANDSYM NULL\n", yytext);}
{ORSYM}			{printf("%s: ORSYM NULL\n", yytext);}
{NOTSYM}		{printf("%s: NOTSYM NULL\n", yytext);}
{PROGRAMSYM}	{printf("%s: PROGRAMSYM NULL\n", yytext);}
{BEGINSYM}		{printf("%s: BEGINSYM NULL\n", yytext);}
{ENDSYM}		{printf("%s: ENDSYM NULL\n", yytext);}
{IFSYM}			{printf("%s: IFSYM NULL\n", yytext);}
{THENSYM}		{printf("%s: THENSYM NULL\n", yytext);}
{ELSESYM}		{printf("%s: ELSESYM NULL\n", yytext);}
{WHILESYM}		{printf("%s: WHILESYM NULL\n", yytext);}
{DOSYM}			{printf("%s: DOSYM NULL\n", yytext);}
{CALLSYM}		{printf("%s: CALLSYM NULL\n", yytext);}
{CONSTSYM}		{printf("%s: CONSTSYM NULL\n", yytext);}
{TYPESYM}		{printf("%s: TYPESYM NULL\n", yytext);}
{VARSYM}		{printf("%s: VARSYM NULL\n", yytext);}
{PROCSYM}		{printf("%s: PROCSYM NULL\n", yytext);}


{INTCON}		{printf("%s: INTCON %s\n", yytext, yytext);}
{IDENT}			{printf("%s: IDENT %s\n", yytext, yytext);}
{CHARCON}       {printf("%s: CHARCON %s\n", yytext, yytext);}

{PLUS}			{printf("%s: PLUS NULL\n", yytext);}
{MINUS}			{printf("%s: MINUS NULL\n", yytext);}
{TIMES}			{printf("%s: TIMES NULL\n", yytext);}
{DIVSYM}		{printf("%s: DIVSYM NULL\n", yytext);}
{BECOME}		{printf("%s: BECOME NULL\n", yytext);}
{EQL}			{printf("%s: EQL NULL\n", yytext);}
{NEQ}			{printf("%s: NEQ NULL\n", yytext);}
{LEQ}			{printf("%s: LEQ NULL\n", yytext);}
{LSS}			{printf("%s: LSS NULL\n", yytext);}
{GEQ}			{printf("%s: GEQ NULL\n", yytext);}
{GTR}			{printf("%s: GTR NULL\n", yytext);}

{LBRACK}		{printf("%s: LBRACK NULL\n", yytext);}
{RBRACK}		{printf("%s: RBRACK NULL\n", yytext);}
{LPAREN}		{printf("%s: LPAREN NULL\n", yytext);}
{RPAREN}		{printf("%s: RPAREN NULL\n", yytext);}
{COMMA}			{printf("%s: COMMA NULL\n", yytext);}
{SEMICOLON}		{printf("%s: SEMICOLON NULL\n", yytext);}
{PERIOD}		{printf("%s: PERIOD NULL\n", yytext);}
{COLON}			{printf("%s: COLON NULL\n", yytext);}
{ERROR}         {printf("%s: ERROR\n", yytext);}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实验词法分析器 一、实验目的 掌握词法分析器的构造原理,掌握手工编程或LEX编程方法之一。 二、实验内容 编写一个LEX源程序,使之生成一个词法分析器,能够输入的源程序转换为单词序列输出。 三、实验环境 Flex+VC6.0 四、实验注意 1.Id正则表达式:{letter}({letter}|{digit})* 2.Num正则表达式:{digit}+(\.{digit}+)?(E[+-]?{digit}+)? 3.注释:(\/\*(.)*\*\/) 4.关键字再加上其他字符就又能编程id,所以在词法分析时,id的判断应该放在关键字前面,这样才不会误判 5.由于本程序知识简单的打印数字,因此没有考虑数字的转换 6.">="比">"多一个字符,它应该放在前面判断,其他类似的也应该如此安排 五、实验代码 ******************************************************************************* 实验文件:lex.l、lex.yy.c 实验结果:lex.exe 运行方式:打开lex.exe,弹出input.txt,在其中输入所要测试的程序,保存并关闭,即可在output.txt中看到所得结果 ******************************************************************************* %{ void Install(char *type); %} %option noyywrap delim [ \t] newline [\n] digit [0-9] num {digit}+(\.{digit}+)?(E[+-]?{digit}+)? letter [A-Za-z] id {letter}({letter}|{digit})* key ("if"|"while"|"do"|"break"|"true") basic ("int"|"float"|"bool"|"char") op (">="|""|"<"|"="|"!="|"+"|"-"|"*"|"/") comment (\/\*(.)*\*\/) %% delim {;} newline {printf("\n");} {num} {Install("Num");} {key} {Install("Key");} {basic} {Install("Basic");} {op} {Install("Op");} ";" {Install("Comma");} {id} {Install("ID");} {comment} {Install("Comment");} "(" | "[" | "{" {Install("lbracket");} ")" | "]" | "}" {Install("rbracket");} %% void Install(char *s) { fprintf(yyout, "%s:%s ", s, yytext); } int main() { printf("please input the test program in input.txt\n"); system("input.txt"); yyin = fopen("input.txt", "r"); yyout = fopen("output.txt", "w" ); yylex(); fclose(yyout); fclose(yyin); printf("analysis result in output.txt\n"); system("output.txt"); return 0; } 六、实验小结 本次的实验由于使用了flex,所以代码较短,麻烦的事flex的正则式表达,由于该使用规则只有简单介绍,而网上找的教程难免有比重就轻之嫌,所以得到上述表达式着实费力,且有的没有成功,例如bracket的(\ ((.)*\ ))或者("("(.)*")")使用时都没有成功,所以便单独写出,有点不伦不类。至于其他的,都较为简单,完。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值