Python库将正则表达式解析为AST?

时间:2015-12-30 05:16:23

标签: python regex parsing

要强调,我不想“使用正则表达式解析” - 我想“将正则表达式解析为符号树”。 (搜索只带来了前者...)

我的用例:为了加快对数据库的正则表达式搜索,我想解析像(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实现后来不会保留结构。关于如何在不编写我的所有者解析器的情况下解析它的任何想法?

2 个答案:

答案 0 :(得分:2)

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

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

这意味着您无法使用正则表达式解析正则表达式(Perl是一个例外, 但随后它的正则表达式#34;超越"经典")。

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

我怀疑这很容易。你自己做起来并不困难;看到 Is there an alternative for flex/bison that is usable on 8-bit embedded systems?用于构建此类解析器的简单方案。

要理解正则表达式的语义(例如,找出"必要的子串"),您可能能够摆脱构建分析器 遍历解析树,并为每个子树(自下而上)计算公共字符串。如果不这样做,您可能必须实施经典的NDFA构造,然后遍历它,或实施NDFA到DFA构造并遍历DFA。真正的正则表达式往往包含许多混乱的复杂功能,如内置字符集,捕获组等。

"常用字符串"可能不仅仅是一个连续的字符序列,尽管你可以狭义地定义它。它可能包括由固定或可变长度的字符间隔分隔的几个常量子串,例如,您的必要子字符串可能总是可以表示为简单的正则表达式"形式:

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

答案 1 :(得分:2)

您也许可以只使用它:

NU, ON, QC, CA, VA, NV, OR