2

我在使用 flex 设置正则表达式以匹配类似 C 的文字字符时遇到了一些麻烦。

我需要根据语法匹配正确的文字字符和不正确的字符,例如未终止的字符文字。

2条规则,一条用于正确的,一条用于未终止的。

chrlit          (\')([^\\\'\n]|(\\.))(\')
untermchrlit    (\')([\\|\']|(.))*

我需要正则表达式方面的帮助,因为它们没有按照我的需要工作。以下是它们应该如何工作的一些示例:

'          -> unterminated char constant
'/'        -> CHRLIT('/')
'('        -> CHRLIT('(')
'a"b"c"de  -> unterminated char constant
'abc       -> unterminated char constant
'abc\      -> unterminated char constant
'\\'       -> CHRLIT('\\')
';'        -> CHRLIT(';')
''         -> unterminated char constant
'a'        -> CHRLIT('a')
'\'        -> unterminated char constant 
'\;'       -> CHRLIT('\;')
'\\\'      -> unterminated char constant
'\\\       -> unterminated char constant    
'\/'       -> CHRLIT('\/')
'a\'       -> unterminated char constant
'\\        -> unterminated char constant
'\t'       -> CHRLIT('\t')
4

1 回答 1

4

问题是您的未终止字符文字的模式也将匹配终止的字符以及任何后续字符,除非字符文字位于行尾。与其尝试精确匹配未终止的字符文字,您可以像这样让自己的生活更简单,untermchrlit如果遇到'不是 a 开头的 a ,则回退到chrlit。(所以它必须是未终止的,如果chrlit匹配所有可能的终止文字。)(我还冒昧地从您的正则表达式中删除了所有多余的括号和反斜杠,这使得它们阅读起来不那么嘈杂。)

chrlit          '([^'\\\n]|\\.)'
untermchrlit    '

此解决方案的唯一问题是它会在未终止的 之后立即继续扫描',这很可能会产生人为错误,特别是在确实存在匹配的情况下',例如'too long'. 在这里,您真的想在第二个之后继续进行词法扫描'(实际上,您可能希望将其标记为过长的字符文字而不是未终止的文字)。要处理这种情况,您需要一组更复杂的模式。以下是可能性:

/* As before */
chrlit          '([^'\\\n]|\\.)'
/* Also as before, a catch-all case. */
untermchrlit    '
/* Try to match single-quoted strings which are too short or too long */
emptychrlit     ''
/* The action for this regex *must* come after the action for chrlit */
longchrlit      '([^'\\\n]|\\.)+'

我应该注意,longchrlit这里也匹配所有chrlit匹配的内容,但与 OP 中的模式不同,它不再匹配任何字符。重要的是按照注释指示对操作进行排序,以便正确的文字将与chrlit. (如果你弄错了顺序,flex 应该会发出警告。)

请记住,Flex 始终匹配最长的匹配项,但如果多个规则与完全相同的标记匹配,Flex 会选择第一个操作。

顺便说一句,至少在 C 中,以下有效的字符文字:

'a\
'

那是因为\紧随其后的换行符完全从输入中删除,因此第二个'被词法分析,就好像它紧随a.

于 2013-03-22T00:38:56.007 回答