使用 lex 将输入与字符串匹配

Match the input with string using lex

我正在尝试匹配字符串 Something 的前缀。例如,如果输入So,SOM,SomeTH,some,S,则全部接受,因为它们都是Something的前缀。

我的代码

Ss[oO]|Ss[omOMOmoM] {
        printf("Accept Something": %s\n", yytext);
}

输入

Som

输出

Accept Something: So
Invalid Character

它应该读作 Som 因为它是 Something 的前缀。我不明白为什么我的代码不起作用。谁能纠正我做错了什么?

不知道你怎么看

的意思
Ss[oO]|Ss[omOMOmoM]

是,但它匹配的是:

  • 一个 S 后跟一个 s 紧跟一个字母 oO,或
  • 一个 S 后跟一个 s 后跟一个字母 oOmM。在括号表达式中多次放置一个符号没有任何效果。

另外,我看不出这会如何产生您报告的输出。可能存在复制粘贴错误,或者可能您有其他模式规则。

如果要匹配前缀,请使用嵌套的可选匹配项:

s(o(m(e(t(h(i(ng?)?)?)?)?)?)?)?

如果你想要不区分大小写的矩阵,你可以写出所有字符 类,但这会很麻烦;更简单的是使用不区分大小写的标志:

(?i:s(o(m(e(t(h(i(ng?)?)?)?)?)?)?)?)

(?i: 打开 insensitive 标志,直到匹配右括号。

实际上,这可能不是您想要的。通常,您会希望将一个完整的词识别为标记。然后您可以检查该词是否是规则操作中的前缀:

[[:alpha:]]+    { if (yyleng <= strlen("something") && 0 == strncasemp(yytext, "something", yyleng) { 
                  /* do something */
                  } 
                }

Flex manual中有很多信息。

现在您的代码(如图所示)应该只匹配 "Sso" 或 "SsO" 或 "Ssm" 或 "SsM".

您有两个备选方案,每个备选方案均以 Ss(不带方括号)开头,因此它们将按字面意思匹配。其后跟 [oO][omOMomoM],但方括号中的字符代表备选方案,因此等同于 [oOmM] —— 即 o 的任何一个字符,OmM.

我将从以下内容开始:%option caseless 使其成为不区分大小写的扫描仪,因此您不必列出每个字母的大写和小写等价物。

那么按字面列出备选方案可能是最简单的方法:

s|so|som|some|somet|someth|somethi|somethin|something { printf("found prefix"); }

我想你可以通过按以下顺序做一些事情来使模式更短一些(至少在源代码中):

s(o(m(e(t(h(i(n(n(g)?)?)?)?)?)?)?)?)? { printf("found prefix"); }

对我来说这似乎不是一个巨大的进步,但有些人可能会觉得它比我更有吸引力。

如果您不想使用 %option caseless 基本思想有更多帮助:

[sS]([oO]([mM]([eE]([tT]([hH]([iI]([nN]([gG])?)?)?)?)?)?)?)? { printf("found prefix"); }

列出每种可能的大小写组合会很乏味。