Flex/Lex匹配含重复大写字母的2-8位字符串遇编译问题求助
问题分析与解决
代码编译错误原因
你的Flex代码存在几个关键语法问题,导致编译报错或卡住:
- 不支持Perl风格大小写不敏感语法:Flex原生不支持
(?i:...)这种PCRE风格正则,要实现大小写不匹配,需添加%option caseless选项,而非在宏定义里写(?i:...)。 - 宏定义拼写错误:
hexagon (?i:pehagon)里的pehagon是笔误,应为hexagon。 - 正则语法冗余:第24行正则末尾的
\n属于多余字符,Flex规则匹配输入流内容,换行符会被单独处理,无需写在正则中。 - 规则顺序不合理:Flex遵循「最长匹配+顺序优先」原则,错误提示规则应放在正确匹配规则之前,否则会被后面的通用规则覆盖。
修复后的代码
%option caseless %{ %} /* 几何实体宏定义 */ point point line line triangle triangle square square pentagon pentagon hexagon hexagon heptagon heptagon octagon octagon %% /* 错误:只输入几何实体,未输入名称 */ ^[ \t]*({point}|{line}|{triangle}|{square}|{pentagon}|{hexagon}|{heptagon}|{octagon})[ \t]*$ printf("你忘记输入几何实体的名称了,比如 triangle ABC,请重试。\n\n"); /* 错误:只输入名称,未输入几何实体 */ ^[ \t]*[A-Z]{1,8}[ \t]*$ printf("你忘记输入几何实体类型了,比如 triangle,请重试。\n\n"); /* 错误:名称包含小写字母 */ ^[ \t]*({point}|{line}|{triangle}|{square}|{pentagon}|{hexagon}|{heptagon}|{octagon})[ \t]*[a-z]+[ \t]*$ printf("几何实体名称只能用大写字母,请使用A-Z的字符重试。\n\n"); /* 错误:名称长度不符合对应实体要求 */ {point}[ \t]*[A-Z]{2,}|{line}[ \t]*[A-Z]{1}|{line}[ \t]*[A-Z]{3,}|{triangle}[ \t]*[A-Z]{1,2}|{triangle}[ \t]*[A-Z]{4,}|{square}[ \t]*[A-Z]{1,3}|{square}[ \t]*[A-Z]{5,}|{pentagon}[ \t]*[A-Z]{1,4}|{pentagon}[ \t]*[A-Z]{6,}|{hexagon}[ \t]*[A-Z]{1,5}|{hexagon}[ \t]*[A-Z]{7,}|{heptagon}[ \t]*[A-Z]{1,6}|{heptagon}[ \t]*[A-Z]{8,}|{octagon}[ \t]*[A-Z]{1,7}|{octagon}[ \t]*[A-Z]{9,} printf("几何实体名称无效,请重试。\n\n"); /* 错误:名称包含重复字母 */ ([A-Z]*A[A-Z]*A[A-Z]*)|([A-Z]*B[A-Z]*B[A-Z]*)|([A-Z]*C[A-Z]*C[A-Z]*)|([A-Z]*D[A-Z]*D[A-Z]*)|([A-Z]*E[A-Z]*E[A-Z]*)|([A-Z]*F[A-Z]*F[A-Z]*)|([A-Z]*G[A-Z]*G[A-Z]*)|([A-Z]*H[A-Z]*H[A-Z]*)|([A-Z]*I[A-Z]*I[A-Z]*)|([A-Z]*J[A-Z]*J[A-Z]*)|([A-Z]*K[A-Z]*K[A-Z]*)|([A-Z]*L[A-Z]*L[A-Z]*)|([A-Z]*M[A-Z]*M[A-Z]*)|([A-Z]*N[A-Z]*N[A-Z]*)|([A-Z]*O[A-Z]*O[A-Z]*)|([A-Z]*P[A-Z]*P[A-Z]*)|([A-Z]*Q[A-Z]*Q[A-Z]*)|([A-Z]*R[A-Z]*R[A-Z]*)|([A-Z]*S[A-Z]*S[A-Z]*)|([A-Z]*T[A-Z]*T[A-Z]*)|([A-Z]*U[A-Z]*U[A-Z]*)|([A-Z]*V[A-Z]*V[A-Z]*)|([A-Z]*W[A-Z]*W[A-Z]*)|([A-Z]*X[A-Z]*X[A-Z]*)|([A-Z]*Y[A-Z]*Y[A-Z]*)|([A-Z]*Z[A-Z]*Z[A-Z]*) printf("哦!你输入了重复的字母,请重试:%s\n", yytext); /* 正确:匹配几何实体 */ {point}|{line}|{triangle}|{square}|{pentagon}|{hexagon}|{heptagon}|{octagon} printf("---> %s: 是几何实体。\n", yytext); /* 正确:匹配几何实体名称(长度1-8的大写字母) */ [A-Z]{1,8} printf("---> %s: 是几何实体的名称。\n\n", yytext); /* 忽略空白字符 */ [ \t\n]+ /* 匹配其他所有字符 */ .+ %% int main(){ yylex(); return 0; }
匹配长度2-8且包含重复[A-Z]字母的字符串
由于Flex不支持正向预查等高级正则特性,最直接的方式是枚举每个大写字母的重复场景,确保整体长度在2-8之间——上面修复后的代码已经通过([A-Z]*X[A-Z]*X[A-Z]*)的形式实现了这一点,枚举A到Z每个字母的重复情况,覆盖所有含至少一个重复大写字母、长度2-8的字符串。
如果觉得枚举太冗长,也可以在匹配到长度2-8的大写字母串后,用代码检查重复字符:
[A-Z]{2,8} { int seen[26] = {0}; int has_duplicate = 0; for (int i = 0; yytext[i]; i++) { int idx = yytext[i] - 'A'; if (seen[idx]) { has_duplicate = 1; break; } seen[idx] = 1; } if (has_duplicate) { printf("匹配到含重复字母的字符串:%s\n", yytext); } }
内容的提问来源于stack exchange,提问作者Vaggelis Manousakis
相关产品推荐
相关产品推荐

