我只是想学习 Flex,这里是 Flex 中用于检测标识符和数字的示例代码。我想通过识别错误的标识符和数字模式(例如:1var、12.2.2、5.等)来改进代码。我将如何检测它?我必须在代码中进行哪些更改?
我的示例代码如下:
ID [a-zA-z][a-zA-z0-9]*
DIGIT [0-9]
%%
[\t]+
{ID} {printf("\n identifier found");}
{DIGIT} {printf("\nDigit found");}
. {}
%%
int main(int argc, char *argv[]){
yylex();
}
最佳答案
这不是一个微不足道的问题,因为词法分析器中检测到的错误在很大程度上是语言处理系统的整个设计以及语言的句法和词汇结构的本质的一部分。有些元素经过检查可能看起来像词汇错误,但事实可能并非如此。这实际上取决于语言的性质;例如,在 Fortran 中,空格没有任何意义,有一个著名的例子:
DO 10 I = 1.10
这是关键字DO
、标签10
、标识符I
、运算符=
和数字1.10
?实际上,它是标识符DO10I
...等等;而
DO 10 I = 1,10
有关键字DO
...
因此有时,当看到序列 123abc
时,您不能自动假设它只是一个无效标识符。有时,最好将其作为两个有效标记 NUMBER
和 IDENTIFIER
返回,并将其留给解析器报告由此产生的任何错误。使用此方法时唯一需要注意的困难区域是在 float 常量中指定指数时以及使用整数范围时。指数使用的一个例子是:
-1234.457E+12
它在数字中嵌入了一个字母,需要作为某种 NUMBER
token 返回。类似地,符号运算符的重载会导致词法分析错误检测出现问题。在前面的数字中,它有两个符号 -
和 +
。如果它们被识别为数字的一部分,那么符号 -
和 +
何时被识别为 SUBTRACT
和 ADD
token ?以这个表达式为例:
i=i-1;
这是IDENTIFIER
、EQUALS
、IDENTIFIER
、NUMBER
吗?不,当然不。因此,这意味着我们不能总是假设 -1
只是一个 NUMBER
。
前面提到的整数范围,在许多语言(特别是 Pascal)中表示为 1..8
,使用两个点表示上限和下限,在处理 float 时会造成困难点表达式如 1.2
.
所以,问题是,“我如何在词法分析器中检查格式不正确的标识符和数字?” 内容很丰富,并且表明它可能代表尚未完全吸收该主题的人区域。类似这样的问题经常出现在类测试中,因为它们是教师了解学生是否拥有更深入的语言处理知识,或者只是以表面方式回答它,并尝试为此类对象编写模式的好方法。
正如刚才提到的,天真的答案就是编写正则表达式模式来匹配无效词位的示例。
例如,我可以添加模式:
[0-9]+\.[0-9]+(\.[0-9]+)+ {printf("Bad float: %s\n", yytext);}
[0-9]+[a-zA-Z][a-zA-Z0-9]+ {printf("Bad Identifier: %s\n", yytext);}
但通常大多数编译器都不会这样做。大多数编译器检测到的唯一词法错误是未封闭的字符串和注释。这也是大多数语言不允许在字符串中换行的原因,因为这样可以很容易地检测到未闭合的字符串。
关于compiler-errors - 检查 Flex 中错误的标识符模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30001711/