如何在Flex中匹配独立关键词,避免捕获子字符串?
解决Flex词法分析器中独立关键词匹配问题
问题原因
你之前添加的边界匹配规则之所以没有输出,是因为它把关键词前后的非单词字符(比如空格、标点)也纳入了匹配范围,导致yytext包含的不是纯关键词;同时这种规则很容易和其他规则(比如标识符、空白字符规则)产生冲突,或者因为输入中没有恰好符合「非单词字符+关键词+非单词字符」的组合而匹配失败。
正确解决方案
Flex内置了专门的单词边界断言:\<表示单词的起始位置(前面不是字母、数字或下划线,后面是),\>表示单词的结束位置(前面是字母、数字或下划线,后面不是)。用它们包裹关键词,就能确保只匹配独立的单词:
(?i:\<if\>|\<else\>|\<while\>|\<class\>|\<fi\>|\<in\>|\<inherits\>|\<isvoid\>|\<let\>|\<loop\>|\<pool\>|\<then\>|\<case\>|\<esac\>|\<new\>|\<of\>|\<not\>) { printf("Keyword: %s\n", yytext); }
这样配置后,in只会被匹配为独立单词,不会匹配sins或inline中的子串。
另一种手动实现方式(不推荐)
如果你不想使用内置边界,也可以通过否定后顾和前瞻实现,但需要额外处理捕获组提取关键词,操作繁琐:
(?i:(^|[^a-zA-Z0-9_])(if|else|while|class|fi|in|inherits|isvoid|let|loop|pool|then|case|esac|new|of|not)(?=[^a-zA-Z0-9_]|$)) { // 提取纯关键词:若前面是行首则直接取,否则跳过第一个非单词字符 char* keyword = yytext; if (*keyword != '\n' && !isalnum(*keyword) && *keyword != '_') { keyword++; } // 计算关键词长度,排除末尾可能的非单词字符(仅当不是行尾时) int len = yyleng - (keyword - yytext); if (*(keyword + len - 1) != '\0' && !isalnum(*(keyword + len - 1)) && *(keyword + len - 1) != '_') { len--; } printf("Keyword: %.*s\n", len, keyword); }
这种方法需要处理多种边界情况,远不如内置的\</\>简洁可靠,因此优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者Abdelrahman Adel
相关产品推荐
相关产品推荐

