如何跳过 Flex 中的空格?

How to skip blank spaces in Flex?

我正在使用 flex 为大学作业生成词法分析器。它应该识别整数、浮点数、变量名称和数学运算符。它还应忽略任何空白,如字符,如 " "、"\n"、"\t" 等。首先,我只尝试捕获像这样的空白字符 " " 或更多连接的空白字符。我的规则文件是这样的:

%{
  #include<stdio.h>
%}
%%
[0-9]+ printf("inteiro:%s\n",yytext);
[0-9]+\.[0-9]+ printf("fracionário:%s\n",yytext);
[a-zA-Z][a-zA-z0-9]* printf("variável:%s\n",yytext);
\+|\-|\*|\/|\*\* printf("operador:%s\n",yytext);
\(|\) printf("parênteses:%s\n",yytext);
[[:space:]]|[[:space:]]+;
%%

使用以下输入

12 + 413

它生成此输出:

inteiro:12 operador:+ inteiro:413

我想知道为什么最后一行不能是这样的:

[[:space:]]+;

规则

    [[:space:]]|[[:space:]]+;

有点奇怪。

弹性规则由模式和(可选)操作组成,由白色space分隔。由于 ; 之前没有 space,它是模式的一部分,而不是动作。因此该模式匹配单个白色space字符([[:space:]])或(|)一个或多个白色space字符后跟分号([[:space:]]+;).

由于该规则中没有任何操作,因此该模式将被忽略。 (这是一个 flex 扩展。Lex 要求存在一个动作,即使它什么都不做。)实际上,这意味着您将忽略所有白色 space(一次一个字符)并且您还将忽略分号如果它们前面有 whitespace.

您可能想要的是

    [[:space:]]+     /* sem ação */

(插入注释以使缺少的操作可见是很有用的。)


顺便说一下,字符 classes 通常比一堆倾斜的木材(即一堆反斜杠转义符)更具可读性。此外,flex 允许您使用双引号来引用字符串。

所以不用

    \+|\-|\*|\/|\*\*    /* operador */
    \(|\)               /* parênteses */

你可以写:

    [-+*/]|"**"         /* operador */
    [()]                /* parênteses */

在第一个字符 class 中,将 - 放在字符列表的开头或结尾很重要,这样它就不会被解释定义字符范围。

并且,不要插入您自己的调试 printf 语句,而是在构建扫描仪时考虑使用 -d(调试)选项。这将为您打印出完整的调试信息,让您准确地看到扫描仪正在做什么。