对包含连字符和斜杠的字母数字字符串进行积极前瞻断言的 Flex 词法分析器规则
Flex lexer rule with positive lookahead assertion on alphanumeric strings containing hyphens and slashes
我在为某种类型的令牌构建具有正面前瞻断言的 flex lexer 规则时遇到了一些麻烦,需要一些帮助。我确定我在这里遗漏了一些简单的东西。
我要匹配的令牌字符串如下所示:
33-abc-13/12
99-ab-33
o3sehh04/00
glu6-840d/00
vm-22hd
xyz-3
要匹配的令牌对象是一个包含 letters and digits
的字符串,并且有 slashes and/or hyphens
,极少数情况 a dot
,可能类似于 xx-3006/10.00
不能匹配的(因为其他规则涵盖这些情况)是以下标记:
numeric370
hyphen-term
plainterm
00/40
到目前为止,我尝试过的是这条具有前瞻性的规则:
([a-z0-9/-]*)/[-/]+[0-9/-]+
通过以上,我得到的结果接近我想要达到的结果。它匹配上面列出的所有这些字符串,但会跳过最后一个字符或数字。匹配的标记如下所示:
33-abc-13/1
o3sehh04/0
...
不幸的是,该规则也匹配 00/40
(导致 00/4
)。
所以我的问题是我在这里想念什么?如果可能并且速度足够快,最好用一个规则来涵盖这些情况。我知道词法分析器脚本中处理规则的顺序,因此该规则的位置将是整个集合中的第一个。
如果不可能,也许打破该规则是另一种方法。
在这个项目中,我使用了 RE-flex 包 (https://github.com/Genivia/RE-flex),因为它涵盖了 flex lexer 接口并提供了 unicode(我需要使用 wchar_t
字符串)。
我的词法分析器是一个带有标记分类的空白标记器,它基本上是在几年前构建在 flex 2.5 包上的。我在令牌处理中重构了一些东西,并转向 re-flex,因为它为我提供了更多机会。 tokenizer 输入字符串是简短的简单文本片段,它们的长度不超过 250-300 个字符。背景介绍到此为止。
注意:在为词法分析器转换规则之前,我在构建规则时使用 regex101.com 到 check/experiment。它有助于找到正确的方向,但仅此而已。
非常感谢任何帮助,感谢您提前的努力!
更新:
根据 rici 的回答,最终模式现在看起来像这样:
[a-z0-9/.-]*[/.-][0-9/-]+
这也包括现在包含 .
的标记,例如
xx33-4.00
f/44-7.87
...
考虑到我下面评论中的句子分隔符问题很简单
模式的最后一个字符组中的 .
。我删除了它,现在它按预期工作了。
我对 RE-flex 一无所知(虽然它看起来很酷)但假设它确实与 flex 兼容,同样的方法应该有效:忘记前瞻性断言(因为匹配的字符串将 not 包含前瞻模式,并且您想匹配整个字符串)并将规则 放在 所有其他可能匹配相同内容的规则之后。
弹性规则是:
- 匹配时间最长的模式获胜,但是
- 如果两个或多个模式都匹配最长的匹配项,则文件中的第一个模式获胜。
例如,假设您有以下模式:
[0-9]+("/"[0-9]+)* { return SLASHED_NUMBERS; }
[a-z0-9/-]*[/-][0-9/-]+ { return GENERAL_TOKEN; }
[注1]
两者都将匹配 00/40
,因此如果这是输入点的标记,则该标记将被检测为 SLASHED_NUMBERS
(文件中的第一个规则)。另一方面,如果您有 00/49-23
,它将被检测为 GENERAL_TOKEN
,因为该规则匹配了更多字符。
备注
- 我基于你的正则表达式。我不明白“罕见的情况下一个点”,它似乎没有反映在你的模式中;此外,您的模式似乎比“字母、数字、连字符和斜杠”更具体,但我不确定具体是什么。
我在为某种类型的令牌构建具有正面前瞻断言的 flex lexer 规则时遇到了一些麻烦,需要一些帮助。我确定我在这里遗漏了一些简单的东西。
我要匹配的令牌字符串如下所示:
33-abc-13/12
99-ab-33
o3sehh04/00
glu6-840d/00
vm-22hd
xyz-3
要匹配的令牌对象是一个包含 letters and digits
的字符串,并且有 slashes and/or hyphens
,极少数情况 a dot
,可能类似于 xx-3006/10.00
不能匹配的(因为其他规则涵盖这些情况)是以下标记:
numeric370
hyphen-term
plainterm
00/40
到目前为止,我尝试过的是这条具有前瞻性的规则:
([a-z0-9/-]*)/[-/]+[0-9/-]+
通过以上,我得到的结果接近我想要达到的结果。它匹配上面列出的所有这些字符串,但会跳过最后一个字符或数字。匹配的标记如下所示:
33-abc-13/1
o3sehh04/0
...
不幸的是,该规则也匹配 00/40
(导致 00/4
)。
所以我的问题是我在这里想念什么?如果可能并且速度足够快,最好用一个规则来涵盖这些情况。我知道词法分析器脚本中处理规则的顺序,因此该规则的位置将是整个集合中的第一个。 如果不可能,也许打破该规则是另一种方法。
在这个项目中,我使用了 RE-flex 包 (https://github.com/Genivia/RE-flex),因为它涵盖了 flex lexer 接口并提供了 unicode(我需要使用 wchar_t
字符串)。
我的词法分析器是一个带有标记分类的空白标记器,它基本上是在几年前构建在 flex 2.5 包上的。我在令牌处理中重构了一些东西,并转向 re-flex,因为它为我提供了更多机会。 tokenizer 输入字符串是简短的简单文本片段,它们的长度不超过 250-300 个字符。背景介绍到此为止。
注意:在为词法分析器转换规则之前,我在构建规则时使用 regex101.com 到 check/experiment。它有助于找到正确的方向,但仅此而已。
非常感谢任何帮助,感谢您提前的努力!
更新: 根据 rici 的回答,最终模式现在看起来像这样:
[a-z0-9/.-]*[/.-][0-9/-]+
这也包括现在包含 .
的标记,例如
xx33-4.00
f/44-7.87
...
考虑到我下面评论中的句子分隔符问题很简单
模式的最后一个字符组中的 .
。我删除了它,现在它按预期工作了。
我对 RE-flex 一无所知(虽然它看起来很酷)但假设它确实与 flex 兼容,同样的方法应该有效:忘记前瞻性断言(因为匹配的字符串将 not 包含前瞻模式,并且您想匹配整个字符串)并将规则 放在 所有其他可能匹配相同内容的规则之后。
弹性规则是:
- 匹配时间最长的模式获胜,但是
- 如果两个或多个模式都匹配最长的匹配项,则文件中的第一个模式获胜。
例如,假设您有以下模式:
[0-9]+("/"[0-9]+)* { return SLASHED_NUMBERS; }
[a-z0-9/-]*[/-][0-9/-]+ { return GENERAL_TOKEN; }
[注1]
两者都将匹配 00/40
,因此如果这是输入点的标记,则该标记将被检测为 SLASHED_NUMBERS
(文件中的第一个规则)。另一方面,如果您有 00/49-23
,它将被检测为 GENERAL_TOKEN
,因为该规则匹配了更多字符。
备注
- 我基于你的正则表达式。我不明白“罕见的情况下一个点”,它似乎没有反映在你的模式中;此外,您的模式似乎比“字母、数字、连字符和斜杠”更具体,但我不确定具体是什么。