编译原理——C语言词法分析器学号21131603姓名黎红波1、实验内容与要求基于C语言的字符集,编写C语言的词法分析器;要求能检查出输入程序中的不合法字符,输出该非法字符并显示所在行号;要求输出词法分析后的结果,并显示对应Token所在程序中的行号;要求能够过滤掉注释内容;2、实验方法利用flex工具进行分词,写出各种单词分类的正则表达式,利用flex工具自带的功能在linux下通过编写.l文件生成相应具有C语言词法分析功能的程序;3、分析与设计单词分类保留字:if|then|else|int|float|double|bool|char|printf|scanf|return|main|while|do|for|struct|void|break|const|static|auto|short|long|union|enum|typedef|unsigned|signed|extern|register|volatile|switch|case|goto|continue|default|sizeof|include标识符:[a-z_A-Z][a-z_A-Z0-9]*常量:1)字符串常量:\[^\n]+\2)整型常量:([-+]?[1-9][0-9]*)|03)浮点常量:[-+]?[0-9]*\.[0-9]+4)字符常量:\'[^'\n]+\'特殊符号:([\=\+\-\*\/\&\!\|\%\.])|([\+\-\*\/\%\\\=][=])限界符:[\{\}\[\]\(\)\,\;]注释判断:\/\/[^\n]*\n\/\*(.)*\*\/利用yylineno来记录程序分析时所在行号,yytext记录当前正在分析的串;Analyse.l文件编写思路:当遇到上述分类中的匹配就输出对于行号和正在分析的串,当遇到空格、Tab及注释就直接跳过;没遇到一次’\n’则yylineno就增加1,如果都没有匹配成功则最后可以输出该字符不是C语言字符集里面的符号。4、实验结果与分析对程序data.c进行分析:data.c:#includestdio.hintmain(){inta=0;intb+=a;//这是注释,编译期间会被忽略itnc=3.14;c=a+b;d=helloworld;c='c';return0;}测试截图如下:5、不足1、程序中略过了已#开头的行,对include和宏定义没有进行分析;2、对于/**/格式的注释,利用yylineno记录行数时只能记录在程序中的行号,没有包括注释中所包括的行号;6、源码展示(仅展示.l文件里面的内容)analyse.l:%{#includestdio.h#includestdlib.h%}INTEGER([-+]?[1-9][0-9]*)|0FLOAT[-+]?[0-9]*\.[0-9]+STR\[^\n]+\CHAR\'[^'\n]+\'ID[a-z_A-Z][a-z_A-Z0-9]*SPEC([\=\+\-\*\/\&\!\|\%\.])|([\+\-\*\/\%\\\=][=])LIM[\{\}\[\]\(\)\,\;]%%\#[^\n]*\n{}\/\/[^\n]*\n{}\/\*(.)*\*\/{}{INTEGER}{printf(Line%d:(Integer,%s)\n,yylineno,yytext);}{FLOAT}{printf(Line%d:(Float,%s)\n,yylineno,yytext);}if|then|else|int|float|double|bool|char|printf|scanf|return|main|while|do|for|struct|void|break|const|static|auto|short|long|union|enum|typedef|unsigned|signed|extern|register|volatile|switch|case|goto|continue|default|sizeof|include{printf(Line%d:(KeyWords,%s)\n,yylineno,yytext);}{STR}{printf(Line%d:(Str,%s)\n,yylineno,yytext);}{CHAR}{printf(Line%d:(Char,%s)\n,yylineno,yytext);}{ID}{printf(Line%d:(Id,%s)\n,yylineno,yytext);}{SPEC}{printf(Line%d:(Special,%s)\n,yylineno,yytext);}{LIM}{printf(Line%d:(LimitDomain,%s)\n,yylineno,yytext);}[\t]+{}{}\n{yylineno++;}.{printf(Line%d:illegalcharacter%s\n,yylineno,yytext);}%%intyywrap(){return1;}voidmain(intargc,char**argv){if(argc1)yyin=fopen(argv[1],r);elseyyin=stdin;yylex();}