mil*_*ose 5 compiler-construction parsing lex lexer
我正在学习编译器构建课程,目前的任务是为我们正在实现的语言编写词法分析器.我无法弄清楚如何满足词法分析器必须识别连接标记的要求.也就是说,令牌没有被空格分隔.例如:字符串39if
应该被识别为数字39
和关键字if
.同时,词法分析器也必须exit(1)
在遇到无效输入时.
我的代码的简化版本:
%{
#include <stdio.h>
%}
%option main warn debug
%%
if |
then |
else printf("keyword: %s\n", yytext);
[[:digit:]]+ printf("number: %s\n", yytext);
[[:alpha:]][[:alnum:]]* printf("identifier: %s\n", yytext);
[[:space:]]+ // skip whitespace
[[:^space:]]+ { printf("ERROR: %s\n", yytext); exit(1); }
%%
Run Code Online (Sandbox Code Playgroud)
当我运行它(或我的完整版本),并将输入传递给它时39if
,错误规则匹配,输出是ERROR: 39if
,当我希望它是:
number: 39
keyword: if
Run Code Online (Sandbox Code Playgroud)
(就像我输入的39 if
那样.)
通过手册,我有一个预感,原因是错误规则匹配比数字和关键字规则更长的输入,而flex会更喜欢它.那就是说,我不知道如何解决这种情况.编写一个拒绝所有非错误输入的显式正则表达似乎是不可行的,我不知道如何为了处理词法错误而编写"全能"规则.
更新:我想我可以制定全能规则,. { exit(1); }
但我希望获得一些比"我在第1行上感到困惑"更好的调试输出.
你说得很对,你应该只匹配一个“任何”字符作为后备。获取有关解析所在行的信息的“标准”方法是使用该--bison-bridge
选项,但这可能有点麻烦,特别是如果您不使用bison
. 还有很多其他方法——例如,在手册中查找指定您自己的 i/o 函数的方法——但恕我直言,最简单的方法是使用启动条件:
%x LEXING_ERROR
%%
// all your rules; the following *must* be at the end
. { BEGIN(LEXING_ERROR); yyless(1); }
<LEXING_ERROR>.+ { fprintf(stderr,
"Invalid character '%c' found at line %d,"
" just before '%s'\n",
*yytext, yylineno, yytext+1);
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
注意:确保您忽略了规则中的空格。该模式.+
匹配任何数字,但至少有一个非换行符,或者换句话说,直到当前行的末尾(它将强制 flex 读取那么远,这应该不是问题)。yyless(n)
按字符备份读取指针n
,因此在.
规则匹配后,它将重新扫描该字符,产生(希望)一条半合理的错误消息。(如果您的输入是多字节,或者具有奇怪的控制字符,这实际上是不合理的,因此您可以编写更仔细的代码。由您决定。如果错误位于行尾,也可能不合理,所以您可能还想编写一个更仔细的正则表达式,它可以获得更多上下文,甚至可能限制读取的前向字符数。这里有很多选项。)
在 Flex 手册中查找启动条件%x
以获取有关和的更多信息BEGIN
归档时间: |
|
查看次数: |
6186 次 |
最近记录: |