捕获名称(但不以破折号结尾)

时间:2020-03-13 07:43:46

标签: parsing flex-lexer

我正在尝试捕获名称(不是以数字开头)可能包含破折号,例如hello-world。我的问题是,我也有一些与单破折号和符号冲突的规则:

[A-Za-z][A-Za-z0-9-]+     { /* capture "hello-world" */ }
"-"                       { return '-'; }
">"                       { return '>'; }

当词法分析器读取hello-world->时,先前的规则产生hello-world->,而我期望hello-world->单独捕获。为了解决这个问题,我通过以下方式对其进行了修复:

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+     { /* ensure final dash is never included at the end */ }

那行得通,除了单字母单词,所以最后我实现了这一点:

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+     { /* ensure final dash is never included at the end */ }
[A-Za-z][A-Za-z0-9]*                  { /* capture possible single letter words */ }

问题:有没有更优雅的方法?

1 个答案:

答案 0 :(得分:2)

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+
[A-Za-z][A-Za-z0-9]*

请注意,正如您所说,第一个规则已经涵盖了不是单个字母的所有内容。因此,第二条规则仅需匹配单个字母,并且可以缩短为[A-Za-z]

[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]+
[A-Za-z]

现在第二个规则只是第一个规则的前缀,因此我们可以通过将第一个字母后面的部分设为可选来将其组合为一个规则:

[A-Za-z]([A-Za-z0-9-]*[A-Za-z0-9]+)?

最后一位上的+是不必要的,因为除了最后一个字符以外的所有内容都可以由中间部分匹配,因此最简单的版本是:

[A-Za-z]([A-Za-z0-9-]*[A-Za-z0-9])?
相关问题