Flex生成词法分析器时规则无法匹配的问题求助
解决Flex规则无法匹配结尾下划线标识符的问题
你的问题出在合法标识符的正则表达式错误地允许了下划线结尾,导致错误规则永远没有触发的机会——Flex会优先用合法标识符规则匹配整个foo_这类字符串,所以编译器警告你的错误规则无法被匹配。
问题根源分析
你原来的identifier规则:
identifier {letter}({letter}|{digit}|\_)*({letter}|{digit})*
这个规则等价于{letter}({letter}|{digit}|_)*,因为后面的({letter}|{digit})*是前面*表达式的子集。这意味着它会匹配任何以字母开头、后面跟任意字母/数字/下划线的字符串,包括foo_这种结尾是下划线的非法标识符。错误规则自然就被跳过了。
修正方案
- 修正合法标识符的规则:确保它只匹配以下字母或数字结尾的标识符,同时支持单个字母的合法情况(比如
a):
letter [A-Za-z] digit [0-9] // 合法标识符:字母开头,可包含字母/数字/下划线,但不能以下划线结尾 identifier {letter}({letter}|{digit}|_)*({letter}|{digit})?
这个规则的逻辑是:
- 必须以字母开头
- 中间可以跟任意数量的字母/数字/下划线
- 结尾必须是字母或数字(或者只有单个字母,此时结尾就是字母本身)
- 简化错误规则:现在合法规则不会匹配结尾下划线的字符串,我们可以用更简洁的规则捕获这类错误,注意要把错误规则放在合法标识符规则之后:
// 捕获以下划线结尾的非法标识符 {letter}({letter}|{digit}|_)*_ { printf("Error at line %d, column %d: identifier \"%s\" cannot end with an underscore.\n", num_lines, num_cols, yytext); exit(1); }
如果你已经定义了character [0-9a-zA-Z_],还可以进一步简化错误规则:
{letter}{character}*_ { // 错误处理代码 }
完整示例片段
letter [A-Za-z] digit [0-9] character [0-9a-zA-Z_] // 合法标识符规则(放在错误规则之前) identifier {letter}({letter}|{digit}|_)*({letter}|{digit})? { // 处理合法标识符的逻辑,比如返回TOKEN_IDENTIFIER } number {digit}+ { // 处理数字的逻辑 } // 错误规则:捕获结尾下划线的非法标识符 {letter}{character}*_ { printf("Error at line %d, column %d: identifier \"%s\" cannot end with an underscore.\n", num_lines, num_cols, yytext); exit(1); }
关键注意事项
- Flex的规则匹配遵循最长匹配优先,且按规则定义的顺序检查,所以一定要把合法标识符规则放在错误规则之前,确保正确的标识符被正常处理,错误的被捕获。
- 单个字母(比如
x)是合法标识符,修正后的规则已经覆盖了这种情况。
内容的提问来源于stack exchange,提问作者Yulin Z.
相关产品推荐
相关产品推荐

