我对 lex 很陌生,并尝试制作扫描仪。这是我的代码:
定义与规则部分
identifier ([A-Za-z][0-9A-Za-z]*)
digit ([0-9])
integer ({digit}+)
float ({integer}"."[0-9]+)
delimiter ([.,:;()\[\]{}])
arithmetic ([+-*/])
relational ([<>=])
string (\"(\"\"|[^"\n])*\")
commentLine (\%[^\n]*)
commentLeft ({%)
commentRight (%})
%x COMMENT
%option noyywrap
%%
{delimiter;} {tokenChar(yytext[0]);}
{arithmetic;} {tokenChar(yytext[0]);}
{relational;} {tokenChar(yytext[0]);}
"<=" { token('<='); }
">=" { token('>='); }
"not=" { token('not='); }
":=" { token(':='); }
"not" { token('not'); }
"and" { token('and'); }
"or" { token('or'); }
"array" { token(ARRAY); }
"begin" { token(BEGIN); }
"bool" { token(BOOL); }
"char" { token(CHAR); }
"const" { token(CONST); }
"decreasing" { token(DECREASING); }
"default" { token(DEFAULT); }
"do" { token(DO); }
"else" { token(ELSE); }
"end" { token(END); }
"exit" { token(EXIT); }
"false" { token(FALSE); }
"for" { token(FOR); }
"function" { token(FUNCTION); }
"get" { token(GET); }
"if" { token(IF); }
"int" { token(INT); }
"loop" { token(LOOP); }
"of" { token(OF); }
"put" { token(PUT); }
"procedure" { token(PROCEDURE); }
"real" { token(REAL); }
"result" { token(RESULT); }
"return" { token(RETURN); }
"skip" { token(SKIP); }
"string" { token(STRING); }
"then" { token(THEN); }
"true" { token(TRUE); }
"var" { token(VAR); }
"when" { token(WHEN); }
{integer} {
tokenInteger("integer", atoi(yytext));
}
{identifier} {
tokenString("identifier", yytext);
table -> insert(yytext);
}
{float} {
tokenFloat("float", yytext);
}
{string} {
char s[MAX_LINE_LENG] = {0};
int idx = 0;
for (int i = 1; i < yyleng - 1; ++i){
if (yytext[i] == '"')
++i;
s[idx++] = yytext[i];
}
tokenString("string", s);
}
{commentLine} {
LIST;
}
{% {
LIST;
BEGIN(COMMENT);
}
<COMMENT>[^\n] {
LIST;
}
<COMMENT>\n {
LIST;
printf("%d: %s", linenum, buf);
linenum++;
buf[0] = '\0';
}
<COMMENT> {commentRight} {
LIST;
BEGIN(INITIAL);
}
\n {
LIST;
printf("%d: %s", linenum++, buf);
buf[0] = '\0';
}
[ \t]* {
LIST;
}
. {
LIST;
printf("%d:%s\n", linenum+1, buf);
printf("bad character:'%s'\n",yytext);
exit(-1);
}
%%
主要功能:
int main(int argc, char **argv){
FILE *yyin;
if (argc > 0){
yyin = fopen(argv[1], "r");
if (!yyin){
printf("Failed to open file %s\n", argv[1]);
return 1;
}
}
yylex();
fclose(yyin);
return 0;
}
既然还在尝试,应该会有不少失误。然而,当我输入
lex scanner.l
时,它只会说:
scanner.l:209: 无法识别的规则
scanner.l:209: 致命解析错误
第 209 行是规则部分之后的
%%
。我的定义不正确吗?不知道错在哪里。
你的文件中出现了不少新手错误,都是错别字。调试此类问题的最佳方法是从代码中删除行,直到错误消失(可能使用二进制斩波方法)。这样做你会很快准确地找到哪些线路导致了问题。我不会列出你犯的每一个错误,但我可以在几分钟内很容易地在 lex/flex 中完成这项工作。
我发现的错误是:
{delimiter;}
.然而,你犯的最大错误,也是很多学生犯的最大错误,就是试图一次完成所有事情。很差。有经验的软件工程师知道一次只做一件事情。从你的语言的一小部分开始,让它工作,然后添加更多的语句并继续,直到它全部工作。也许从运算符或关键字开始,然后逐步添加其他部分。然后你就知道错误在哪里了。这就是为什么 Stack Overflow 喜欢可重现的小例子而不是整个代码库。