【问题标题】:Python library to parse regex into AST?将正则表达式解析为 AST 的 Python 库?
【发布时间】:2016-04-04 01:29:30
【问题描述】:

强调一下,我不想“使用正则表达式解析”——我想“将正则表达式解析为符号树”。 (搜索只找到了前者……)

我的用例:为了加快对数据库的正则表达式搜索,我想解析像 (foo|bar)baz+(bat)* 这样的正则表达式并提取所有必须出现在匹配项中的子字符串。 (在这种情况下,它只是baz,因为 foo/bar 是交替出现的,而 bat 可以出现 0 次。)

为此,我需要对正则表达式运算符/语义有所了解。 re.DEBUG 最接近:

In [7]: re.compile('(foo|bar)baz+(bat)', re.DEBUG)
subpattern 1
  branch
    literal 102
    literal 111
    literal 111
  or
    literal 98
    literal 97
    literal 114
literal 98
literal 97
max_repeat 1 4294967295
  literal 122
subpattern 2
  literal 98
  literal 97
  literal 116

但是,它只是打印出来,据我所知,c 实现并没有保留之后的结构。关于如何在不编写所有者解析器的情况下解析它的任何想法?

【问题讨论】:

  • 如何在正则模式上使用正则表达式?
  • @DanielSanchez 你不能用正则表达式解析正则表达式。
  • @BlackJack,你可以对正则表达式字符串进行正则表达式,我的意思是如果我的正则表达式有“1|2”,你可以正则表达式那个字符串。
  • @DanielSanchez 您可以对1|2 执行此操作,但不能对任意正则表达式执行此操作。您不能像问题所问的那样将正则表达式转换为符号树,您需要一个用于上下文无关语法的解析器,就像 Ira Baxter 的回答所解释的那样。

标签: python regex parsing


【解决方案1】:

你可以只用这个:

import sre_parse
sre_parse.parse(r'(\d+)foo(.*)')

【讨论】:

    【解决方案2】:

    您只能使用上下文无关语法指定(经典)正则表达式:

     regex = { alternatives };
     alternatives =  primitive { '|' alternatives } ;
     primitive = '(' regex ')' | '[' character_set ']' | ...
    

    这意味着您不能使用正则表达式解析正则表达式(Perl 是一个例外, 但随后它的“正则表达式”超出了“经典”的范围)。

    因此,要解析正则表达式,您需要构建自己的解析器并构建某种树(re.Debug 非常接近)或您希望的魔法库。

    我怀疑这是最简单的部分。自己做这件事并不难。看 Is there an alternative for flex/bison that is usable on 8-bit embedded systems? 用于构建此类解析器的简单方案。

    要了解正则表达式的语义(例如,找出“必要的子字符串”),您或许可以轻松构建分析器 遍历解析树,并为每个子树(自下而上)计算公共字符串。如果失败,您可能必须执行经典的 NDFA 构造然后遍历它,或者执行 NDFA 到 DFA 构造并遍历 DFA。真正的正则表达式往往包含很多杂乱无章的复杂情况,例如内置字符集、捕获组等。

    “公共字符串”可能不仅仅是一个连续的字符序列,尽管您可以将其狭义地定义为这样。它可能包括几个由固定或可变长度的字符间隔分隔的常量子字符串,例如,您所需的子字符串本身可能总是可以表达为以下形式的“简单正则表达式”:

       (<character>+ ?+) <character>+
    

    【讨论】:

    • 是的,我希望有一些正则表达式库可以让我遍历 NDFA 或解析树;我已经使用过几次 ANTLR 之类的东西,一点也不错过...... re:“简单的正则表达式”,你用(ab+)* 之类的例子遇到了复杂性,在这些例子的末尾没有必需的子字符串那天。无论如何,感谢您的观点,这很有用(尽管会保持问题开放,以防有人有想法让我免于解析自己)
    猜你喜欢
    • 2013-01-05
    • 2010-10-23
    • 2011-06-05
    • 2012-09-12
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 2014-08-12
    相关资源
    最近更新 更多