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

时间:2018-10-02 04:39:00

标签: flex-lexer lex

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

我的代码

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

输入

Som

输出

Accept Something: So
Invalid Character

假设阅读 Som ,因为它是 Something 的前缀。我不明白为什么我的代码不起作用。有人可以纠正我在做错什么吗?

2 个答案:

答案 0 :(得分:2)

我不知道你怎么看待

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:开启i nsensitive标志,直到匹配的右括号为止。

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

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

Flex manual中有很多信息。

答案 1 :(得分:2)

现在,您的代码(如图所示)应仅与“ Sso”或“ SsO”或“ Ssm”或“ SsM”匹配。

您有两种选择,每种选择都以Ss开头(不带方括号),因此它们将按字面值进行匹配。其后跟着[oO][omOMomoM],但是方括号中的字符代表替代项,因此等效于[oOmM],即o,{ {1}},Om

我将以M开始,使其成为不区分大小写的扫描器,因此您不必列出每个字母的大小写等效项。

那么可能最简单的是按字面意思列出替代方案:

%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

列出大写和小写的所有可能组合会很乏味。