LEX正则表达式匹配问题:程序结果异常且无法终止求助
LEX正则匹配不符合预期且程序无法终止的问题排查与解决
我用LEX编写正则定义,需要匹配以下模式并输出对应行:
- 匹配以d开头、以t结尾的任意字符串
- 匹配字符串
def - 匹配一个或多个
ab连接的字符串 - 匹配一个或多个不含大写字母A-Z的字符组成的字符串
但程序输出不符合预期,还无法终止。以下是我的C代码:
%{ #include <stdio.h> %} %% def { printf("Matched 'def' string: %s\n", yytext); } d.*t { printf("Matched 'd...t' string: %s\n", yytext); } (ab)+ { printf("Matched 'ab' concatenated: %s\n", yytext); } [^A-Z]+ { printf("Matched string (no uppercase A-Z): %s\n", yytext); } %% int main(int argc, char* argv[]){ printf("Enter the string:\n"); yylex(); // Start lexical analysis return 0; } int yywrap(){ return 1; }
执行后的输出如下:
PS C:\CODE\CST302-Compiler-Principles\Lab3\Q2> flex Q2.l PS C:\CODE\CST302-Compiler-Principles\Lab3\Q2> g++ lex.yy.c PS C:\CODE\CST302-Compiler-Principles\Lab3\Q2> ./a Enter the string: dooot def abc abab ABCd Matched string (no uppercase A-Z): dooot def abc abab ABC abc
问题原因分析
正则匹配规则冲突
LEX遵循最长匹配+先定义先匹配的优先级规则:[^A-Z]+匹配范围过于宽泛,会优先匹配所有不含大写字母的长串(比如dooot def abc abab),导致更具体的def、(ab)+无法触发。d.*t是贪婪匹配,.*会匹配包括换行在内的任意字符,若输入无t则完全不触发,且位置在def之后,会覆盖def的匹配(如果def处于d开头t结尾的串中)。
未匹配字符导致程序无法终止
当输入出现大写字母(如ABCd中的ABC),现有正则无法匹配,LEX会默认将未匹配字符直接输出到标准输出,同时持续等待新输入,导致程序无法自动终止。正则写法不严谨
d.*t未限制单行匹配,会跨多行贪婪匹配,不符合常规的单行匹配需求。
修正方案
调整正则顺序(优先匹配具体模式)、修正正则写法、添加未匹配字符处理规则:
修正后的代码
%{ #include <stdio.h> %} %% // 最具体的模式放在最前面 def { printf("Matched 'def' string: %s\n", yytext); } // 限制单行内d开头t结尾的匹配,避免跨多行 d[^\n]*t { printf("Matched 'd...t' string: %s\n", yytext); } // 匹配连续ab组合 (ab)+ { printf("Matched 'ab' concatenated: %s\n", yytext); } // 匹配不含大写和换行的字符,避免跨多行 [^A-Z\n]+ { printf("Matched string (no uppercase A-Z): %s\n", yytext); } // 处理大写字母串,避免默认输出 [A-Z]+ { printf("Matched uppercase string: %s\n", yytext); } // 单独处理换行,避免被无大写规则匹配 \n { // 可留空或自定义换行处理逻辑 } // 处理单个未匹配的特殊字符 . { printf("Unmatched character: %c\n", *yytext); } %% int main(int argc, char* argv[]){ printf("Enter the string:\n"); yylex(); return 0; } int yywrap(){ return 1; }
修正说明
- 正则优先级调整:将
def、(ab)+等具体模式放在前面,确保优先匹配,避免被宽泛规则覆盖。 - 限制单行匹配:把
d.*t改为d[^\n]*t,[^A-Z]+改为[^A-Z\n]+,避免跨多行匹配。 - 处理未匹配字符:添加
[A-Z]+和.的匹配规则,解决LEX默认输出未匹配字符的问题,同时让程序能处理所有输入类型,输入结束后按Ctrl+Z(Windows)或Ctrl+D(Linux/macOS)即可正常终止。
内容的提问来源于stack exchange,提问作者user27828776
相关产品推荐
相关产品推荐

