【问题标题】:Using flex for matching Python multiline strings with escaped characters使用 flex 匹配带有转义字符的 Python 多行字符串
【发布时间】:2017-10-30 13:55:40
【问题描述】:

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

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

以前,我用过:

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

它可以检测出像这样的cmets:

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

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

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

它作为一个整体不承认:

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

【问题讨论】:

标签: python regex flex-lexer lex


【解决方案1】:

您可以使用单个正则表达式识别 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;
           }
}

【讨论】:

  • 我用 unicode 字符支持更新了你的正则表达式,请你检查一下吗? UCN (\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}) 然后["]{3}(["]{0,2}([^\\"]|\\(.|\n)|{UCN}))*["]{3}
  • @linrongbin:正则表达式已经处理转义码,UCN 没有什么特别之处,这使得转义处理更加复杂。它不尝试做的是解释转义码;这在正则表达式中是不可能的,尽管它在开始条件模型中是直截了当的。尝试在正则表达式中验证 UCN 会产生比它解决的问题更多的问题。您如何处理无效的 UCN(同样,使用无效的十六进制或字母转义)?你不能在那个时候停止识别文字,这就是你的修改会做的事情。
猜你喜欢
  • 1970-01-01
  • 2019-09-12
  • 2013-06-22
  • 2020-10-03
  • 2012-06-19
  • 2019-06-26
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
相关资源
最近更新 更多