使用flex将Python多行字符串与转义字符进行匹配

时间:2017-10-30 13:55:40

标签: python regex flex-lexer lex

我想知道如何将python多行评论与flex相匹配。我遇到了一些麻烦,以下在Regexr上工作正常,但没有被flex识别,我不知道如何修复它。

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

以前,我用过:

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

可以检测如下评论:

"""A\"""A"""

然而,它无法处理多个\,如

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

总体上认为它不是:

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

1 个答案:

答案 0 :(得分:0)

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

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

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

可能更容易阅读(但稍微慢一些)的解决方案是使用启动开始条件。在这里,我使用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;
           }
}