使用 flex 匹配带有转义字符的 Python 多行字符串

Using flex for matching Python multiline strings with escaped characters

我想知道如何将 python 多行注释与 flex 匹配。而且我遇到了一些麻烦,以下在 Regexr 上工作正常,但 flex 无法识别,我不知道如何解决它。

"""[^"\]*(?:(?:\.|"{1,2}(?!"))[^"\]*)*"""

之前,我使用:

["]{3}(\["])*(["]{0,2}[^"](\["])*)*["]{3}

它可以检测像 :

这样的评论
"""A\"""A"""

但是不能处理多个\,比如

'''A\\'''A=B'''C'''

哪个整体认不出来:

'''A\\'''  (comment)   
A=B     
'''C'''(comment) 

您可以使用单个正则表达式识别 Python 长字符串。它不漂亮,但我相信它有效:

["]{3}(["]{0,2}([^\"]|\(.|\n)))*["]{3}

这与您的原始正则表达式非常相似,但它不会尝试将其反斜杠处理限制为 \",因此它可以正确地将 \ 识别为反斜杠字符。

一个可能更容易阅读(但速度稍慢)的解决方案是使用 start 作为开始条件。在这里,我使用 yymore() 创建一个不包含 """ 定界符的标记,但生产代码可能会试图解释 Python 的各种反斜杠转义符。 (正是这种需要激发了开始条件的使用,而不是试图用一个正则表达式来识别整个字符串。)

%x SC_LONGSTRING
%%
["]{3}     BEGIN(SC_LONGSTRING);
<SC_LONGSTRING>{
  [^\"]+  yymore();
  \(.|\n) yymore();
  ["]["]?  yymore();
  ["]{3}   { BEGIN(INITIAL);
             yylval.str = malloc(yyleng - 2);
             memcpy(yylval.str, yytext, yyleng - 3);
             yylval.str[yyleng - 3] = 0;
             return TOKEN_STRING;
           }
}