字符串文字的正确弹性模式是(转义序列见下文):
\"(\\(.|\n)|[^\\"\n])*\"
这与您的模式不同,因为它允许在转义字符后换行(从技术上讲,这是一个拼接,而不是字符串文字 [注 1] 语法的一部分),否则禁止换行。这必须明确完成,因为[^...]包括换行符,除非\n是要拒绝的字符列表的一部分。仅.隐式禁止换行符。
要匹配不正确的字符串文字,您只需要没有终止符的相同模式":
\"(\\(.|\n)|[^\\"\n])*
您不必担心模式匹配正确的字符串文字,因为 flex 总是选择最长的匹配,并且与终止引号的匹配保证更长。
如果您想更准确地了解转义字符,则需要以下内容:
\"(\\([abfnrtv'"?\\\n]|[0-7]{1,3}|x[[:xdigit:]]+|u[[:xdigit:]]{4}|U[[:xdigit:]]{8})|[^\\"\n])*\"
您可以使用相同的技术来匹配错误,但您可能想要区分未终止的引号错误和无效的转义错误,您可以使用两种错误模式来做到这一点:
\"(\\([abfnrtv'"?\\\n]|[0-7]{1,3}|x[[:xdigit:]]+|u[[:xdigit:]]{4}|U[[:xdigit:]]{8})|[^\\"\n])*\" { /* Valid string */ }
\"(\\([abfnrtv'"?\\\n]|[0-7]{1,3}|x[[:xdigit:]]+|u[[:xdigit:]]{4}|U[[:xdigit:]]{8})|[^\\"\n])*/\\ { /* Invalid escape sequence */ }
\"(\\([abfnrtv'"?\\\n]|[0-7]{1,3}|x[[:xdigit:]]+|u[[:xdigit:]]{4}|U[[:xdigit:]]{8})|[^\\"\n])* { /* Missing terminating quote */ }
笔记
“拼接”是行尾的反斜杠。您通常只在长宏的定义中看到这些,但 C 允许在任何地方进行拼接:反斜杠和以下换行符只是从程序文本中删除,因此拼接甚至可以放在标识符或多字符运算符的中间。(但不要那样做!)
使用拼接在多行上继续字符串不是好的风格;最好使用字符串连接。但是 C 标准确实允许这样做。
但是,在标记化开始之前会删除拼接,这意味着您不能在行尾使用反斜杠转义反斜杠:
"This is a string literal which includes a \\
t tab, with a splice in the middle of the escape."
请不要在生产代码中使用它:-)