and*_*pcg 2 regex cygwin expression flex-lexer
我在使用 flex 设置正则表达式来匹配类似 C 的文字字符时遇到了一些问题。
我需要匹配根据语法正确的文字字符和不正确的文字字符,例如未终止的字符文字。
2 条规则,一条为正确规则,另一条为未终止规则。
chrlit (\')([^\\\'\n]|(\\.))(\')
untermchrlit (\')([\\|\']|(.))*
Run Code Online (Sandbox Code Playgroud)
我需要有关正则表达式的帮助,因为它们无法按照我的需要工作。以下是它们应该如何工作的一些示例:
' -> 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')
Run Code Online (Sandbox Code Playgroud)
问题是,未终止的字符文字的模式也将匹配终止的字符以及任何后续字符,除非字符文字位于行的末尾。您可以像这样让自己的生活变得更简单,而不是尝试精确匹配未终止的字符文字,untermchrlit如果遇到一个'which不是a的开头,则返回到chrlit。(因此,如果chrlit匹配所有可能的终止文字,它必须是未终止的。)(我还冒昧地从正则表达式中删除了所有多余的括号和反斜杠,这使得它们阅读起来不那么嘈杂。)
chrlit '([^'\\\n]|\\.)'
untermchrlit '
Run Code Online (Sandbox Code Playgroud)
该解决方案的唯一问题是,它将在未终止后立即继续扫描',这很可能会产生人为错误,特别是在确实存在匹配的情况下',如 中所示'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]|\\.)+'
Run Code Online (Sandbox Code Playgroud)
我应该注意,longchrlit这里也匹配所有chrlit匹配的内容,但与OP中的模式不同,它不匹配任何更多字符。重要的是,按照注释指示的顺序对操作进行排序,以便正确的文字将由 匹配chrlit。(不过,如果顺序错误,flex 应该发出警告。)
请记住,Flex 始终匹配最长的匹配项,但如果多个规则与完全相同的标记匹配,Flex 将选择第一个操作。
顺便说一句,至少在 C 语言中,以下是有效的字符文字:
'a\
'
Run Code Online (Sandbox Code Playgroud)
这是因为\紧随其后的换行符已从输入中完全删除,因此第二个'词法分析就像它紧随a.