目前正在使用 Flex 扫描定义 C 子集的语法。这是 .l 文件。
/*definitions*/
%{
#include <stdio.h>
int yylex(void);
%}
/*rules*/
%%
"int" {printf("TYPE_INT %s\n",yytext);}
"float" {printf("TYPE_FLOAT %s\n",yytext);}
"char" {printf("TYPE_CHAR %s\n",yytext);}
"bool" {printf("TYPE_BOOL %s\n",yytext);}
"while" {printf("WHILE %s\n",yytext);}
"do" {printf("DO %s\n",yytext);}
"for" {printf("FOR %s\n",yytext);}
"printf" {printf("PRINTF %s\n",yytext);}
"scanf" {printf("SCANF %s\n",yytext);}
"if" {printf("IF %s\n",yytext);}
"elif" {printf("ELIF %s\n",yytext);}
"else if" {printf("ELSE_IF %s\n",yytext);}
"else" {printf("ELSE %s\n",yytext);}
"true" {printf("TRUE %s\n",yytext);}
"false" {printf("FALSE %s\n",yytext);}
"void" {printf("VOID %s\n",yytext);}
"main" {printf("MAIN %s\n",yytext);}
"return" {printf("RETURN %s\n",yytext);}
[a-zA-Z_][a-zA-Z0-9]* {printf("IDENTIFIER %s\n",yytext);}
[-+]?(([1-9][0-9]*)|0) {printf("INTEGER %s\n",yytext);}
[-+]?[0-9]+\.[0-9]+ {printf("FLOAT %s\n",yytext);}
\"[^\"\n]*\" {printf("STRING %s\n",yytext);}
"," {printf("COMMA %s\n",yytext);}
";" {printf("SEMICOLON %s\n",yytext);}
"{" {printf("LEFT_BRACE %s\n",yytext);}
"}" {printf("RIGHT_BRACE %s\n",yytext);}
"(" {printf("LEFT_PAREN %s\n",yytext);}
")" {printf("RIGHT_PAREN %s\n",yytext);}
"[" {printf("LEFT_BRACKET %s\n",yytext);}
"]" {printf("RIGHT_BRACKET %s\n",yytext);}
"-" {printf("MINUS %s\n",yytext);}
"+" {printf("PLUS %s\n",yytext);}
"*" {printf("MULTIPLY %s\n",yytext);}
"/" {printf("DIVIDE %s\n",yytext);}
"\\" {printf("BACKSLASH %s\n",yytext);}
"%" {printf("MODULUS %s\n",yytext);}
"==" {printf("EQUALS %s\n",yytext);}
"!=" {printf("NOT_EQUALS %s\n",yytext);}
"<" {printf("LESS_THAN %s\n",yytext);}
">" {printf("GREATER_THAN %s\n",yytext);}
"<=" {printf("LESS_THAN_OR_EQUAL %s\n",yytext);}
">=" {printf("GREATER_THAN_OR_EQUAL %s\n",yytext);}
"=" {printf("ASSIGN %s\n",yytext);}
"&&" {printf("LOGICAL_AND %s\n",yytext);}
"||" {printf("LOGICAL_OR %s\n",yytext);}
"!" {printf("LOGICAL_NOT %s\n",yytext);}
[" "|\t|\n|\f|\v] {printf("WHITESPACE\n");}
. {printf("UNRECOGNIZED_CHARACTER %s\n",yytext);}
%%
/*for when we use multipe input files*/
int yywrap(void){
return 1;
}
/*main driver function that takes */
int main(int argc, char *argv[]){
if(argc<2){
printf("Usage: %s <input_file_name>\n",argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if(fp == NULL){
printf("Error opening input file.\n");
return 1;
}
yyin = fp;
yylex();
fclose(fp);
return 0;
}
我遇到的问题是某些输入,例如
90.s3
和 232a3
。 flex 不是像上一条语法规则中那样得到 'UNRECOGNIZED CHARACTER',而是将它们分开。
232a3
变成
INTEGER 232
IDENTIFIER a3
和
90.s3
变成
INTEGER 90
UNRECOGNIZED_CHARACTER .
IDENTIFIER s3
我应该如何阻止这种情况发生?
我应该如何阻止这种情况发生?
有几种选择。其中,
你可以使用带有尾随上下文的模式。例如,此
INTEGER
模式仅在紧跟文件末尾或既不是小数点也不是大写或小写字母的字符时识别整数标记:
[-+]?(([1-9][0-9]*)|0)/([^.A-Za-z]|<<EOF>>)
或者你可以玩有开始条件的游戏.
但是你最好的选择可能是添加一个模式来匹配不需要的标记并标记错误。例子:
[a-zA-Z_][a-zA-Z0-9]* { /* IDENTIFIER */ }
([1-9][0-9]*)|0 { /* INTEGER */ }
[0-9]+[.][0-9]* { /* FLOAT version 1 */ }
[.][0-9]+ { /* FLOAT version 2 */ }
/* Used only if it affords a longer match than any of the above: */
[0-9.][0-9]*[a-zA-Z_.][0-9a-zA-Z_.]* { /* ERROR */ }
请注意,此示例从数字模式中省略了前导
+
和-
。它们将与您现有的 +
和 -
运算符模式相匹配,这正是它们在 C 中的作用。
还请注意,如果您支持
.
作为 C 中的成员选择运算符,则您需要付出更多努力——可能不止一种错误模式。