我正在编写一个 lex 代码,其中的正则表达式部分与详细部分中的完全一样。我的主要问题是文本的 RE
I am writing a lex code in which the regular expression section is given exactly like in the detailed section. Main problem I have is the RE for text
%{
#define FUNCT 300
#define IDENTIFIER 301
#define ASSGN 302
#define INTEGER 303
#define PRINT 304
#define TEXT 305
#define INPUT 306
#define CONTINUE 307
#define RETURN 308
#define IF 309
#define THEN 310
#define ENDIF 311
#define ELSE 312
#define WHILE 313
#define DO 314
#define ENDDO 315
#define END 316
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_SYM 200
int found;
void initialize();
void create(char *lexeme, int scope, char type, char usage);
int readsymtab(char *lexeme, int scope, char usage);
%}
%%
[\t ]+ {}
= {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ASSGN) ;}
print {int found = readsymtab(yytext,0,'L'); //line 39
if(found == -1)
{
create(yytext,0,'S','L');
};
return(PRINT) ;}
input {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(INPUT) ;}
continue {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(CONTINUE) ;}
return {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(RETURN) ;}
if {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(IF) ;}
then {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(THEN) ;}
endif {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ENDIF) ;}
else {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ELSE) ;}
while {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(WHILE) ;}
do {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(DO) ;}
enddo {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ENDDO) ;}
end {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(END);
exit(0); ;}
funct {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(FUNCT) ;}
[0-9]+ {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'I','L');
};
return(FUNCT) ;}
[a-zA-Z]+ {int found = readsymtab(yytext,0,'I');
if(found == -1)
{
create(yytext,0,'S','I');
};
return(IDENTIFIER) ;}
\"[^\"\n]+|[\n]+\" {int found = readsymtab(yytext,0,'L'); //line130
if(found == -1)
{
create(yytext,0,'S','L');
};
return(TEXT) ;}
. {return(yytext[0]) ;}
%%
//new variable declaration
int num;
int scope;
struct symbtab
{
char Lexeme [18];
int Scope;
char Type;
char Usage;
int Reference;
};
struct symbtab arr_symtab[200]; //data structure in which the symbol table entries are stored
void print_fn() //function which actually prints the symbol tabel in columnar form
{
int rows;
printf("Row No Lexeme Scope Type Usage Reference\n");
for (rows=0; rows<=num; rows++){
printf("%6d %-16s %-7d %-7c %-7c %-7d \n",rows, arr_symtab[rows].Lexeme,arr_symtab[rows].Scope,arr_symtab[rows].Type,arr_symtab[rows].Usage,arr_symtab[rows].Reference);
}
}
void initialize() //function which enteres the initial value into the symbol table
{
num = -1;
int scope = 0;
char lexeme[18]= "FRED";
char type = 'I';
char usage = 'L';
create(lexeme,scope,type,usage);
}
void create(char *lexeme, int scope, char type, char usage) //function which creates a new entry in the symbol table
{
int reference;
if(type=='I' && usage =='L')
reference = atoi(lexeme);
else
reference = -1;
num = num+1;
strcpy(arr_symtab[num].Lexeme, lexeme);
arr_symtab[num].Scope = scope;
arr_symtab[num].Type = type;
arr_symtab[num].Usage = usage;
arr_symtab[num].Reference = reference;
}
int readsymtab(char *lexeme, int scope, char usage) //function which checks if the entry is already in the table or not and the takes the required action
{
for(int i=num; i>=0; i--){
int comp = strcmp(arr_symtab[i].Lexeme, lexeme);
if(comp==0 && arr_symtab[i].Scope==scope && arr_symtab[i].Usage==usage)
{
return i;
}
else
{
return -1;
}
}
}
int main()
{
//other lines
printf("\n COURSE: CSCI50200 NAME: Aryan Banyal NN: 01 Assignment #: 04 \n");
initialize();
yylex();
print_fn();
printf("End of test.\n");
return 0;
}
int yywrap ()
{
return 1;
}
以下是打印“aryan banyal”的输出
COURSE: CSCI50200 NAME: Aryan Banyal NN: 01 Assignment #: 04
--(end of buffer or a NUL)
--accepting rule at line 39 ("print")
Row No Lexeme Scope Type Usage Reference
0 FRED 0 I L 0
1 print 0 S L -1
End of test.
如您所见,它甚至没有转到“aryan banyal”部分,只是打印并退出...
以下是“aryan banyal”
的输出
COURSE: CSCI50200 NAME: Aryan Banyal NN: 01 Assignment #: 04
--(end of buffer or a NUL)
--accepting rule at line 130 (""aryan banyal")
Row No Lexeme Scope Type Usage Reference
0 FRED 0 I L 0
1 "aryan banyal 0 S L -1
End of test.
第 1 行应该是 aryan banyal,但由于某种原因前面有一个 "。
您有(至少)三个(有些)不相关的问题。
使用词法扫描器
您的代码在读取单个标记后停止,因为您只调用了 yylex()
一次(并忽略了它 return 的内容)。 yylex()
return 每次调用时都是一个标记;如果要扫描整个文件,则需要在循环中调用它。遇到输入结束会return0。
理解模式
模式\"[^\"\n]+|[\n]+\"
中间有一个|
;该运算符匹配它周围的任一模式。所以你正在匹配 \"[^\"\n]+
或 [\n]+\"
。第一个匹配单个双引号,后跟任意数量的字符(但至少一个),不能是引号或换行符。这样匹配 "aryan banyal
没有结束引号但包括开始引号。备选方案的后半部分将匹配任意数量的字符(同样,至少一个),所有这些字符要么是反斜杠,要么是字母 n
,然后是一个双引号。
(我不明白这个模式背后的想法,它几乎肯定不是你想要的。如果你在 "aryan banyal
的比赛后再次调用 yylex
,结束报价会not 已被匹配,因为它将是紧接的下一个字符,并且该模式坚持认为它前面至少有一个反斜杠或 n
。(也许你打算这样做是一个换行符,但也没有一个。)
我想您可能想要匹配整个带引号的字符串,然后只保留引号之间的部分。如果您正确编写了模式,那就是它会匹配的内容,然后您需要删除双引号。我将把编写正确的模式作为练习。您可能想阅读 Flex 手册中的简短 description of Flex patterns;您的 class 笔记中可能也有一些信息。
只选择匹配的一部分
删除令牌开头的引号很容易。所需要的只是在 yytext
上加一。要去掉末尾的那个,您需要用 [=22=]
覆盖它,从而提前一个字符终止字符串。这很容易做到,因为 Flex 在变量 yyleng
中为您提供了匹配的长度。所以你可以设置 yytext[yyleng - 1] = '[=24=]'
然后用 yytext + 1
.
调用你的符号 table 函数
如果以上段落没有意义,您应该复习任何关于 C 中字符串处理的介绍性文本。请记住,在 C 中,字符串不过是一个以 0 结尾的单个字符(小整数)的数组。这使得一些事情很容易做,而另一些事情则有点痛苦(但从不神秘)。
%{
#define FUNCT 300
#define IDENTIFIER 301
#define ASSGN 302
#define INTEGER 303
#define PRINT 304
#define TEXT 305
#define INPUT 306
#define CONTINUE 307
#define RETURN 308
#define IF 309
#define THEN 310
#define ENDIF 311
#define ELSE 312
#define WHILE 313
#define DO 314
#define ENDDO 315
#define END 316
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_SYM 200
int found;
void initialize();
void create(char *lexeme, int scope, char type, char usage);
int readsymtab(char *lexeme, int scope, char usage);
%}
%%
[\t ]+ {}
= {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ASSGN) ;}
print {int found = readsymtab(yytext,0,'L'); //line 39
if(found == -1)
{
create(yytext,0,'S','L');
};
return(PRINT) ;}
input {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(INPUT) ;}
continue {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(CONTINUE) ;}
return {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(RETURN) ;}
if {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(IF) ;}
then {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(THEN) ;}
endif {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ENDIF) ;}
else {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ELSE) ;}
while {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(WHILE) ;}
do {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(DO) ;}
enddo {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(ENDDO) ;}
end {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(END);
exit(0); ;}
funct {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'S','L');
};
return(FUNCT) ;}
[0-9]+ {int found = readsymtab(yytext,0,'L');
if(found == -1)
{
create(yytext,0,'I','L');
};
return(FUNCT) ;}
[a-zA-Z]+ {int found = readsymtab(yytext,0,'I');
if(found == -1)
{
create(yytext,0,'S','I');
};
return(IDENTIFIER) ;}
\"[^\"\n]+|[\n]+\" {int found = readsymtab(yytext,0,'L'); //line130
if(found == -1)
{
create(yytext,0,'S','L');
};
return(TEXT) ;}
. {return(yytext[0]) ;}
%%
//new variable declaration
int num;
int scope;
struct symbtab
{
char Lexeme [18];
int Scope;
char Type;
char Usage;
int Reference;
};
struct symbtab arr_symtab[200]; //data structure in which the symbol table entries are stored
void print_fn() //function which actually prints the symbol tabel in columnar form
{
int rows;
printf("Row No Lexeme Scope Type Usage Reference\n");
for (rows=0; rows<=num; rows++){
printf("%6d %-16s %-7d %-7c %-7c %-7d \n",rows, arr_symtab[rows].Lexeme,arr_symtab[rows].Scope,arr_symtab[rows].Type,arr_symtab[rows].Usage,arr_symtab[rows].Reference);
}
}
void initialize() //function which enteres the initial value into the symbol table
{
num = -1;
int scope = 0;
char lexeme[18]= "FRED";
char type = 'I';
char usage = 'L';
create(lexeme,scope,type,usage);
}
void create(char *lexeme, int scope, char type, char usage) //function which creates a new entry in the symbol table
{
int reference;
if(type=='I' && usage =='L')
reference = atoi(lexeme);
else
reference = -1;
num = num+1;
strcpy(arr_symtab[num].Lexeme, lexeme);
arr_symtab[num].Scope = scope;
arr_symtab[num].Type = type;
arr_symtab[num].Usage = usage;
arr_symtab[num].Reference = reference;
}
int readsymtab(char *lexeme, int scope, char usage) //function which checks if the entry is already in the table or not and the takes the required action
{
for(int i=num; i>=0; i--){
int comp = strcmp(arr_symtab[i].Lexeme, lexeme);
if(comp==0 && arr_symtab[i].Scope==scope && arr_symtab[i].Usage==usage)
{
return i;
}
else
{
return -1;
}
}
}
int main()
{
//other lines
printf("\n COURSE: CSCI50200 NAME: Aryan Banyal NN: 01 Assignment #: 04 \n");
initialize();
yylex();
print_fn();
printf("End of test.\n");
return 0;
}
int yywrap ()
{
return 1;
}
以下是打印“aryan banyal”的输出
COURSE: CSCI50200 NAME: Aryan Banyal NN: 01 Assignment #: 04
--(end of buffer or a NUL)
--accepting rule at line 39 ("print")
Row No Lexeme Scope Type Usage Reference
0 FRED 0 I L 0
1 print 0 S L -1
End of test.
如您所见,它甚至没有转到“aryan banyal”部分,只是打印并退出... 以下是“aryan banyal”
的输出 COURSE: CSCI50200 NAME: Aryan Banyal NN: 01 Assignment #: 04
--(end of buffer or a NUL)
--accepting rule at line 130 (""aryan banyal")
Row No Lexeme Scope Type Usage Reference
0 FRED 0 I L 0
1 "aryan banyal 0 S L -1
End of test.
第 1 行应该是 aryan banyal,但由于某种原因前面有一个 "。
您有(至少)三个(有些)不相关的问题。
使用词法扫描器
您的代码在读取单个标记后停止,因为您只调用了 yylex()
一次(并忽略了它 return 的内容)。 yylex()
return 每次调用时都是一个标记;如果要扫描整个文件,则需要在循环中调用它。遇到输入结束会return0。
理解模式
模式\"[^\"\n]+|[\n]+\"
中间有一个|
;该运算符匹配它周围的任一模式。所以你正在匹配 \"[^\"\n]+
或 [\n]+\"
。第一个匹配单个双引号,后跟任意数量的字符(但至少一个),不能是引号或换行符。这样匹配 "aryan banyal
没有结束引号但包括开始引号。备选方案的后半部分将匹配任意数量的字符(同样,至少一个),所有这些字符要么是反斜杠,要么是字母 n
,然后是一个双引号。
(我不明白这个模式背后的想法,它几乎肯定不是你想要的。如果你在 "aryan banyal
的比赛后再次调用 yylex
,结束报价会not 已被匹配,因为它将是紧接的下一个字符,并且该模式坚持认为它前面至少有一个反斜杠或 n
。(也许你打算这样做是一个换行符,但也没有一个。)
我想您可能想要匹配整个带引号的字符串,然后只保留引号之间的部分。如果您正确编写了模式,那就是它会匹配的内容,然后您需要删除双引号。我将把编写正确的模式作为练习。您可能想阅读 Flex 手册中的简短 description of Flex patterns;您的 class 笔记中可能也有一些信息。
只选择匹配的一部分
删除令牌开头的引号很容易。所需要的只是在 yytext
上加一。要去掉末尾的那个,您需要用 [=22=]
覆盖它,从而提前一个字符终止字符串。这很容易做到,因为 Flex 在变量 yyleng
中为您提供了匹配的长度。所以你可以设置 yytext[yyleng - 1] = '[=24=]'
然后用 yytext + 1
.
如果以上段落没有意义,您应该复习任何关于 C 中字符串处理的介绍性文本。请记住,在 C 中,字符串不过是一个以 0 结尾的单个字符(小整数)的数组。这使得一些事情很容易做,而另一些事情则有点痛苦(但从不神秘)。