实验要求:
借助flex工具实现一个词法分析器,识别出SysY代码中的所有终结符,然后按照单词符号出现顺序依次输出: 原始单词符号、该符号出现的行数、该符号出现的列数起始与终止位置。
实验方法:
主要采用了穷举标识符的方式进行识别,其他数字类内容采用了正则表达式进行识别,通过检测换行符维护当前行数,通过全局变量判断当前识别内容是否位于注释范围内,如果被注释掉了则输出fake标记
flex代码如下:
%option noyywrap
%{
#include <stdio.h>
#include <stdlib.h>
long long line_num=1;
long long col_num=1;
long long My_yylineno=1;
long long old_My_yylineno=1;
int isLineAnno=0;
int isPartAnno=0;
%}
%%
/*快乐标识符*/
auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*快乐变量名*/
[a-zA-Z_][a-zA-Z0-9_]* {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*快乐整数常量*/
[-+]?[1-9][0-9]* {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*不快乐的八进制数*/
0[0-7]+ {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*不快乐的十六进制数*/
0x[0-9a-fA-F]+ {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*快乐小数常量*/
[-+]?[0-9]+\.[0-9]*|\.[0-9]+ {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*快乐科学计数法*/
[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*快乐字符串*/
\"(\\.|[^\\"])*\" {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*快乐运算符*/
"=="|"+"|"-"|"*"|"/"|"="|"<"|">"|"!"|"&&"|\|\||","|";"|"("|")"|"{"|"}"|"["|"]" {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
col_num += strlen(yytext);
}
/*行注释*/
\/\/ {
{
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
{
if(isPartAnno)
{
isPartAnno = 1;
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
}
else
{
isLineAnno =1;
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
}
}
col_num += strlen(yytext);
}
}
/*开始注释*/
\/\* {
{
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
{
if(!isPartAnno)
{
isPartAnno = 1;
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
}
else
{
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
}
}
col_num += strlen(yytext);
}
}
/*结束注释*/
\*\/ {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno)
printf("%s \t\t %d \t %d \t %d - Fake\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
else
{
if(isPartAnno)
{
isPartAnno = 0;
printf("%s \t\t %d \t %d \t %d\n", yytext, My_yylineno, col_num,col_num + strlen(yytext));
}
else
{
printf("Part Annotation error-No start but finish\n");
exit(1);
}
}
col_num += strlen(yytext);
}
/*换行*/
[\n] {
isLineAnno = 0;
printf("n");
My_yylineno++;
}
/*制表符*/
[\t] {
printf("%s \t %d \t %d - t\n", yytext, My_yylineno, col_num);
My_yylineno++;
}
/*不认识你*/
. {
if(My_yylineno>old_My_yylineno)
{
col_num=1;
old_My_yylineno=My_yylineno;
}
if(isLineAnno || isPartAnno)
printf("%s(Fake)\n", yytext);
else
printf("%s", yytext);
col_num += strlen(yytext);
}
%%
int main(int argc, char *argv[]) {
while(1)
{
int ijk=-1;
printf("Please input which one do you want, 0 for example.sy, i for i.sy\n");
scanf("%d",&ijk);
FILE *file = NULL;
switch(ijk)
{
case 0:
file = fopen("example.sy", "r");
break;
case 1:
file = fopen("test-cases\\1.sy", "r");
break;
case 2:
file = fopen("test-cases\\2.sy", "r");
break;
case 3:
file = fopen("test-cases\\3.sy", "r");
break;
case 4:
file = fopen("test-cases\\4.sy", "r");
break;
case 5:
file = fopen("test-cases\\5.sy", "r");
break;
case 6:
file = fopen("test-cases\\6.sy", "r");
break;
default:
printf("swtich file error");
exit(1);
}
printf("\n------------------Now Starting case %d-------------------\n\n",ijk);
printf("What \t\t Line \t Col_Start \t Col_Finish\n");
line_num=1;
col_num=1;
My_yylineno=1;
old_My_yylineno=1;
isLineAnno=0;
isPartAnno=0;
if (file == NULL)
{
printf("Failed to open the file in %d.\n",ijk);
exit(1);
}
yyin = file;
yylex();
}
return 0;
}